r43952 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r43951‎ | r43952 | r43953 >
Date:21:58, 25 November 2008
Author:yaron
Status:deferred
Tags:
Comment:
New extension
Modified paths:
  • /trunk/extensions/SemanticCompoundQueries (added) (history)
  • /trunk/extensions/SemanticCompoundQueries/README (added) (history)
  • /trunk/extensions/SemanticCompoundQueries/SCQ_QueryProcessor.php (added) (history)
  • /trunk/extensions/SemanticCompoundQueries/SCQ_QueryResult.php (added) (history)
  • /trunk/extensions/SemanticCompoundQueries/SCQ_Settings.php (added) (history)

Diff [purge]

Index: trunk/extensions/SemanticCompoundQueries/SCQ_QueryResult.php
@@ -0,0 +1,35 @@
 2+<?php
 3+
 4+if (!defined('MEDIAWIKI')) die();
 5+
 6+/**
 7+ * Subclass of SMWQueryResult - this class was mostly created in order to
 8+ * get around an inconvenient print-request-compatibility check in
 9+ * SMWQueryResult::addRow()
 10+ *
 11+ * @ingroup SemanticCompoundQueries
 12+ * @author Yaron Koren
 13+ */
 14+class SCQQueryResult extends SMWQueryResult {
 15+
 16+ function addResult($new_result) {
 17+ // create an array of the pages already in this query result,
 18+ // so that we can check against it to make sure that pages
 19+ // aren't included twice
 20+ $existing_page_names = array();
 21+ while ($row = $this->getNext()) {
 22+ if ($row[0] instanceof SMWResultArray) {
 23+ $content = $row[0]->getContent();
 24+ $existing_page_names[] = $content[0]->getLongText(SMW_OUTPUT_WIKI);
 25+ }
 26+ }
 27+ while (($row = $new_result->getNext()) !== false) {
 28+ $row[0]->display_options = $new_result->display_options;
 29+ $content = $row[0]->getContent();
 30+ $page_name = $content[0]->getLongText(SMW_OUTPUT_WIKI);
 31+ if (! in_array($page_name, $existing_page_names))
 32+ $this->m_content[] = $row;
 33+ }
 34+ reset($this->m_content);
 35+ }
 36+}
