Mwjames has uploaded a new change for review. https://gerrit.wikimedia.org/r/52598
Change subject: ParserHook re-factoring prototype [DO NOT MERGE] ...................................................................... ParserHook re-factoring prototype [DO NOT MERGE] This is a prootype based on the comments made [1]. Since I constantly fail to understand, it is working prototpe to ensure core functionality is working but under the understanding for a missing base class and reimplementation of code in order to achieve loose coupling. + Tests are missing + Comments are mssing [1] https://gerrit.wikimedia.org/r/#/c/51974/6 Change-Id: I5d3cc9ff97f77acb05225658b1fb2f815b8b9f5f --- M includes/Setup.php M includes/parserhooks/ParserParameter.php M includes/parserhooks/RecurringEvents.php M includes/parserhooks/RecurringEventsHandler.php A includes/parserhooks/SemanticDataHandler.php M includes/parserhooks/SetParser.php M includes/parserhooks/SubobjectHandler.php 7 files changed, 442 insertions(+), 141 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/SemanticMediaWiki refs/changes/98/52598/1 diff --git a/includes/Setup.php b/includes/Setup.php index d9410f0..131c526 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -210,6 +210,7 @@ $wgAutoloadClasses['SMW\Subobject'] = $phDir . 'Subobject.php'; $wgAutoloadClasses['SMW\RecurringEventsHandler'] = $phDir . 'RecurringEventsHandler.php'; $wgAutoloadClasses['SMW\RecurringEvents'] = $phDir . 'RecurringEvents.php'; + $wgAutoloadClasses['SMW\SemanticDataHandler'] = $phDir . 'SemanticDataHandler.php'; // Stores & queries $wgAutoloadClasses['SMWQueryProcessor'] = $smwgIP . 'includes/SMW_QueryProcessor.php'; diff --git a/includes/parserhooks/ParserParameter.php b/includes/parserhooks/ParserParameter.php index 34bcbec..42e8713 100644 --- a/includes/parserhooks/ParserParameter.php +++ b/includes/parserhooks/ParserParameter.php @@ -22,6 +22,7 @@ * * @since 1.9 * + * @file * @ingroup SMW * * @licence GNU GPL v2+ @@ -31,28 +32,72 @@ /** * Returns a default separator - * - * @since 1.9 - * * @var string */ protected $defaultSeparator = ','; /** - * Returns an instance of the current class + * Returns first named identifier + * @var array + */ + protected $rawParameters; + + /** + * Returns first named identifier + * @var array + */ + protected $parameters; + + /** + * Returns first named identifier + * @var string + */ + protected $first = null; + + /** + * Constructor * * @since 1.9 * - * @return ParserParameter + * @param array $parameters */ - public static function singleton() { - static $instance = null; + public function __construct( array $parameters ) { + $this->rawParameters = $parameters; + $this->parameters = $this->map( $this->rawParameters ); + } - if ( $instance === null ) { - $instance = new self(); - } + /** + * Returns first available parameter + * + * @since 1.9 + * + * @return string + */ + public function getFirst() { + return $this->first; + } - return $instance; + /** + * Map parameters from an external source independent from the invoked + * constructor + * + * @since 1.9 + * + * @return string + */ + public function mapParameters( array $params ) { + return $this->map( $params ); + } + + /** + * Returns raw parameters + * + * @since 1.9 + * + * @return string + */ + public function getRaw() { + return $this->rawParameters; } /** @@ -60,11 +105,48 @@ * * @since 1.9 * - * @param array $param + * @return string + */ + public function toArray() { + return $this->parameters; + } + + /** + * Inject parameters from an outside source + * + * @since 1.9 + * + * @param array + */ + public function setParameters( array $parameters ) { + $this->parameters = $parameters; + } + + /** + * Add parameter key and value + * + * @since 1.9 + * + * @param string $key + * @param string $value + */ + public function addParameter( $key, $value ) { + if( $key !== '' && $value !== '' ) { + $this->parameters[$key][] = $value; + } + } + + /** + * Do mapping of raw parameters array into an 2n-array for simplified + * via [key] => [value1, value2] + * + * @since 1.9 + * + * @param array $params * * @return array */ - public function getParameters( array $params ) { + protected function map( array $params ) { $results = array(); $previousProperty = null; @@ -72,7 +154,12 @@ $separator = ''; $values = array(); - // Get the current element + // Only strings are allowed for processing + if( !is_string( current ( $params ) ) ) { + next( $params ); + } + + // Get the current element and divide it into parts $currentElement = explode( '=', trim( current ( $params ) ), 2 ); // Looking to the next element for comparison @@ -81,7 +168,7 @@ if ( $nextElement !== array() ) { // This allows assignments of type |Has property=Test1,Test2|+sep=, - // as a means to support mutliple value declaration + // as a means to support multiple value declaration if ( substr( $nextElement[0], - 5 ) === '+sep' ) { $separator = isset( $nextElement[1] ) ? $nextElement[1] !== '' ? $nextElement[1] : $this->defaultSeparator : $this->defaultSeparator; next( $params ); @@ -89,8 +176,13 @@ } } + // First named parameter + if ( count( $currentElement ) == 1 && $previousProperty === null ) { + $this->first = str_replace( ' ', '_', $currentElement[0] ); + } + // Here we allow to support assignments of type |Has property=Test1|Test2|Test3 - // for mutliple values with the same preceeding property + // for multiple values with the same preceding property if ( count( $currentElement ) == 1 && $previousProperty !== null ) { $currentElement[1] = $currentElement[0]; $currentElement[0] = $previousProperty; @@ -105,13 +197,13 @@ $values[] = $currentElement[1]; } - // Remap properties and values to ouput a simple array + // Remap properties and values to output a simple array foreach ( $values as $value ) { if ( $value !== '' ){ $results[ $currentElement[0] ][] = $value; } } } - return $results; + return $results; } } \ No newline at end of file diff --git a/includes/parserhooks/RecurringEvents.php b/includes/parserhooks/RecurringEvents.php index e3a6c19..f7e5783 100644 --- a/includes/parserhooks/RecurringEvents.php +++ b/includes/parserhooks/RecurringEvents.php @@ -39,12 +39,9 @@ class RecurringEvents { /** - * Defines the default / max number of an instances - * var $defaultLimit - * var $maxLimit + * Defines available options from $GLOBALS */ - protected $defaultLimit; - protected $maxLimit; + protected $options = array(); /** * Defines the property used @@ -76,16 +73,14 @@ * @since 1.9 * * @param array $parameters + * @param array $options */ - public function __construct( $parameters ) { - global $smwgDefaultNumRecurringEvents, $smwgMaxNumRecurringEvents; - + public function __construct( $parameters, $options ) { if ( !is_array( $parameters ) ) { throw new MWException( 'Parameters array is not initialized' ); } - $this->defaultLimit = $smwgDefaultNumRecurringEvents; - $this->maxLimit = $smwgMaxNumRecurringEvents; + $this->options = $options; $this->parse( $parameters ); } @@ -145,6 +140,22 @@ } /** + * Get value for a specific option + * + * Options are available for local context therefore no public exposure + * + * @since 1.9 + * + * @return mixed + */ + protected function getOption( $name ) { + if ( !isset( $this->options[$name] ) ) { + throw new MWException( "Option {$name} is not available" ); + } + return $this->options[$name]; + } + + /** * Returns the "Julian day" value from an object of type * SMWTimeValue. */ @@ -191,8 +202,8 @@ $end_date = SMWDataValueFactory::newTypeIDValue( '_dat', $value ); break; case 'limit': - // Override default limit with parameter specific limit - $this->defaultLimit = (int)$value; + // Override default limit with query specific limit + $this->options['DefaultNumRecurringEvents'] = (int)$value; break; case 'unit': $unit = $value; @@ -229,16 +240,17 @@ } } - // Make sure start date is set - if ( !( $start_date->getDataItem() instanceof SMWDITime ) ) { + if ( $start_date === null ) { + $this->setError( array( 'The start date is missing') ); + return; + } else if ( !( $start_date->getDataItem() instanceof SMWDITime ) ) { $this->setError( $start_date->getErrors() ); return; } // Check property if ( is_null( $this->property ) ) { - // FIXME ErrorReport class should use a message key instead of an - // already translated message + $this->setError( array( 'The property is missing') ); // $this->setError( $this->msg( 'smw-missing-property' )->inContentLanguage()->text() ); return; } @@ -363,9 +375,9 @@ // should we stop? if ( is_null( $end_date ) ) { - $reached_end_date = $i > $this->defaultLimit; + $reached_end_date = $i > $this->getOption( 'DefaultNumRecurringEvents' ); } else { - $reached_end_date = ( $cur_date_jd > $end_date_jd ) || ( $i > $this->maxLimit ); + $reached_end_date = ( $cur_date_jd > $end_date_jd ) || ( $i > $this->getOption( 'MaxNumRecurringEvents' ) ); } } while ( !$reached_end_date ); diff --git a/includes/parserhooks/RecurringEventsHandler.php b/includes/parserhooks/RecurringEventsHandler.php index 78280b7..bbc5a0a 100644 --- a/includes/parserhooks/RecurringEventsHandler.php +++ b/includes/parserhooks/RecurringEventsHandler.php @@ -3,7 +3,10 @@ namespace SMW; use Parser; -use SMWParseData; +use Title; +use ParserOutput; +use SMWDIWikiPage; +use SMW\ParserParameter; /** * Class handling #set_recurring_event parser function @@ -33,55 +36,90 @@ * * @author mwjames */ -class RecurringEventsHandler { +class RecurringEventsHandler extends SubobjectHandler { /** - * Method for handling the set_recurring_event parser function. + * Method for handling the subobject parser function. * * @since 1.9 + * + */ + public function init( Title $title, ParserOutput $parserOutput, $params ) { + + // Global settings are transformed into an independent array + //$settings = new Settings( $GLOBALS ); + $options = array( + 'DefaultNumRecurringEvents' => 100, + 'MaxNumRecurringEvents'=> 200 + ); + + $this->subject = new SMWDIWikiPage( + $title->getDBkey(), + $title->getNamespace(), + $title->getInterwiki() + ); + + $this->subobject = new Subobject( $this->subject ); + $this->parameters = new ParserParameter( $params ); + $this->semanticDataHandler = new SemanticDataHandler(); + + $this->semanticDataHandler->initSemanticData( $parserOutput, $this->subject ); + + // Get recurring events + $events = new RecurringEvents( $this->parameters->toArray(), $options ); + + // Collect errors + $this->error= $events->getErrors(); + + // Iterate over available recurring events + foreach ( $events->getDates() as $date_str ) { + + // Override parameters with the returned left-overs from recurring + // events that were marked as unused + $this->parameters->setParameters( $events->getParameters() ); + + // Add the date string as individual property / value parameter + $this->parameters->addParameter( $events->getProperty(), $date_str ); + + // Add the first parameter if available as parameter to act as direct + // page pointer + if( $this->parameters->getFirst() !== null ){ + $this->parameters->addParameter( + $this->parameters->getFirst(), + $this->subject->getTitle()->getPrefixedText() + ); + } + + // Register object values + // @see SMW\SubobjectHandler::registerObjectValues + $this->add( $this->parameters->toArray() ); + + // Store subobject + $this->semanticDataHandler->addPropertyObjectValue( + $this->getSubobject()->getProperty(), + $this->getSubobject()->getContainer() + ); + + $this->semanticDataHandler->storeSemanticData( $parserOutput ); + + $this->errors = $this->semanticDataHandler->getErrors(); + $this->errors = $this->subobject->getErrors(); + + } + + + return $this->errors; + } + + /** + * Method for handling the set parser function. * * @param Parser $parser */ public static function render( Parser &$parser ) { $params = func_get_args(); - array_shift( $params ); - - $mainSemanticData = SMWParseData::getSMWData( $parser ); - $subject = $mainSemanticData->getSubject(); - - // FIXME Use a class instance - $parameters = ParserParameter::singleton()->getParameters( $params ); - - // Get recurring events - $events = new RecurringEvents( $parameters ); - $errors = $events->getErrors(); - - // Go over available recurring events - foreach ( $events->getDates() as $date_str ) { - - // Override parameters as only unused parameters are necessary - $parameters = $events->getParameters(); - - // Add individual date string as parameter in order to be handled - // equally by the SubobjectHandler as member of the same instance - // once the ParserParameter class is fixed use a - // $parameters->addParameter( key, value ) instead - $parameters[$events->getProperty()][] = $date_str; - - // Instantiate subobject handler for each new date - $handler = new SubobjectHandler( $subject, $parameters ); - - // Store an individual subobject - SMWParseData::getSMWData( $parser )->addPropertyObjectValue( - $handler->getSubobject()->getProperty(), - $handler->getSubobject()->getContainer() - ); - - // Collect individual errors - $errors = array_merge( $handler->getSubobject()->getErrors(), $errors ); - } - - // See comments in SubobjectHandler class - return smwfEncodeMessages( $errors , 'warning', '' , false ); + $handler = new self(); + return smwfEncodeMessages( $handler->init( $parser->getTitle(), $parser->getOutput(), $params ) ); } + } diff --git a/includes/parserhooks/SemanticDataHandler.php b/includes/parserhooks/SemanticDataHandler.php new file mode 100644 index 0000000..b1e467c --- /dev/null +++ b/includes/parserhooks/SemanticDataHandler.php @@ -0,0 +1,137 @@ +<?php + +namespace SMW; + +use ParserOutput; +use SMWDIWikiPage; +use SMWPropertyValue; +use SMWSemanticData; +use MWException; +use SMWDataValueFactory; +use SMWDIProperty; + +/** + * Class ... + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @see http://semantic-mediawiki.org/wiki/Help:Properties_and_types#Silent_annotations_using_.23set + * @see http://www.semantic-mediawiki.org/wiki/Help:Setting_values + * + * @since 1.9 + * + * @file + * @ingroup SMW + * @ingroup ParserHooks + * + * @author mwjames + */ +class SemanticDataHandler { + + /** + * ... + */ + protected $semanticData; + + /** + * ... + */ + protected $errors = array(); + + protected $useExtensionData = false; + + /** + * ... + * + * @since 1.9 + */ + public function getErrors( ) { + return $this->errors; + + } + + /** + * ... + * + * @since 1.9 + */ + public function addPropertyObjectValue( SMWDIProperty $propertyDi, $dataItem ) { + $this->semanticData->addPropertyObjectValue( $propertyDi, $dataItem ); + } + + /** + * ... + * + * @since 1.9 + */ + public function addPropertyValueString( $propertyName, $valueString ) { + if ( $this->semanticData === array() ) { + throw new MWException( 'The subject container is not initialized' ); + } + + $propertyDv = SMWPropertyValue::makeUserProperty( $propertyName ); + $propertyDi = $propertyDv->getDataItem(); + + if ( !$propertyDi->isInverse() ) { + $valueDv = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, $valueString, + false, $this->semanticData->getSubject() ); + $this->addPropertyObjectValue( $propertyDi, $valueDv->getDataItem() ); + + // Take note of the error for storage (do this here and not in storage, thus avoiding duplicates). + if ( !$valueDv->isValid() ) { + $this->addPropertyObjectValue( new SMWDIProperty( SMWDIProperty::TYPE_ERROR ), + $propertyDi->getDiWikiPage() ); + $this->errors = array_merge( $this->errors, $valueDv->getErrors() ); + } + } else { + $this->errors[] = $this->msg( 'smw_noinvannot' )->inContentLanguage()->text(); + } + } + + /** + * ... + * + * @since 1.9 + */ + public function initSemanticData( ParserOutput $parserOutput, SMWDIWikiPage $subject ) { + if ( method_exists( $parserOutput, 'getExtensionData' ) && $this->useExtensionData ) { + $this->semanticData = $parserOutput->getExtensionData( 'smwdata' ); + } elseif ( isset( $parserOutput->mSMWData ) ) { + $this->semanticData = $parserOutput->mSMWData; + } + // Setup data container + if ( !( $this->semanticData instanceof SMWSemanticData ) ) { + $this->semanticData = new SMWSemanticData( $subject ); + } + } + + /** + * ... + * + * @since 1.9 + */ + public function storeSemanticData( ParserOutput $parserOutput ){ + if ( !( $this->semanticData instanceof SMWSemanticData ) ) { + throw new MWException( 'The semantic data container is not available' ); + } + if ( method_exists( $parserOutput, 'setExtensionData' ) && $this->useExtensionData ) { + $parserOutput->setExtensionData( 'smwdata', $this->semanticData ); + } else { + $parserOutput->mSMWData = $this->semanticData; + } + } + +} \ No newline at end of file diff --git a/includes/parserhooks/SetParser.php b/includes/parserhooks/SetParser.php index 5fe1f04..8a32cba 100644 --- a/includes/parserhooks/SetParser.php +++ b/includes/parserhooks/SetParser.php @@ -1,7 +1,12 @@ <?php namespace SMW; -use Parser, SMWParseData; + +use Parser; +use Title; +use ParserOutput; +use SMWDIWikiPage; +use SMW\ParserParameter; /** * Class for the 'set' parser functions. @@ -36,22 +41,47 @@ */ class SetParser { + protected $subject; + protected $parameters; + protected $semanticDataHandler; + protected $errors = array(); + /** * Method for handling the set parser function. * - * @since 1.5.3 + * @param + * @param + */ + public function init( Title $title, ParserOutput $parserOutput, $params ) { + $this->subject = new SMWDIWikiPage( + $title->getDBkey(), + $title->getNamespace(), + $title->getInterwiki() + ); + $this->parameters = new ParserParameter( $params ); + $this->semanticDataHandler = new SemanticDataHandler(); + + $this->semanticDataHandler->initSemanticData( $parserOutput, $this->subject ); + + foreach ( $this->parameters->toArray() as $property => $values ){ + foreach ( $values as $value ) { + $this->semanticDataHandler->addPropertyValueString( $property, $value ); + } + } + + $this->semanticDataHandler->storeSemanticData( $parserOutput ); + + return $this->semanticDataHandler->getErrors(); + } + + /** + * Method for handling the set parser function. * * @param Parser $parser */ public static function render( Parser &$parser ) { $params = func_get_args(); - array_shift( $params ); - - foreach ( ParserParameter::singleton()->getParameters( $params ) as $property => $values ){ - foreach ( $values as $value ) { - SMWParseData::addProperty( $property, $value, false, $parser, true ); - } - } - return ''; + $handler = new self(); + return smwfEncodeMessages( $handler->init( $parser->getTitle(), $parser->getOutput(), $params ) ); } } \ No newline at end of file diff --git a/includes/parserhooks/SubobjectHandler.php b/includes/parserhooks/SubobjectHandler.php index 2c95317..d9d0942 100644 --- a/includes/parserhooks/SubobjectHandler.php +++ b/includes/parserhooks/SubobjectHandler.php @@ -3,10 +3,10 @@ namespace SMW; use Parser; -use MWException; - -use SMWParseData; +use Title; +use ParserOutput; use SMWDIWikiPage; +use SMW\ParserParameter; /** * Class for the #subobject parser functions. @@ -37,29 +37,11 @@ */ class SubobjectHandler { - /** - * Defines a subobject instance - * @var $subobject - */ + protected $subject; + protected $parameters; + protected $semanticDataHandler; + protected $errors = array(); protected $subobject; - - /** - * Constructor which returns an immutable value object - * - * @since 1.9 - * - * @param SMWDIWikiPage $subject wikipage subject - * @param array $parameters array of parameters - * @param string $identifier named subobject identifier - */ - public function __construct( SMWDIWikiPage $subject, $parameters = '', $identifier = '' ) { - if ( !is_array( $parameters ) ) { - throw new MWException( 'Parameters array is not initialized' ); - } - - $this->subobject = new Subobject( $subject ); - $this->add( $parameters, $identifier ); - } /** * Returns the subobject instance @@ -80,7 +62,7 @@ * @param array $parameters array of parameters * @param string $identifier named subobject identifier */ - protected function add( $parameters, $identifier ) { + protected function add( $parameters, $identifier = '' ) { // An instance that don't use a named identifier will get an anonymous Id if ( $identifier === '' || $identifier === '-' ){ @@ -103,36 +85,45 @@ * * @since 1.9 * - * @param Parser $parser */ - public static function render( Parser &$parser ) { - - $params = func_get_args(); - array_shift( $params ); - - $mainSemanticData = SMWParseData::getSMWData( $parser ); - $subject = $mainSemanticData->getSubject(); - $name = str_replace( ' ', '_', trim( array_shift( $params ) ) ); - - // FIXME Use a class instance here - $parameters = ParserParameter::singleton()->getParameters( $params ); - - // Create handler instance and encapsulate the subobject instance by - // returning a value object - $handler = new self( $subject, $parameters, $name ); - - // Store subobject - SMWParseData::getSMWData( $parser )->addPropertyObjectValue( - $handler->getSubobject()->getProperty(), - $handler->getSubobject()->getContainer() + public function init( Title $title, ParserOutput $parserOutput, $params ) { + $this->subject = new SMWDIWikiPage( + $title->getDBkey(), + $title->getNamespace(), + $title->getInterwiki() ); - // Error output + $this->subobject = new Subobject( $this->subject ); + $this->parameters = new ParserParameter( $params ); + $this->semanticDataHandler = new SemanticDataHandler(); - // FIXME Use a real ErrorReport class where context determines the - // message language instead of having the object contain a translated - // error message; An error object should only hold a message key which at - // the time of the output is translated within context - return smwfEncodeMessages( $handler->getSubobject()->getErrors() ); + $this->semanticDataHandler->initSemanticData( $parserOutput, $this->subject ); + + $this->add( $this->parameters->toArray(), $this->parameters->getFirst() ); + + // Store subobject + $this->semanticDataHandler->addPropertyObjectValue( + $this->getSubobject()->getProperty(), + $this->getSubobject()->getContainer() + ); + + $this->semanticDataHandler->storeSemanticData( $parserOutput ); + + $this->errors = $this->semanticDataHandler->getErrors(); + $this->errors = $this->subobject->getErrors(); + + return $this->errors; } + + /** + * Method for handling the set parser function. + * + * @param Parser $parser + */ + public static function render( Parser &$parser ) { + $params = func_get_args(); + $handler = new self(); + return smwfEncodeMessages( $handler->init( $parser->getTitle(), $parser->getOutput(), $params ) ); + } + } \ No newline at end of file -- To view, visit https://gerrit.wikimedia.org/r/52598 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5d3cc9ff97f77acb05225658b1fb2f815b8b9f5f Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/SemanticMediaWiki Gerrit-Branch: master Gerrit-Owner: Mwjames <jamesin.hongkon...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits