gplx/mediawiki/extensions/SemanticMediaWiki/includes/querypages/QueryPage.php

258 lines
6.0 KiB
PHP

<?php
namespace SMW;
use MediaWiki\Html\Html;
use MediaWiki\Linker\Linker;
use MediaWiki\SpecialPage\QueryPage as MWQueryPage;
use MediaWiki\Xml\Xml;
use SMW\MediaWiki\MessageBuilder;
/**
* An abstract query page base class that supports array-based
* data retrieval instead of the SQL-based access used by MW.
*
*
* @license GPL-2.0-or-later
* @since ??
*
* @author Markus Krötzsch
*/
/**
* Abstract base class for SMW's variant of the MW QueryPage.
* Subclasses must implement getResults() and formatResult(), as
* well as some other standard functions of QueryPage.
*
* @ingroup SMW
* @ingroup QueryPage
*/
abstract class QueryPage extends MWQueryPage {
/** @var MessageFormatter */
protected $msgFormatter;
/** @var Linker */
protected $linker = null;
/** @var array */
protected $selectOptions = [];
/** @var array */
protected $useSerchForm = false;
/**
* Implemented by subclasses to provide concrete functions.
*/
abstract function getResults( $requestoptions );
/**
* Clear the cache and save new results
* @todo Implement caching for SMW query pages
*/
function recache( $limit, $ignoreErrors = true ) {
/// TODO
}
function isExpensive() {
return false; // Disables caching for now
}
function isSyndicated() {
return false; // TODO: why not?
}
/**
* @see QueryPage::linkParameters
*
* @since 1.9
*
* @return array
*/
public function linkParameters() {
$parameters = [];
$property = $this->getRequest()->getVal( 'property' );
if ( $property !== null && $property !== '' ) {
$parameters['property'] = $property;
}
$filter = $this->getRequest()->getVal( 'filter' );
if ( $filter !== null && $filter !== '' ) {
$parameters['filter'] = $filter;
}
return $parameters;
}
/**
* Returns a MessageFormatter object
*
* @since 1.9
*
* @return MessageFormatter
*/
public function getMessageFormatter() {
if ( !isset( $this->msgFormatter ) ) {
$this->msgFormatter = new MessageFormatter( $this->getLanguage() );
}
return $this->msgFormatter;
}
/**
* Returns a Linker object
*
* @since 1.9
*
* @return Linker
*/
public function getLinker() {
if ( $this->linker === null ) {
$this->linker = smwfGetLinker();
}
return $this->linker;
}
/**
* Generates a search form
*
* @since 1.9
*
* @param string $property
*
* @return string
*/
public function getSearchForm( $property = '', $cacheDate = '', $propertySearch = true, $filter = '' ) {
$this->useSerchForm = true;
$this->getOutput()->addModules( 'ext.smw.autocomplete.property' );
// No need to verify $this->selectOptions because its values are set
// during doQuery() which is processed before this form is generated
$limit = $this->selectOptions['limit'];
$offset = $this->selectOptions['offset'];
$resultCount = $this->msg( 'smw-showingresults' )->numParams( $limit, $offset + 1 )->parse();
$msgBuilder = new MessageBuilder( $this->getLanguage() );
$selection = $msgBuilder->prevNextToText(
$this->getContext()->getTitle(),
$limit,
$offset,
$this->linkParameters(),
$this->selectOptions['end']
);
if ( $cacheDate !== '' ) {
$cacheDate = Xml::tags( 'p', [], $cacheDate );
}
if ( $propertySearch ) {
$propertySearch = Xml::tags( 'hr', [ 'style' => 'margin-bottom:10px;' ], '' ) .
Xml::inputLabel( $this->msg( 'smw-special-property-searchform' )->text(), 'property', 'smw-property-input', 20, $property ) . ' ' .
Xml::submitButton( $this->msg( 'allpagessubmit' )->text() );
}
if ( $filter !== '' ) {
$filter = Xml::tags( 'hr', [ 'style' => 'margin-bottom:10px;' ], '' ) . $filter;
}
return Xml::tags( 'form', [
'method' => 'get',
'action' => htmlspecialchars( $GLOBALS['wgScript'] ),
'class' => 'plainlinks'
], Html::hidden( 'title', $this->getContext()->getTitle()->getPrefixedText() ) .
Xml::fieldset( $this->msg( 'smw-special-property-searchform-options' )->text(),
Xml::tags( 'p', [], $resultCount ) .
Xml::tags( 'p', [], $selection ) .
$cacheDate .
$propertySearch .
$filter
)
);
}
/**
* This is the actual workhorse. It does everything needed to make a
* real, honest-to-gosh query page.
* Alas, we need to overwrite the whole beast since we do not assume
* an SQL-based storage backend.
*
* @param $offset database query offset
* @param $limit database query limit
* @param $property database string query
*/
function doQuery( $offset = false, $limit = false, $property = false ) {
$out = $this->getOutput();
$sk = $this->getSkin();
$options = new RequestOptions();
$options->limit = $limit;
$options->offset = $offset;
$options->sort = true;
if ( $property ) {
$options->addStringCondition( $property, StringCondition::STRCOND_MID );
}
if ( ( $filter = $this->getRequest()->getVal( 'filter' ) ) === 'unapprove' ) {
$options->addExtraCondition( [ 'filter.unapprove' => true ] );
}
$res = $this->getResults( $options );
$num = count( $res );
// often disable 'next' link when we reach the end
$atend = $num < $limit;
$this->selectOptions = [
'offset' => $offset,
'limit' => $limit,
'end' => $atend,
'count' => $num
];
$out->addHTML( $this->getPageHeader() );
// if list is empty, show it
if ( $num == 0 ) {
$out->addHTML( '<p>' . $this->msg( 'specialpage-empty' )->escaped() . '</p>' );
return;
}
if ( $num > 0 ) {
$s = [];
if ( !$this->listoutput ) {
$s[] = $this->openList( $offset );
}
foreach ( $res as $r ) {
$format = $this->formatResult( $sk, $r );
if ( $format ) {
$s[] = $this->listoutput ? $format : "<li>{$format}</li>\n";
}
}
if ( !$this->listoutput ) {
$s[] = $this->closeList();
}
$str = $this->listoutput ? $this->getLanguage()->listToText( $s ) : implode( '', $s );
$out->addHTML( $str );
}
if ( !$this->useSerchForm ) {
$out->addHTML( "<p>{$sl}</p>\n" );
}
return $num;
}
/**
* @return array|null
*/
public function getQueryInfo(): ?array {
return null;
}
}