Index: trunk/extensions/SemanticCompoundQueries/SCQ_QueryProcessor.php
@@ -0,0 +1,159 @@
 2+<?php
 3+
 4+if (!defined('MEDIAWIKI')) die();
 5+
 6+/**
 7+ * Class that holds static functions for handling compound queries.
 8+ * This class is heavily based on Semantic MediaWiki's SMWQueryProcessor,
 9+ * and calls that class's functions when possible.
 10+ *
 11+ * @ingroup SemanticCompoundQueries
 12+ * @author Yaron Koren
 13+ */
 14+class SCQQueryProcessor {
 15+
 16+ public static function registerParserFunctions(&$parser) {
 17+ $parser->setFunctionHook( 'compound_query', array('SCQQueryProcessor','doCompoundQuery') );
 18+ return true; // always return true, in order not to stop MW's hook processing!
 19+ }
 20+
 21+ /**
 22+ * An alternative to explode() - that function won't work here,
 23+ * because we don't want to split the string on all semicolons, just
 24+ * the ones that aren't contained within square brackets
 25+ */
 26+ public static function getSubParams($param) {
 27+ $sub_params = array();
 28+ $sub_param = "";
 29+ $uncompleted_square_brackets = 0;
 30+ for ($i = 0; $i <= strlen($param); $i++) {
 31+ $c = $param[$i];
 32+ if (($c == ';') && ($uncompleted_square_brackets <= 0)) {
 33+ $sub_params[] = $sub_param;
 34+ $sub_param = "";
 35+ } else {
 36+ $sub_param .= $c;
 37+ if ($c == '[')
 38+ $uncompleted_square_brackets++;
 39+ elseif ($c == ']')
 40+ $uncompleted_square_brackets--;
 41+ }
 42+ }
 43+ $sub_params[] = $sub_param;
 44+ return $sub_params;
 45+ }
 46+
 47+ /**
 48+ */
 49+ public static function doCompoundQuery(&$parser) {
 50+ global $smwgQEnabled, $smwgIQRunningNumber;
 51+ if ($smwgQEnabled) {
 52+ $smwgIQRunningNumber++;
 53+ $params = func_get_args();
 54+ array_shift( $params ); // we already know the $parser ...
 55+ $other_params = array();
 56+ $query_result = null;
 57+ foreach ($params as $param) {
 58+ // very primitive heuristic - if the parameter
 59+ // includes a square bracket, then it's a
 60+ // sub-query; otherwise it's a regular parameter
 61+ if (strpos($param, '[') !== false) {
 62+ $sub_params = SCQQueryProcessor::getSubParams($param);
 63+ $next_result = SCQQueryProcessor::getQueryResultFromFunctionParams($sub_params, SMW_OUTPUT_WIKI);
 64+ if ($query_result == null)
 65+ $query_result = new SCQQueryResult($next_result->getPrintRequests(), new SMWQuery());
 66+ $query_result->addResult($next_result);
 67+ } else {
 68+ $parts = explode('=', $param, 2);
 69+ if (count($parts) >= 2) {
 70+ $other_params[strtolower(trim($parts[0]))] = $parts[1]; // don't trim here, some params care for " "
 71+ }
 72+ }
 73+ }
 74+ $result = SCQQueryProcessor::getResultFromQueryResult($query_result, $other_params, null, SMW_OUTPUT_WIKI);
 75+ } else {
 76+ wfLoadExtensionMessages('SemanticMediaWiki');
 77+ $result = smwfEncodeMessages(array(wfMsgForContent('smw_iq_disabled')));
 78+ }
 79+ return $result;
 80+ }
 81+
 82+ static function getQueryResultFromFunctionParams($rawparams, $outputmode, $context = SMWQueryProcessor::INLINE_QUERY, $showmode = false) {
 83+ SMWQueryProcessor::processFunctionParams($rawparams,$querystring,$params,$printouts,$showmode);
 84+ return SCQQueryProcessor::getQueryResultFromQueryString($querystring,$params,$printouts, SMW_OUTPUT_WIKI, $context);
 85+ }
 86+
 87+ /**
 88+ * Combine the values from two SMWQueryResult objects into one
 89+ */
 90+ static function mergeSMWQueryResults($result1, $result2) {
 91+ if ($result1 == null) {
 92+ $result1 = new SMWQueryResult($result2->getPrintRequests(), new SMWQuery());
 93+ }
 94+ $existing_page_names = array();
 95+ while ($row = $result1->getNext()) {
 96+ if ($row[0] instanceof SMWResultArray) {
 97+ $content = $row[0]->getContent();
 98+ $existing_page_names[] = $content[0]->getLongText(SMW_OUTPUT_WIKI);
 99+ }
 100+ }
 101+ while (($row = $result2->getNext()) !== false) {
 102+ $row[0]->display_options = $result2->display_options;
 103+ $content = $row[0]->getContent();
 104+ $page_name = $content[0]->getLongText(SMW_OUTPUT_WIKI);
 105+ if (! in_array($page_name, $existing_page_names))
 106+ $result1->addRow($row);
 107+ }
 108+ return $result1;
 109+ }
 110+
 111+ // this method is an exact copy of SMWQueryProcessor's function,
 112+ // but it needs to be duplicated because there it's protected
 113+ static function getResultFormat($params) {
 114+ $format = 'auto';
 115+ if (array_key_exists('format', $params)) {
 116+ $format = strtolower(trim($params['format']));
 117+ global $smwgResultFormats;
 118+ if ( !array_key_exists($format, $smwgResultFormats) ) {
 119+ $format = 'auto'; // If it is an unknown format, defaults to list/table again
 120+ }
 121+ }
 122+ return $format;
 123+ }
 124+
 125+ static function getQueryResultFromQueryString($querystring, $params, $extraprintouts, $outputmode, $context = SMWQueryProcessor::INLINE_QUERY) {
 126+ wfProfileIn('SCQQueryProcessor::getQueryResultFromQueryString');
 127+ $query = SMWQueryProcessor::createQuery($querystring, $params, $context, null, $extraprintouts);
 128+ $query_result = smwfGetStore()->getQueryResult($query);
 129+ $query_result->display_options = array();
 130+ foreach ($params as $key => $value) {
 131+ // special handling for 'icon' field, since it requires
 132+ // conversion of a name to a URL
 133+ if ($key == 'icon') {
 134+ $icon_title = Title::newFromText($value);
 135+ $icon_image_page = new ImagePage($icon_title);
 136+ $icon_url = $icon_image_page->getDisplayedFile()->getURL();
 137+ $query_result->display_options['icon'] = $icon_url;
 138+ } else {
 139+ $query_result->display_options[$key] = $value;
 140+ }
 141+ }
 142+
 143+ wfProfileOut('SCQQueryProcessor::getQueryResultFromQueryString');
 144+ return $query_result;
 145+ }
 146+
 147+ /*
 148+ * Matches getResultFromQueryResult() from SMWQueryProcessor,
 149+ * except that formats of type 'debug' and 'count' aren't handled
 150+ */
 151+ static function getResultFromQueryResult($res, $params, $extraprintouts, $outputmode, $context = SMWQueryProcessor::INLINE_QUERY, $format = '') {
 152+ wfProfileIn('SCQQueryProcessor::getResultFromQueryResult');
 153+ $format = SCQQueryProcessor::getResultFormat($params);
 154+ $printer = SMWQueryProcessor::getResultPrinter($format, $context, $res);
 155+ $result = $printer->getResult($res, $params, $outputmode);
 156+ wfProfileOut('SCQQueryProcessor::getResultFromQueryResult');
 157+ return $result;
 158+ }
 159+}
 160+
