diff options
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/includes/queryprinters/AggregatablePrinter.php')
-rw-r--r-- | www/wiki/extensions/SemanticMediaWiki/includes/queryprinters/AggregatablePrinter.php | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/includes/queryprinters/AggregatablePrinter.php b/www/wiki/extensions/SemanticMediaWiki/includes/queryprinters/AggregatablePrinter.php new file mode 100644 index 00000000..7439d2f8 --- /dev/null +++ b/www/wiki/extensions/SemanticMediaWiki/includes/queryprinters/AggregatablePrinter.php @@ -0,0 +1,280 @@ +<?php + +namespace SMW; + +use SMWDataItem; +use SMWQueryResult; + +/** + * Abstract class that supports the aggregation and distributive calculation + * of numerical data. + * + * @since 1.9 + * + * + * @license GNU GPL v2+ + * @author Jeroen De Dauw < jeroendedauw@gmail.com > + */ + +/** + * Abstract class that supports the aggregation and distributive calculation + * of numerical data. Supports the distribution parameter, and related + * parameters that allows the user to choose between regular behavior or + * generating a distribution of values. + * + * For example, this result set: foo bar baz foo bar bar ohi + * Will be turned into + * * bar (3) + * * foo (2) + * * baz (1) + * * ohi (1) + * + * @ingroup QueryPrinter + */ +abstract class AggregatablePrinter extends ResultPrinter { + + /** + * Create the formats output given the result data and return it. + * + * @since 1.7 + * + * @param array $data label => value + */ + protected abstract function getFormatOutput( array $data ); + + /** + * Method gets called right before the result is returned + * in case there are values to display. It is meant for + * adding resources such as JS and CSS only needed for this + * format when it has actual values. + * + * @since 1.7 + */ + protected function addResources() { + } + + /** + * (non-PHPdoc) + * @see SMWResultPrinter::getResultText() + */ + protected function getResultText( SMWQueryResult $queryResult, $outputMode ) { + $data = $this->getResults( $queryResult, $outputMode ); + + if ( $data === [] ) { + $queryResult->addErrors( [ + $this->msg( 'smw-qp-empty-data' )->inContentLanguage()->text() + ] ); + return ''; + } else { + $this->applyDistributionParams( $data ); + $this->addResources(); + return $this->getFormatOutput( $data ); + } + } + + /** + * Apply the distribution specific parameters. + * + * @since 1.7 + * + * @param array $data + */ + protected function applyDistributionParams( array &$data ) { + if ( $this->params['distributionsort'] == 'asc' ) { + asort( $data, SORT_NUMERIC ); + } + elseif ( $this->params['distributionsort'] == 'desc' ) { + arsort( $data, SORT_NUMERIC ); + } + + if ( $this->params['distributionlimit'] !== false ) { + $data = array_slice( $data, 0, $this->params['distributionlimit'], true ); + } + } + + /** + * Gets and processes the results so they can be fed directly to the + * getFormatOutput method. They are returned as an array with the keys + * being the labels and the values being their corresponding (numeric) values. + * + * @since 1.7 + * + * @param SMWQueryResult $result + * @param $outputMode + * + * @return array label => value + */ + protected function getResults( SMWQueryResult $result, $outputMode ) { + if ( $this->params['distribution'] ) { + return $this->getDistributionResults( $result, $outputMode ); + } + else { + return $this->getNumericResults( $result, $outputMode ); + } + } + + /** + * Counts all the occurrences of all values in the query result, + * and returns an array with as key the value and as value the count. + * + * @since 1.7 + * + * @param SMWQueryResult $result + * @param $outputMode + * + * @return array label => value + */ + protected function getDistributionResults( SMWQueryResult $result, $outputMode ) { + $values = []; + + while ( /* array of SMWResultArray */ $row = $result->getNext() ) { // Objects (pages) + for ( $i = 0, $n = count( $row ); $i < $n; $i++ ) { // SMWResultArray for a sinlge property + while ( ( /* SMWDataValue */ $dataValue = $row[$i]->getNextDataValue() ) !== false ) { // Data values + + // Get the HTML for the tag content. Pages are linked, other stuff is just plaintext. + if ( $dataValue->getTypeID() == '_wpg' ) { + $value = $dataValue->getTitle()->getText(); + } + else { + $value = $dataValue->getShortText( $outputMode, $this->getLinker( false ) ); + } + + if ( !array_key_exists( $value, $values ) ) { + $values[$value] = 0; + } + + $values[$value]++; + } + } + } + + return $values; + } + + /** + * Returns an array with the numerical data in the query result. + * + * @since 1.7 + * + * @param SMWQueryResult $res + * @param $outputMode + * + * @return array label => value + */ + protected function getNumericResults( SMWQueryResult $res, $outputMode ) { + $values = []; + + // print all result rows + while ( $subject = $res->getNext() ) { + $dataValue = $subject[0]->getNextDataValue(); + + if ( $dataValue !== false ) { + $name = $dataValue->getShortWikiText(); + + foreach ( $subject as $field ) { + + // Use the aggregation parameter to determine the source of + // the number composition + if ( $this->params['aggregation'] === 'property' ) { + $name = $field->getPrintRequest()->getLabel(); + } + + // Aggregated array key depends on the mainlabel which is + // either the subject or a printout property + if ( $this->params['mainlabel'] === '-' ) { + + // In case of '-', getNextDataValue() already shifted the + // array forward which means the first column + // ( $subject[0] == $field ) contains a possible value + // and has to be collected as well + if ( ( $subject[0] == $field ) && $dataValue->getDataItem()->getDIType() === SMWDataItem::TYPE_NUMBER ) { + $value = $dataValue->getDataItem( )->getNumber(); + $values[$name] = isset( $values[$name] ) ? $values[$name] + $value : $value; + } + } + + while ( ( /* SMWDataItem */ $dataItem = $field->getNextDataItem() ) !== false ) { + $this->addNumbersForDataItem( $dataItem, $values, $name ); + } + } + } + } + + return $values; + } + + /** + * Adds all numbers contained in a dataitem to the list. + * + * @since 1.7 + * + * @param SMWDataItem $dataItem + * @param array $values + * @param string $name + */ + protected function addNumbersForDataItem( SMWDataItem $dataItem, array &$values, $name ) { + switch ( $dataItem->getDIType() ) { + case SMWDataItem::TYPE_NUMBER: + // Collect and aggregate values for the same array key + $value = $dataItem->getNumber(); + if ( !isset( $values[$name] ) ) { + $values[$name] = 0; + } + $values[$name] += $value; + break; + case SMWDataItem::TYPE_CONTAINER: + foreach ( $dataItem->getDataItems() as $di ) { + $this->addNumbersForDataItem( $di, $values, $name ); + } + break; + default: + } + } + + /** + * @codeCoverageIgnore + * @see SMWResultPrinter::getParamDefinitions + * + * @since 1.8 + * + * @param ParamDefinition[] $definitions + * + * @return array + */ + public function getParamDefinitions( array $definitions ) { + $definitions = parent::getParamDefinitions( $definitions ); + + $definitions['distribution'] = [ + 'name' => 'distribution', + 'type' => 'boolean', + 'default' => false, + 'message' => 'smw-paramdesc-distribution', + ]; + + $definitions['distributionsort'] = [ + 'name' => 'distributionsort', + 'type' => 'string', + 'default' => 'none', + 'message' => 'smw-paramdesc-distributionsort', + 'values' => [ 'asc', 'desc', 'none' ], + ]; + + $definitions['distributionlimit'] = [ + 'name' => 'distributionlimit', + 'type' => 'integer', + 'default' => false, + 'manipulatedefault' => false, + 'message' => 'smw-paramdesc-distributionlimit', + 'lowerbound' => 1, + ]; + + $definitions['aggregation'] = [ + 'message' => 'smw-paramdesc-aggregation', + 'default' => 'subject', + 'values' => [ 'property', 'subject' ], + ]; + + return $definitions; + } + +} |