summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php749
1 files changed, 749 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php b/www/wiki/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php
new file mode 100644
index 00000000..55845919
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/src/Query/ResultPrinters/ResultPrinter.php
@@ -0,0 +1,749 @@
+<?php
+
+namespace SMW\Query\ResultPrinters;
+
+use Linker;
+use ParamProcessor\ParamDefinition;
+use ParserOptions;
+use Sanitizer;
+use SMW\Message;
+use SMW\Parser\RecursiveTextProcessor;
+use SMW\Query\Result\StringResult;
+use SMW\Query\ResultPrinter as IResultPrinter;
+use SMWInfolink;
+use SMWOutputs as ResourceManager;
+use SMWQuery;
+use SMWQueryResult as QueryResult;
+use Title;
+
+/**
+ * Abstract base class for SMW's novel query printing mechanism. It implements
+ * part of the former functionality of SMWInlineQuery (everything related to
+ * output formatting and the corresponding parameters) and is subclassed by concrete
+ * printers that provide the main formatting functionality.
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author Markus Krötzsch
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ * @author mwjames
+ */
+abstract class ResultPrinter implements IResultPrinter {
+
+ /**
+ * Individual printers can decide what sort of deferrable mode is used for
+ * the output. `DEFERRED_DATA` signals that the format expects only the data
+ * component to be loaded from the backend.
+ */
+ const DEFERRED_DATA = 'deferred.data';
+
+ /**
+ * List of parameters, set by handleParameters.
+ * param name (lower case, trimmed) => param value (mixed)
+ *
+ * @since 1.7
+ *
+ * @var array
+ */
+ protected $params;
+
+ /**
+ * List of parameters, set by handleParameters.
+ * param name (lower case, trimmed) => IParam object
+ *
+ * @since 1.8
+ *
+ * @var \IParam[]
+ */
+ protected $fullParams;
+
+ /**
+ * @since 1.8
+ *
+ * @var
+ */
+ protected $outputMode;
+
+ /**
+ * The query result being displayed.
+ *
+ * @since 1.8
+ *
+ * @var QueryResult
+ */
+ protected $results;
+
+ /**
+ * Text to print *before* the output in case it is *not* empty; assumed to be wikitext.
+ * Normally this is handled in SMWResultPrinter and can be ignored by subclasses.
+ */
+ protected $mIntro = '';
+
+ /**
+ * Text to print *after* the output in case it is *not* empty; assumed to be wikitext.
+ * Normally this is handled in SMWResultPrinter and can be ignored by subclasses.
+ */
+ protected $mOutro = '';
+
+ /**
+ * Text to use for link to further results, or empty if link should not be shown.
+ * Unescaped! Use @see SMWResultPrinter::getSearchLabel()
+ * and @see SMWResultPrinter::linkFurtherResults()
+ * instead of accessing this directly.
+ */
+ protected $mSearchlabel = null;
+
+ /** Default return value for empty queries. Unescaped. Normally not used in sub-classes! */
+ protected $mDefault = '';
+
+ // parameters relevant for printers in general:
+ protected $mFormat; // a string identifier describing a valid format
+ protected $mLinkFirst; // should article names of the first column be linked?
+ protected $mLinkOthers; // should article names of other columns (besides the first) be linked?
+ protected $mShowHeaders = SMW_HEADERS_SHOW; // should the headers (property names) be printed?
+ protected $mShowErrors = true; // should errors possibly be printed?
+ protected $mInline; // is this query result "inline" in some page (only then a link to unshown results is created, error handling may also be affected)
+ protected $mLinker; // Linker object as needed for making result links. Might come from some skin at some time.
+
+ /**
+ * List of errors that occurred while processing the parameters.
+ *
+ * @since 1.6
+ *
+ * @var array
+ */
+ protected $mErrors = [];
+
+ /**
+ * If set, treat result as plain HTML. Can be used by printer classes if wiki mark-up is not enough.
+ * This setting is used only after the result text was generated.
+ * @note HTML query results cannot be used as parameters for other templates or in any other way
+ * in combination with other wiki text. The result will be inserted on the page literally.
+ */
+ protected $isHTML = false;
+
+ /**
+ * If set, take the necessary steps to make sure that things like {{templatename| ...}} are properly
+ * processed if they occur in the result. Clearly, this is only relevant if the output is not HTML, i.e.
+ * it is ignored if SMWResultPrinter::$is_HTML is true. This setting is used only after the result
+ * text was generated.
+ * @note This requires extra processing and may make the result less useful for being used as a
+ * parameter for further parser functions. Use only if required.
+ */
+ protected $hasTemplates = false;
+ /// Incremented while expanding templates inserted during printout; stop expansion at some point
+ private static $mRecursionDepth = 0;
+ /// This public variable can be set to higher values to allow more recursion; do this at your own risk!
+ /// This can be set in LocalSettings.php, but only after enableSemantics().
+ public static $maxRecursionDepth = 2;
+
+ /**
+ * @var RecursiveTextProcessor
+ */
+ protected $recursiveTextProcessor;
+
+ /**
+ * @var boolean
+ */
+ private $recursiveAnnotation = false;
+
+ /**
+ * For certaing activities (embedded pages etc.) make sure that annotations
+ * are not tranclucded (imported) into the target page when resolving a
+ * query.
+ *
+ * @var boolean
+ */
+ protected $transcludeAnnotation = true;
+
+ /**
+ * Return serialised results in specified format.
+ * Implemented by subclasses.
+ */
+ abstract protected function getResultText( QueryResult $res, $outputMode );
+
+ /**
+ * Constructor. The parameter $format is a format string
+ * that may influence the processing details.
+ *
+ * Do not override in deriving classes.
+ *
+ * @param string $format
+ * @param boolean $inline Optional since 1.9
+ */
+ public function __construct( $format, $inline = true ) {
+ global $smwgQDefaultLinking;
+
+ $this->mFormat = $format;
+ $this->mInline = $inline;
+ $this->mLinkFirst = ( $smwgQDefaultLinking != 'none' );
+ $this->mLinkOthers = ( $smwgQDefaultLinking == 'all' );
+ $this->mLinker = new Linker(); ///TODO: how can we get the default or user skin here (depending on context)?
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param integer $queryContext
+ */
+ public function setQueryContext( $queryContext ) {
+ $this->mInline = $queryContext != QueryContext::SPECIAL_PAGE;
+ }
+
+ /**
+ * This method is added temporary measures to avoid breaking those that relied
+ * on the removed ContextSource interface.
+ *
+ * @since 3.0
+ *
+ * @return Message
+ */
+ public function msg() {
+ return wfMessage( func_get_args() );
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param RecursiveTextProcessor $recursiveTextProcessor
+ */
+ public function setRecursiveTextProcessor( RecursiveTextProcessor $recursiveTextProcessor ) {
+ $this->recursiveTextProcessor = $recursiveTextProcessor;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param integer $feature
+ *
+ * @return boolean
+ */
+ public function isEnabledFeature( $feature ) {
+ return ( (int)$GLOBALS['smwgResultFormatsFeatures'] & $feature ) != 0;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param string $text
+ *
+ * @return string
+ */
+ public function expandTemplates( $text ) {
+ return $this->recursiveTextProcessor->expandTemplates( $text );
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param array $modules
+ * @param array $styleModules
+ */
+ public function registerResources( array $modules = [], array $styleModules = [] ) {
+
+ foreach ( $modules as $module ) {
+ ResourceManager::requireResource( $module );
+ }
+
+ foreach ( $styleModules as $styleModule ) {
+ ResourceManager::requireStyle( $styleModule );
+ }
+ }
+
+ /**
+ * @see IResultPrinter::getResult
+ *
+ * @note: since 1.8 this method is final, since it's the entry point.
+ * Most logic has been moved out to buildResult, which you can override.
+ *
+ * @param $results QueryResult
+ * @param $fullParams array
+ * @param $outputMode integer
+ *
+ * @return string
+ */
+ public final function getResult( QueryResult $results, array $fullParams, $outputMode ) {
+ $this->outputMode = $outputMode;
+ $this->results = $results;
+
+ $params = [];
+ $modules = [];
+ $styles = [];
+
+ /**
+ * @var \ParamProcessor\Param $param
+ */
+ foreach ( $fullParams as $param ) {
+ $params[$param->getName()] = $param->getValue();
+ }
+
+ $this->params = $params;
+ $this->fullParams = $fullParams;
+
+ $this->postProcessParameters();
+ $this->handleParameters( $this->params, $outputMode );
+
+ $resources = $this->getResources();
+
+ if ( isset( $resources['modules'] ) ) {
+ $modules = $resources['modules'];
+ }
+
+ if ( isset( $resources['styles'] ) ) {
+ $styles = $resources['styles'];
+ }
+
+ // Register possible default modules at this point to allow for content
+ // retrieved from a remote source to use required JS/CSS modules from the
+ // local entry point
+ $this->registerResources( $modules, $styles );
+
+ if ( $results instanceof StringResult ) {
+ $results->setOption( 'is.exportformat', $this->isExportFormat() );
+ return $results->getResults();
+ }
+
+ return $this->buildResult( $results );
+ }
+
+ /**
+ * Build and return the HTML result.
+ *
+ * @since 1.8
+ *
+ * @param QueryResult $results
+ *
+ * @return string
+ */
+ protected function buildResult( QueryResult $results ) {
+ $this->isHTML = false;
+ $this->hasTemplates = false;
+
+ $outputMode = $this->outputMode;
+
+ // Default output for normal printers:
+ if ( $outputMode !== SMW_OUTPUT_FILE && $results->getCount() == 0 ) {
+ if ( !$results->hasFurtherResults() ) {
+ return $this->escapeText( $this->mDefault, $outputMode )
+ . $this->getErrorString( $results );
+ } elseif ( $this->mInline && $this->isDeferrable() !== self::DEFERRED_DATA ) {
+
+ if ( !$this->linkFurtherResults( $results ) ) {
+ return '';
+ }
+
+ return $this->getFurtherResultsLink( $results, $outputMode )->getText( $outputMode, $this->mLinker )
+ . $this->getErrorString( $results );
+ }
+ }
+
+ // Get output from printer:
+ $result = $this->getResultText( $results, $outputMode );
+
+ if ( $outputMode !== SMW_OUTPUT_FILE ) {
+ $result = $this->handleNonFileResult( $result, $results, $outputMode );
+ }
+
+ return $result;
+ }
+
+ /**
+ * Continuation of getResult that only gets executed for non file outputs.
+ *
+ * @since 1.6
+ *
+ * @param string $result
+ * @param QueryResult $results
+ * @param integer $outputmode
+ *
+ * @return string
+ */
+ protected function handleNonFileResult( $result, QueryResult $results, $outputmode ) {
+
+ // append errors
+ $result .= $this->getErrorString( $results );
+
+ // Should not happen, used as fallback which in case the parser state
+ // relies on the $GLOBALS['wgParser']
+ if ( $this->recursiveTextProcessor === null ) {
+ $this->recursiveTextProcessor = new RecursiveTextProcessor();
+ }
+
+ $this->recursiveTextProcessor->uniqid();
+
+ $this->recursiveTextProcessor->setMaxRecursionDepth(
+ self::$maxRecursionDepth
+ );
+
+ $this->recursiveTextProcessor->transcludeAnnotation(
+ $this->transcludeAnnotation
+ );
+
+ $this->recursiveTextProcessor->setRecursiveAnnotation(
+ $this->recursiveAnnotation
+ );
+
+ // Apply intro parameter
+ if ( ( $this->mIntro ) && ( $results->getCount() > 0 ) ) {
+ if ( $outputmode == SMW_OUTPUT_HTML ) {
+ $result = Message::get( [ 'smw-parse', $this->mIntro ], Message::PARSE ) . $result;
+ } elseif ( $outputmode !== SMW_OUTPUT_RAW ) {
+ $result = $this->mIntro . $result;
+ }
+ }
+
+ // Apply outro parameter
+ if ( ( $this->mOutro ) && ( $results->getCount() > 0 ) ) {
+ if ( $outputmode == SMW_OUTPUT_HTML ) {
+ $result = $result . Message::get( [ 'smw-parse', $this->mOutro ], Message::PARSE );
+ } elseif ( $outputmode !== SMW_OUTPUT_RAW ) {
+ $result = $result . $this->mOutro;
+ }
+ }
+
+ // Preprocess embedded templates if needed
+ if ( ( !$this->isHTML ) && ( $this->hasTemplates ) ) {
+ $result = $this->recursiveTextProcessor->recursivePreprocess( $result );
+ }
+
+ if ( ( $this->isHTML ) && ( $outputmode == SMW_OUTPUT_WIKI ) ) {
+ $result = [ $result, 'isHTML' => true ];
+ } elseif ( ( !$this->isHTML ) && ( $outputmode == SMW_OUTPUT_HTML ) ) {
+ $result = $this->recursiveTextProcessor->recursiveTagParse( $result );
+ }
+
+ if ( $this->mShowErrors && $this->recursiveTextProcessor->getError() !== [] ) {
+ $result .= Message::get( $this->recursiveTextProcessor->getError(), Message::TEXT, Message::USER_LANGUAGE );
+ }
+
+ $this->recursiveTextProcessor->releaseAnnotationBlock();
+
+ return $result;
+ }
+
+ /**
+ * Does any additional parameter handling that needs to be done before the
+ * actual result is build. This includes cleaning up parameter values
+ * and setting class fields.
+ *
+ * Since 1.6 parameter handling should happen via validator based on the parameter
+ * definitions returned in getParameters. Therefore this method should likely
+ * not be used in any new code. It's mainly here for legacy reasons.
+ *
+ * @since 1.6
+ *
+ * @param array $params
+ * @param $outputMode
+ */
+ protected function handleParameters( array $params, $outputMode ) {
+ // No-op
+ }
+
+ /**
+ * Similar to handleParameters.
+ *
+ * @since 1.8
+ */
+ protected function postProcessParameters() {
+ $params = $this->params;
+
+ $this->mIntro = isset( $params['intro'] ) ? str_replace( '_', ' ', $params['intro'] ) : '';
+ $this->mOutro = isset( $params['outro'] ) ? str_replace( '_', ' ', $params['outro'] ) : '';
+
+ $this->mSearchlabel = !isset( $params['searchlabel'] ) || $params['searchlabel'] === false ? null : $params['searchlabel'];
+ $link = isset( $params['link'] ) ? $params['link'] : '';
+
+ switch ( $link ) {
+ case 'head': case 'subject':
+ $this->mLinkFirst = true;
+ $this->mLinkOthers = false;
+ break;
+ case 'all':
+ $this->mLinkFirst = true;
+ $this->mLinkOthers = true;
+ break;
+ case 'none':
+ $this->mLinkFirst = false;
+ $this->mLinkOthers = false;
+ break;
+ }
+
+ $this->mDefault = isset( $params['default'] ) ? str_replace( '_', ' ', $params['default'] ) : '';
+ $headers = isset( $params['headers'] ) ? $params['headers'] : '';
+
+ if ( $headers == 'hide' ) {
+ $this->mShowHeaders = SMW_HEADERS_HIDE;
+ } elseif ( $headers == 'plain' ) {
+ $this->mShowHeaders = SMW_HEADERS_PLAIN;
+ } else {
+ $this->mShowHeaders = SMW_HEADERS_SHOW;
+ }
+
+ $this->recursiveAnnotation = isset( $params['import-annotation'] ) ? $params['import-annotation'] : false;
+ }
+
+ /**
+ * Depending on current linking settings, returns a linker object
+ * for making hyperlinks or NULL if no links should be created.
+ *
+ * @param boolean $firstcol True of this is the first result column (having special linkage settings).
+ * @return Linker|null
+ */
+ protected function getLinker( $firstcol = false ) {
+ if ( ( $firstcol && $this->mLinkFirst ) || ( !$firstcol && $this->mLinkOthers ) ) {
+ return $this->mLinker;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets a SMWInfolink object that allows linking to a display of the query result.
+ *
+ * @since 1.8
+ *
+ * @param QueryResult $res
+ * @param $outputMode
+ * @param string $classAffix
+ *
+ * @return SMWInfolink
+ */
+ protected function getLink( QueryResult $res, $outputMode, $classAffix = '' ) {
+ $link = $res->getQueryLink( $this->getSearchLabel( $outputMode ) );
+
+ if ( $classAffix !== '' ){
+ $link->setStyle( 'smw-' . $this->params['format'] . '-' . Sanitizer::escapeClass( $classAffix ) );
+ }
+
+ if ( isset( $this->params['format'] ) ) {
+ $link->setParameter( $this->params['format'], 'format' );
+ }
+
+ /**
+ * @var \IParam $param
+ */
+ foreach ( $this->fullParams as $param ) {
+ if ( !$param->wasSetToDefault() && !( $param->getName() == 'limit' && $param->getValue() === 0 ) ) {
+ $link->setParameter( $param->getOriginalValue(), $param->getName() );
+ }
+ }
+
+ return $link;
+ }
+
+ /**
+ * Gets a SMWInfolink object that allows linking to further results for the query.
+ *
+ * @since 1.8
+ *
+ * @param QueryResult $res
+ * @param $outputMode
+ *
+ * @return SMWInfolink
+ */
+ protected function getFurtherResultsLink( QueryResult $res, $outputMode ) {
+ $link = $this->getLink( $res, $outputMode, 'furtherresults' );
+ $link->setParameter( $this->params['offset'] + $res->getCount(), 'offset' );
+ return $link;
+ }
+
+ /**
+ * @see IResultPrinter::getQueryMode
+ *
+ * @param $context
+ *
+ * @return integer
+ */
+ public function getQueryMode( $context ) {
+ // TODO: Now that we are using RequestContext object maybe
+ // $context is misleading
+ return SMWQuery::MODE_INSTANCES;
+ }
+
+ /**
+ * @see IResultPrinter::getName
+ *
+ * @return string
+ */
+ public function getName() {
+ return $this->mFormat;
+ }
+
+ /**
+ * Provides a simple formatted string of all the error messages that occurred.
+ * Can be used if not specific error formatting is desired. Compatible with HTML
+ * and Wiki.
+ *
+ * @param QueryResult $res
+ *
+ * @return string
+ */
+ protected function getErrorString( QueryResult $res ) {
+ return $this->mShowErrors ? smwfEncodeMessages( array_merge( $this->mErrors, $res->getErrors() ) ) : '';
+ }
+
+ /**
+ * @see IResultPrinter::setShowErrors
+ *
+ * @param boolean $show
+ */
+ public function setShowErrors( $show ) {
+ $this->mShowErrors = $show;
+ }
+
+ /**
+ * Individual printer can override this method to allow for unified loading
+ * practice.
+ *
+ * Styles are loaded first to avoid a possible FOUC (Flash of unstyled content).
+ *
+ * @since 3.0
+ *
+ * @return []
+ */
+ protected function getResources() {
+ return [ 'modules' => [], 'styles' => [] ];
+ }
+
+ /**
+ * If $outputmode is SMW_OUTPUT_HTML, escape special characters occurring in the
+ * given text. Otherwise return text as is.
+ *
+ * @param string $text
+ * @param $outputmode
+ *
+ * @return string
+ */
+ protected function escapeText( $text, $outputmode ) {
+ return $outputmode == SMW_OUTPUT_HTML ? htmlspecialchars( $text ) : $text;
+ }
+
+ /**
+ * Get the string the user specified as a text for the "further results" link,
+ * properly escaped for the current output mode.
+ *
+ * @param $outputmode
+ *
+ * @return string
+ */
+ protected function getSearchLabel( $outputmode ) {
+ return $this->escapeText( $this->mSearchlabel, $outputmode );
+ }
+
+ /**
+ * Check whether a "further results" link would normally be generated for this
+ * result set with the given parameters. Individual result printers may decide to
+ * create or hide such a link independent of that, but this is the default.
+ *
+ * @param QueryResult $results
+ *
+ * @return boolean
+ */
+ protected function linkFurtherResults( QueryResult $results ) {
+ return $this->mInline && $results->hasFurtherResults() && $this->mSearchlabel !== '';
+ }
+
+ /**
+ * Adds an error message for a parameter handling error so a list
+ * of errors can be created later on.
+ *
+ * @since 1.6
+ *
+ * @param string $errorMessage
+ */
+ protected function addError( $errorMessage ) {
+ $this->mErrors[] = $errorMessage;
+ }
+
+ /**
+ * A function to describe the allowed parameters of a query using
+ * any specific format - most query printers should override this
+ * function.
+ *
+ * @deprecated since 1.8, use getParamDefinitions instead.
+ *
+ * @since 1.5
+ *
+ * @return array
+ */
+ public function getParameters() {
+ return [];
+ }
+
+ /**
+ * @see IResultPrinter::getParamDefinitions
+ *
+ * @since 1.8
+ *
+ * @param ParamDefinition[] $definitions
+ *
+ * @return array
+ */
+ public function getParamDefinitions( array $definitions ) {
+ return array_merge( $definitions, $this->getParameters() );
+ }
+
+ /**
+ * Returns the parameter definitions as an associative array where
+ * the keys hold the parameter names and point to their full definitions.
+ * array( name => array|IParamDefinition )
+ *
+ * @since 1.8
+ *
+ * @param array $definitions List of definitions to prepend to the result printers list before further processing.
+ *
+ * @return array
+ */
+ public final function getNamedParameters( array $definitions = [] ) {
+ $params = [];
+
+ foreach ( $this->getParamDefinitions( $definitions ) as $param ) {
+ $params[is_array( $param ) ? $param['name'] : $param->getName()] = $param;
+ }
+
+ return $params;
+ }
+
+ /**
+ * @see IResultPrinter::isExportFormat
+ *
+ * @since 1.8
+ *
+ * @return boolean
+ */
+ public function isExportFormat() {
+ return false;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @return boolean
+ */
+ public function isDeferrable() {
+ return false;
+ }
+
+ /**
+ * Returns if the result printer supports using a "full parse" instead of a
+ * '[[SMW::off]]' . $wgParser->replaceVariables( $result ) . '[[SMW::on]]'
+ *
+ * @since 3.0
+ *
+ * @return boolean
+ */
+ public function supportsRecursiveAnnotation() {
+ return false;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return string
+ */
+ public function getDefaultSort() {
+ return 'ASC';
+ }
+
+}