Index: trunk/extensions/SemanticCompoundQueries/SCQ_Settings.php
@@ -0,0 +1,52 @@
 2+<?php
 3+/**
 4+ * Initialization file for SemanticCompoundQueries
 5+ *
 6+ * @file
 7+ * @ingroup SemanticCompoundQueries
 8+ * @author Yaron Koren
 9+ */
 10+
 11+if (!defined('MEDIAWIKI')) die();
 12+
 13+define('SCQ_VERSION', '0.2');
 14+
 15+$wgExtensionCredits['parserhook'][]= array(
 16+ 'name' => 'Semantic Compound Queries',
 17+ 'version' => SCQ_VERSION,
 18+ 'author' => 'Yaron Koren',
 19+ 'url' => 'http://www.mediawiki.org/wiki/Extension:Semantic_Compound_Queries',
 20+ 'description' => 'A parser function that displays multiple semantic queries at the same time',
 21+);
 22+
 23+$wgExtensionFunctions[] = 'scqgParserFunctions';
 24+$wgHooks['LanguageGetMagic'][] = 'scqgLanguageGetMagic';
 25+
 26+$scqIP = $IP . '/extensions/SemanticCompoundQueries';
 27+$wgAutoloadClasses['SCQQueryProcessor'] = $scqIP . '/SCQ_QueryProcessor.php';
 28+$wgAutoloadClasses['SCQQueryResult'] = $scqIP . '/SCQ_QueryResult.php';
 29+
 30+function scqgParserFunctions () {
 31+ global $wgHooks, $wgParser;
 32+ if( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
 33+ $wgHooks['ParserFirstCallInit'][] = 'scqgRegisterParser';
 34+ } else {
 35+ if ( class_exists( 'StubObject' ) && !StubObject::isRealObject( $wgParser ) ) {
 36+ $wgParser->_unstub();
 37+ }
 38+ SCQQueryProcessor::registerParserFunctions( $wgParser );
 39+ }
 40+}
 41+
 42+function scqgRegisterParser(&$parser) {
 43+ $parser->setFunctionHook( 'compound_query', array('SCQQueryProcessor','doCompoundQuery') );
 44+ return true; // always return true, in order not to stop MW's hook processing!
 45+}
 46+
 47+function scqgLanguageGetMagic( &$magicWords, $langCode = "en" ) {
 48+ switch ( $langCode ) {
 49+ default:
 50+ $magicWords['compound_query'] = array ( 0, 'compound_query' );
 51+ }
 52+ return true;
 53+}
Index: trunk/extensions/SemanticCompoundQueries/README
@@ -0,0 +1,48 @@
 2+Semantic Compound Queries Extension
 3+
 4+ Version 0.2
 5+ Yaron Koren
 6+
 7+This is free software licensed under the GNU General Public License. Please
 8+see http://www.gnu.org/copyleft/gpl.html for further details, including the
 9+full text and terms of the license.
 10+
 11+== Overview ==
 12+
 13+Semantic Compound Queries is an extension to MediaWiki that defines a
 14+parser function, '#compound_query', that displays the results of the
 15+equivalent of multiple Semantic MediaWiki #ask queries at the same time.
 16+The syntax of #compound_query resembles that of #ask, but with more than
 17+one query, and with the elements of each sub-query delimited by semicolons
 18+instead of pipes. Elements that are common across all sub-queries, like
 19+'format=' and 'width=' (for maps) should be placed after all sub-queries.
 20+
 21+A sample call to #compound query, which retrieves both biographies, along
 22+with their subject; and fiction books, along with their author; is:
 23+
 24+{{#compound_query:[[Category:Books]][[Has gentre::Biography]];?Covers subject=Subject
 25+ |[[Category:Books]][[Has genre::Fiction]];?Has author=Author
 26+ |format=list}}
 27+
 28+
 29+For more information, see the extension homepage at:
 30+http://www.mediawiki.org/wiki/Extension:Semantic_Compound_Queries
 31+
 32+== Requirements ==
 33+
 34+This version of the Semantic Compound Queries extension requires MediaWiki 1.8
 35+or higher and Semantic MediaWiki 1.2 or higher.
 36+
 37+== Installation ==
 38+
 39+To install the extension, place the entire 'SemanticCompoundQueries' directory
 40+within your MediaWiki 'extensions' directory, then add the following
 41+line to your 'LocalSettings.php' file:
 42+
 43+ require_once( "$IP/extensions/SemanticCompoundQueries/SCQ_Settings.php" );
 44+
 45+== Contact ==
 46+
 47+Comments, questions, suggestions and bug reports are welcome, and can
 48+be placed on the Talk page for the extension, or sent to Yaron at
 49+yaron57@gmail.com.

Status & tagging log