diff options
Diffstat (limited to 'SemanticMediaWiki/includes')
290 files changed, 0 insertions, 54780 deletions
diff --git a/SemanticMediaWiki/includes/Aliases.php b/SemanticMediaWiki/includes/Aliases.php deleted file mode 100644 index 69d7ad4b..00000000 --- a/SemanticMediaWiki/includes/Aliases.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/** - * Indicate class aliases in a way PHPStorm and Eclipse understand. - * This is purely an IDE helper file, and is not loaded by the extension. - * - * @since 1.9 - * - * @file - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ - -throw new Exception( 'Not an actual source file' ); - -class SMWDataItemException extends SMW\DataItemException {} - -abstract class SMWStore extends SMW\Store {} - -class SMWSemanticData extends SMW\SemanticData {} - -class SMWDIWikiPage extends SMW\DIWikiPage {} - -class SMWDIConcept extends SMW\DIConcept {} - -class SMWDIProperty extends SMW\DIProperty {} - -class SMWDISerializer extends SMW\Serializers\QueryResultSerializer {} - -class SMWUpdateJob extends SMW\UpdateJob {} - -class SMWRefreshJob extends SMW\RefreshJob {} - -abstract class SMWResultPrinter extends SMW\ResultPrinter {} - -class SMWCategoryResultPrinter extends SMW\CategoryResultPrinter {} - -class SMWDSVResultPrinter extends SMW\DsvResultPrinter {} - -class SMWEmbeddedResultPrinter extends SMW\EmbeddedResultPrinter {} - -class SMWRDFResultPrinter extends SMW\RdfResultPrinter {} - -class SMWListResultPrinter extends SMW\ListResultPrinter {} - -interface SMWIResultPrinter extends SMW\QueryResultPrinter {} - -class SMWSparqlDatabase4Store extends SMW\SPARQLStore\FourstoreHttpDatabaseConnector {} - -class SMWSparqlDatabaseVirtuoso extends SMW\SPARQLStore\VirtuosoHttpDatabaseConnector {} - -class SMWSparqlStore extends SMW\SPARQLStore\SPARQLStore {} - -class SMWSparqlDatabase extends SMW\SPARQLStore\GenericHttpDatabaseConnector {} diff --git a/SemanticMediaWiki/includes/ContentParser.php b/SemanticMediaWiki/includes/ContentParser.php deleted file mode 100644 index fb06c3b3..00000000 --- a/SemanticMediaWiki/includes/ContentParser.php +++ /dev/null @@ -1,231 +0,0 @@ -<?php - -namespace SMW; - -use ParserOptions; -use Revision; -use Parser; -use Title; -use User; - -/** - * Fetches the ParserOutput either by parsing an invoked text component, - * re-parsing a text revision, or accessing the ContentHandler to generate a - * ParserOutput object - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class ContentParser { - - /** @var Title */ - protected $title; - - /** @var Parser */ - protected $parser = null; - - /** @var ParserOutput */ - protected $parserOutput = null; - - /** @var Revision */ - protected $revision = null; - - /** @var array */ - protected $errors = array(); - - /** - * @var boolean - */ - private $enabledToUseContentHandler = true; - - /** - * @note Injecting new Parser() alone will not yield an expected result and - * doing new Parser( $GLOBALS['wgParserConf'] brings no benefits therefore - * we stick to the GLOBAL as fallback if no parser is injected. - * - * @since 1.9 - * - * @param Title $title - * @param Parser|null $parser - */ - public function __construct( Title $title, Parser $parser = null ) { - $this->title = $title; - $this->parser = $parser; - - if ( $this->parser === null ) { - $this->parser = $GLOBALS['wgParser']; - } - } - - /** - * @since 1.9.1 - * - * @return ContentParser - */ - public function setRevision( Revision $revision = null ) { - $this->revision = $revision; - return $this; - } - - /** - * @bug 62856 and #212 - * - * @since 2.0 - */ - public function forceToUseParser() { - $this->enabledToUseContentHandler = false; - } - - /** - * @since 1.9 - * - * @return Title - */ - public function getTitle() { - return $this->title; - } - - /** - * @since 1.9 - * - * @return ParserOutput|null - */ - public function getOutput() { - return $this->parserOutput; - } - - /** - * @since 1.9 - * - * @return array - */ - public function getErrors() { - return $this->errors; - } - - /** - * Generates or fetches the ParserOutput object from an appropriate source - * - * @since 1.9 - * - * @param string|null $text - * - * @return ContentParser - */ - public function parse( $text = null ) { - - if ( $text !== null ) { - return $this->parseText( $text ); - } - - if ( $this->hasContentHandler() && $this->enabledToUseContentHandler ) { - return $this->fetchFromContent(); - } - - return $this->fetchFromParser(); - } - - protected function parseText( $text ) { - Profiler::In( __METHOD__ ); - - $this->parserOutput = $this->parser->parse( - $text, - $this->getTitle(), - $this->makeParserOptions() - ); - - Profiler::Out( __METHOD__ ); - return $this; - } - - /** - * @note Revision ID must be passed to the parser output to - * get revision variables correct - * - * @note If no content is available create an empty object - */ - protected function fetchFromContent() { - Profiler::In( __METHOD__ ); - - if ( $this->getRevision() === null ) { - return $this->msgForNullRevision(); - } - - $content = $this->getRevision()->getContent( Revision::RAW ); - - if ( !$content ) { - $content = $this->getRevision()->getContentHandler()->makeEmptyContent(); - } - - $this->parserOutput = $content->getParserOutput( - $this->getTitle(), - $this->getRevision()->getId(), - null, - true - ); - - Profiler::Out( __METHOD__ ); - return $this; - } - - protected function fetchFromParser() { - Profiler::In( __METHOD__ ); - - if ( $this->getRevision() === null ) { - return $this->msgForNullRevision(); - } - - $this->parserOutput = $this->parser->parse( - $this->getRevision()->getText(), - $this->getTitle(), - $this->makeParserOptions(), - true, - true, - $this->getRevision()->getID() - ); - - Profiler::Out( __METHOD__ ); - return $this; - } - - protected function msgForNullRevision( $fname = __METHOD__ ) { - $this->errors = array( $fname . " No revision available for {$this->getTitle()->getPrefixedDBkey()}" ); - return $this; - } - - protected function makeParserOptions() { - - $user = null; - - if ( $this->getRevision() !== null ) { - $user = User::newFromId( $this->getRevision()->getUser() ); - } - - return new ParserOptions( $user ); - } - - protected function getRevision() { - - if ( $this->revision instanceOf Revision ) { - return $this->revision; - } - - // Revision::READ_NORMAL is not specified in MW 1.19 - if ( defined( 'Revision::READ_NORMAL' ) ) { - $this->revision = Revision::newFromTitle( $this->getTitle(), false, Revision::READ_NORMAL ); - } else { - $this->revision = Revision::newFromTitle( $this->getTitle() ); - } - - return $this->revision; - } - - protected function hasContentHandler() { - return defined( 'CONTENT_MODEL_WIKITEXT' ); - } - -} diff --git a/SemanticMediaWiki/includes/DataTypeRegistry.php b/SemanticMediaWiki/includes/DataTypeRegistry.php deleted file mode 100644 index 45a78ee4..00000000 --- a/SemanticMediaWiki/includes/DataTypeRegistry.php +++ /dev/null @@ -1,398 +0,0 @@ -<?php - -namespace SMW; - -use SMWDataItem as DataItem; - -/** - * DataTypes registry class - * - * Registry class that manages datatypes, and provides various methods to access - * the information - * - * @ingroup SMWDataValues - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author mwjames - */ -class DataTypeRegistry { - - /** @var DataTypeRegistry */ - protected static $instance = null; - - /** - * Array of type labels indexed by type ids. Used for datatype resolution. - * - * @var string[] - */ - private $typeLabels = array(); - - /** - * Array of ids indexed by type aliases. Used for datatype resolution. - * - * @var string[] - */ - private $typeAliases = array(); - - /** - * Array of class names for creating new SMWDataValue, indexed by type - * id. - * - * @var string[] - */ - private $typeClasses; - - /** - * Array of data item classes, indexed by type id. - * - * @var integer[] - */ - private $typeDataItemIds; - - /** - * Lookup map that allows finding a datatype id given a label or alias. - * All labels and aliases (ie array keys) are stored lower case. - * - * @var string[] - */ - private $typeByLabelOrAliasLookup = array(); - - /** - * Array of default types to use for making datavalues for dataitems. - * - * @var string[] - */ - private $defaultDataItemTypeIds = array( - DataItem::TYPE_BLOB => '_txt', // Text type - DataItem::TYPE_URI => '_uri', // URL/URI type - DataItem::TYPE_WIKIPAGE => '_wpg', // Page type - DataItem::TYPE_NUMBER => '_num', // Number type - DataItem::TYPE_TIME => '_dat', // Time type - DataItem::TYPE_BOOLEAN => '_boo', // Boolean type - DataItem::TYPE_CONTAINER => '_rec', // Value list type (replacing former nary properties) - DataItem::TYPE_GEO => '_geo', // Geographical coordinates - DataItem::TYPE_CONCEPT => '__con', // Special concept page type - DataItem::TYPE_PROPERTY => '__pro', // Property type - - // If either of the following two occurs, we want to see a PHP error: - //DataItem::TYPE_NOTYPE => '', - //DataItem::TYPE_ERROR => '', - ); - - /** - * Returns a DataTypeRegistry instance - * - * @since 1.9 - * - * @return DataTypeRegistry - */ - public static function getInstance() { - - if ( self::$instance === null ) { - - self::$instance = new self( - $GLOBALS['smwgContLang']->getDatatypeLabels(), - $GLOBALS['smwgContLang']->getDatatypeAliases() - ); - - self::$instance->initDatatypes(); - } - - return self::$instance; - } - - /** - * Resets the DataTypeRegistry instance - * - * @since 1.9 - */ - public static function clear() { - self::$instance = null; - } - - /** - * @since 1.9.0.2 - * - * @param array $typeLabels - * @param array $typeAliases - */ - public function __construct( array $typeLabels, array $typeAliases ) { - foreach ( $typeLabels as $typeId => $typeLabel ) { - $this->registerTypeLabel( $typeId, $typeLabel ); - } - - foreach ( $typeAliases as $typeAlias => $typeId ) { - $this->registerDataTypeAlias( $typeId, $typeAlias ); - } - } - - /** - * Get the preferred data item ID for a given type. The ID defines the - * appropriate data item class for processing data of this type. See - * DataItem for possible values. - * - * @note SMWDIContainer is a pseudo dataitem type that is used only in - * data input methods, but not for storing data. Types that work with - * SMWDIContainer use SMWDIWikiPage as their DI type. (Since SMW 1.8) - * - * @param $typeId string id string for the given type - * @return integer data item ID - */ - public function getDataItemId( $typeId ) { - if ( isset( $this->typeDataItemIds[ $typeId ] ) ) { - return $this->typeDataItemIds[ $typeId ]; - } - - return DataItem::TYPE_NOTYPE; - } - - /** - * @since 2.0 - * - * @param string - * @return boolean - */ - public function isKnownTypeId( $typeId ) { - return isset( $this->typeDataItemIds[ $typeId ] ); - } - - /** - * A function for registering/overwriting datatypes for SMW. Should be - * called from within the hook 'smwInitDatatypes'. - * - * @param $id string type ID for which this datatype is registered - * @param $className string name of the according subclass of SMWDataValue - * @param $dataItemId integer ID of the data item class that this data value uses, see DataItem - * @param $label mixed string label or false for types that cannot be accessed by users - */ - public function registerDataType( $id, $className, $dataItemId, $label = false ) { - $this->typeClasses[$id] = $className; - $this->typeDataItemIds[$id] = $dataItemId; - - if ( $label !== false ) { - $this->registerTypeLabel( $id, $label ); - } - } - - private function registerTypeLabel( $typeId, $typeLabel ) { - $this->typeLabels[$typeId] = $typeLabel; - $this->addTextToIdLookupMap( $typeId, $typeLabel ); - } - - private function addTextToIdLookupMap( $dataTypeId, $text ) { - $this->typeByLabelOrAliasLookup[strtolower($text)] = $dataTypeId; - } - - /** - * Add a new alias label to an existing datatype id. Note that every ID - * should have a primary label, either provided by SMW or registered with - * registerDataType(). This function should be called from within the hook - * 'smwInitDatatypes'. - * - * @param string $typeId - * @param string $typeAlias - */ - public function registerDataTypeAlias( $typeId, $typeAlias ) { - $this->typeAliases[$typeAlias] = $typeId; - $this->addTextToIdLookupMap( $typeId, $typeAlias ); - } - - /** - * Look up the ID that identifies the datatype of the given label - * internally. This id is used for all internal operations. If the - * label does not belong to a known type, the empty string is returned. - * - * The lookup is case insensitive. - * - * @param string $label - * - * @return string - */ - public function findTypeId( $label ) { - $label = strtolower( $label ); - - if ( isset( $this->typeByLabelOrAliasLookup[$label] ) ) { - return $this->typeByLabelOrAliasLookup[$label]; - } - - return ''; - } - - /** - * Get the translated user label for a given internal ID. If the ID does - * not have a label associated with it in the current language, the - * empty string is returned. This is the case both for internal type ids - * and for invalid (unknown) type ids, so this method cannot be used to - * distinguish the two. - * - * @param string $id - * - * @return string - */ - public function findTypeLabel( $id ) { - if ( isset( $this->typeLabels[ $id ] ) ) { - return $this->typeLabels[ $id ]; - } - - // internal type without translation to user space; - // might also happen for historic types after an upgrade -- - // alas, we have no idea what the former label would have been - return ''; - } - - /** - * Return an array of all labels that a user might specify as the type of - * a property, and that are internal (i.e. not user defined). No labels are - * returned for internal types without user labels (e.g. the special types - * for some special properties), and for user defined types. - * - * @return array - */ - public function getKnownTypeLabels() { - return $this->typeLabels; - } - - /** - * Returns a default DataItemId - * - * @since 1.9 - * - * @param string $diType - * - * @return string|null - */ - public function getDefaultDataItemTypeId( $diType ) { - - if ( isset( $this->defaultDataItemTypeIds[ $diType ] ) ) { - return $this->defaultDataItemTypeIds[ $diType ]; - } - - return null; - } - - /** - * Returns a class based on a typeId - * - * @since 1.9 - * - * @param string $typeId - * - * @return string|null - */ - public function getDataTypeClassById( $typeId ) { - if ( $this->hasDataTypeClassById( $typeId ) ) { - return $this->typeClasses[ $typeId ]; - } - - return null; - } - - /** - * Whether a datatype class is registered for a particular typeId - * - * @since 1.9 - * - * @param string $typeId - * - * @return boolean - */ - public function hasDataTypeClassById( $typeId ) { - return isset( $this->typeClasses[ $typeId ] ); - } - - /** - * Gather all available datatypes and label<=>id<=>datatype - * associations. This method is called before most methods of this - * factory. - */ - protected function initDatatypes() { - // Setup built-in datatypes. - // NOTE: all ids must start with underscores, where two underscores indicate - // truly internal (non user-acceptable types). All others should also get a - // translation in the language files, or they won't be available for users. - $this->typeClasses = array( - '_txt' => 'SMWStringValue', // Text type - '_cod' => 'SMWStringValue', // Code type - '_str' => 'SMWStringValue', // DEPRECATED Will vanish after SMW 1.9; use '_txt' - '_ema' => 'SMWURIValue', // Email type - '_uri' => 'SMWURIValue', // URL/URI type - '_anu' => 'SMWURIValue', // Annotation URI type - '_tel' => 'SMWURIValue', // Phone number (URI) type - '_wpg' => 'SMWWikiPageValue', // Page type - '_wpp' => 'SMWWikiPageValue', // Property page type TODO: make available to user space - '_wpc' => 'SMWWikiPageValue', // Category page type TODO: make available to user space - '_wpf' => 'SMWWikiPageValue', // Form page type for Semantic Forms - '_num' => 'SMWNumberValue', // Number type - '_tem' => 'SMWTemperatureValue', // Temperature type - '_dat' => 'SMWTimeValue', // Time type - '_boo' => 'SMWBoolValue', // Boolean type - '_rec' => 'SMWRecordValue', // Value list type (replacing former nary properties) - '_qty' => 'SMWQuantityValue', // Type for numbers with units of measurement - // Special types are not avaialble directly for users (and have no local language name): - '__typ' => 'SMWTypesValue', // Special type page type - '__pls' => 'SMWPropertyListValue', // Special type list for decalring _rec properties - '__con' => 'SMWConceptValue', // Special concept page type - '__sps' => 'SMWStringValue', // Special string type - '__spu' => 'SMWURIValue', // Special uri type - '__sob' => 'SMWWikiPageValue', // Special subobject type - '__sup' => 'SMWWikiPageValue', // Special subproperty type - '__suc' => 'SMWWikiPageValue', // Special subcategory type - '__spf' => 'SMWWikiPageValue', // Special Form page type for Semantic Forms - '__sin' => 'SMWWikiPageValue', // Special instance of type - '__red' => 'SMWWikiPageValue', // Special redirect type - '__err' => 'SMWErrorValue', // Special error type - '__imp' => 'SMWImportValue', // Special import vocabulary type - '__pro' => 'SMWPropertyValue', // Property type (possibly predefined, no always based on a page) - '__key' => 'SMWStringValue', // Sort key of a page - ); - - $this->typeDataItemIds = array( - '_txt' => DataItem::TYPE_BLOB, // Text type - '_cod' => DataItem::TYPE_BLOB, // Code type - '_str' => DataItem::TYPE_BLOB, // DEPRECATED Will vanish after SMW 1.9; use '_txt' - '_ema' => DataItem::TYPE_URI, // Email type - '_uri' => DataItem::TYPE_URI, // URL/URI type - '_anu' => DataItem::TYPE_URI, // Annotation URI type - '_tel' => DataItem::TYPE_URI, // Phone number (URI) type - '_wpg' => DataItem::TYPE_WIKIPAGE, // Page type - '_wpp' => DataItem::TYPE_WIKIPAGE, // Property page type TODO: make available to user space - '_wpc' => DataItem::TYPE_WIKIPAGE, // Category page type TODO: make available to user space - '_wpf' => DataItem::TYPE_WIKIPAGE, // Form page type for Semantic Forms - '_num' => DataItem::TYPE_NUMBER, // Number type - '_tem' => DataItem::TYPE_NUMBER, // Temperature type - '_dat' => DataItem::TYPE_TIME, // Time type - '_boo' => DataItem::TYPE_BOOLEAN, // Boolean type - '_rec' => DataItem::TYPE_WIKIPAGE, // Value list type (replacing former nary properties) - '_geo' => DataItem::TYPE_GEO, // Geographical coordinates - '_gpo' => DataItem::TYPE_BLOB, // Geographical polygon - '_qty' => DataItem::TYPE_NUMBER, // Type for numbers with units of measurement - // Special types are not available directly for users (and have no local language name): - '__typ' => DataItem::TYPE_URI, // Special type page type - '__pls' => DataItem::TYPE_BLOB, // Special type list for decalring _rec properties - '__con' => DataItem::TYPE_CONCEPT, // Special concept page type - '__sps' => DataItem::TYPE_BLOB, // Special string type - '__spu' => DataItem::TYPE_URI, // Special uri type - '__sob' => DataItem::TYPE_WIKIPAGE, // Special subobject type - '__sup' => DataItem::TYPE_WIKIPAGE, // Special subproperty type - '__suc' => DataItem::TYPE_WIKIPAGE, // Special subcategory type - '__spf' => DataItem::TYPE_WIKIPAGE, // Special Form page type for Semantic Forms - '__sin' => DataItem::TYPE_WIKIPAGE, // Special instance of type - '__red' => DataItem::TYPE_WIKIPAGE, // Special redirect type - '__err' => DataItem::TYPE_ERROR, // Special error type - '__imp' => DataItem::TYPE_BLOB, // Special import vocabulary type - '__pro' => DataItem::TYPE_PROPERTY, // Property type (possibly predefined, no always based on a page) - '__key' => DataItem::TYPE_BLOB, // Sort key of a page - ); - - // Deprecated since 1.9 - wfRunHooks( 'smwInitDatatypes' ); - - // Since 1.9 - wfRunHooks( 'SMW::DataType::initTypes' ); - } - -} diff --git a/SemanticMediaWiki/includes/DataValueFactory.php b/SemanticMediaWiki/includes/DataValueFactory.php deleted file mode 100644 index 723a248a..00000000 --- a/SemanticMediaWiki/includes/DataValueFactory.php +++ /dev/null @@ -1,255 +0,0 @@ -<?php - -namespace SMW; - -use SMWDataItem; -use SMWErrorValue; -use SMWLanguage; -use SMWPropertyValue; -use SMWDIError; - -/** - * Factory class for creating SMWDataValue objects for supplied types or - * properties and data values. - * - * The class has the main entry point newTypeIdValue(), which creates a new - * datavalue object, possibly with preset user values, captions and - * property names. To create suitable datavalues for a given property, the - * method newPropertyObjectValue() can be used. - * - * @ingroup SMWDataValues - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author mwjames - */ -class DataValueFactory { - - /** @var DataTypeRegistry */ - protected $dataTypeRegistry = null; - - /** - * FIXME In order to remove wfMessage dependency, a message formatter - * should be injected - * - * @note The constructor is made protected until all static/deprecated - * methods are removed - * - * @since 1.9 - * - * @param DataTypeRegistry|null $dataTypeRegistry - */ - protected function __construct( DataTypeRegistry $dataTypeRegistry = null ) { - $this->dataTypeRegistry = $dataTypeRegistry; - } - - /** - * @since 1.9 - * - * @return DataValueFactory - */ - public static function getInstance() { - return new self( DataTypeRegistry::getInstance() ); - } - - /** - * Create a value from a type id. If no $value is given, an empty - * container is created, the value of which can be set later on. - * - * @param $typeId string id string for the given type - * @param $valueString mixed user value string, or false if unknown - * @param $caption mixed user-defined caption, or false if none given - * @param $property SMWDIProperty property object for which this value is made, or null - * @param $contextPage SMWDIWikiPage that provides a context for parsing the value string, or null - * - * @return SMWDataValue - */ - public static function newTypeIdValue( $typeId, $valueString = false, $caption = false, - $property = null, $contextPage = null ) { - - $dataTypeRegistry = DataTypeRegistry::getInstance(); - - if ( $dataTypeRegistry->hasDataTypeClassById( $typeId ) ) { - $class = $dataTypeRegistry->getDataTypeClassById( $typeId ); - $result = new $class( $typeId ); - } else { - return new SMWErrorValue( $typeId, - wfMessage( 'smw_unknowntype', $typeId )->inContentLanguage()->text(), - $valueString, $caption ); - } - - if ( !is_null( $property ) ) { - $result->setProperty( $property ); - } - - if ( !is_null( $contextPage ) ) { - $result->setContextPage( $contextPage ); - } - - if ( $valueString !== false ) { - $result->setUserValue( $valueString, $caption ); - } - - return $result; - } - - /** - * Create a value for a data item. - * - * @param $dataItem SMWDataItem - * @param $property mixed null or SMWDIProperty property object for which this value is made - * @param $caption mixed user-defined caption, or false if none given - * - * @return SMWDataValue - */ - public static function newDataItemValue( SMWDataItem $dataItem, DIProperty $property = null, $caption = false ) { - - if ( $property !== null ) { - $typeId = $property->findPropertyTypeID(); - } else { - $typeId = DataTypeRegistry::getInstance()->getDefaultDataItemTypeId( $dataItem->getDiType() ); - } - - $result = self::newTypeIdValue( $typeId, false, $caption, $property ); - $result->setDataItem( $dataItem ); - - if ( $caption !== false ) { - $result->setCaption( $caption ); - } - - return $result; - } - - /** - * Create a value for the given property, provided as an SMWDIProperty - * object. If no value is given, an empty container is created, the - * value of which can be set later on. - * - * @param $property SMWDIProperty property object for which this value is made - * @param $valueString mixed user value string, or false if unknown - * @param $caption mixed user-defined caption, or false if none given - * @param $contextPage SMWDIWikiPage that provides a context for parsing the value string, or null - * - * @return SMWDataValue - */ - public static function newPropertyObjectValue( DIProperty $property, $valueString = false, - $caption = false, $contextPage = null ) { - - $typeId = $property->isInverse() ? '_wpg' : $property->findPropertyTypeID(); - return self::newTypeIdValue( $typeId, $valueString, $caption, $property, $contextPage ); - } - - /** - * This factory method returns a data value object from a given property, - * value string. It is intended to be used on user input to allow to - * turn a property and value strings into a data value object. - * - * @since 1.9 - * - * @param string $propertyName property string - * @param string $valueString user value string - * @param mixed $caption user-defined caption - * @param SMWDIWikiPage|null $contextPage context for parsing the value string - * - * @return SMWDataValue - */ - public function newPropertyValue( $propertyName, $valueString, - $caption = false, DIWikiPage $contextPage = null ) { - - Profiler::In( __METHOD__, true ); - - $propertyDV = SMWPropertyValue::makeUserProperty( $propertyName ); - - if ( !$propertyDV->isValid() ) { - Profiler::Out( __METHOD__, true ); - return $propertyDV; - } - - $propertyDI = $propertyDV->getDataItem(); - - if ( $propertyDI instanceof SMWDIError ) { - Profiler::Out( __METHOD__, true ); - return $propertyDV; - } - - if ( $propertyDI instanceof DIProperty && !$propertyDI->isInverse() ) { - $dataValue = self::newPropertyObjectValue( - $propertyDI, - $valueString, - $caption, - $contextPage - ); - } else if ( $propertyDI instanceof DIProperty && $propertyDI->isInverse() ) { - $dataValue = new SMWErrorValue( $propertyDV->getPropertyTypeID(), - wfMessage( 'smw_noinvannot' )->inContentLanguage()->text(), - $valueString, $caption - ); - } else { - $dataValue = new SMWErrorValue( $propertyDV->getPropertyTypeID(), - wfMessage( 'smw-property-name-invalid', $propertyName )->inContentLanguage()->text(), - $valueString, $caption - ); - } - - Profiler::Out( __METHOD__, true ); - return $dataValue; - } - - /** - * Deprecated since 1.9 and be removed in 1.10, use DataTypeRegistry instead - * - * @since 1.9 - */ - public static function registerDatatype( $id, $className, $dataItemId, $label = false ) { - DataTypeRegistry::getInstance()->registerDataType( $id, $className, $dataItemId, $label ); - } - - /** - * Deprecated since 1.9 and be removed in 1.10, use DataTypeRegistry instead - * - * @since 1.9 - */ - public static function registerDatatypeAlias( $id, $label ) { - DataTypeRegistry::getInstance()->registerDataTypeAlias( $id, $label ); - } - - /** - * Deprecated since 1.9 and be removed in 1.10, use DataTypeRegistry instead - * - * @since 1.9 - */ - public static function findTypeID( $label ) { - return DataTypeRegistry::getInstance()->findTypeId( $label ); - } - - /** - * Deprecated since 1.9 and be removed in 1.10, use DataTypeRegistry instead - * - * @since 1.9 - */ - public static function findTypeLabel( $id ) { - return DataTypeRegistry::getInstance()->findTypeLabel( $id ); - } - - /** - * Deprecated since 1.9 and be removed in 1.10, use DataTypeRegistry instead - * - * @since 1.9 - */ - public static function getKnownTypeLabels() { - return DataTypeRegistry::getInstance()->getKnownTypeLabels(); - } - - /** - * Deprecated since 1.9 and be removed in 1.10, use DataTypeRegistry instead - * - * @since 1.9 - */ - public static function getDataItemId( $typeId ) { - return DataTypeRegistry::getInstance()->getDataItemId( $typeId ); - } - -} diff --git a/SemanticMediaWiki/includes/Defines.php b/SemanticMediaWiki/includes/Defines.php deleted file mode 100644 index 550ed9e5..00000000 --- a/SemanticMediaWiki/includes/Defines.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php -/** - * Constants relevant to Semantic MediaWiki - * - * @file - */ - -/** - * @ingroup Constants - * @ingroup SMW - */ - -/**@{ - * SMW\ResultPrinter related constants that define - * how/if headers should be displayed - */ -define( 'SMW_HEADERS_SHOW', 2 ); -define( 'SMW_HEADERS_PLAIN', 1 ); -define( 'SMW_HEADERS_HIDE', 0 ); // Used to be "false" hence use "0" to support extensions that still assume this. -/**@}*/ - -/**@{ - * Constants for denoting output modes in many functions: HTML or Wiki? - * "File" is for printing results into stand-alone files (e.g. building RSS) - * and should be treated like HTML when building single strings. Only query - * printers tend to have special handling for that. - */ -define( 'SMW_OUTPUT_HTML', 1 ); -define( 'SMW_OUTPUT_WIKI', 2 ); -define( 'SMW_OUTPUT_FILE', 3 ); -/**@}*/ - -/**@{ - * Constants for displaying the factbox - */ -define( 'SMW_FACTBOX_HIDDEN', 1 ); -define( 'SMW_FACTBOX_SPECIAL', 2 ); -define( 'SMW_FACTBOX_NONEMPTY', 3 ); -define( 'SMW_FACTBOX_SHOWN', 5 ); -/**@}*/ - -/**@{ - * Constants for regulating equality reasoning - */ -define( 'SMW_EQ_NONE', 0 ); -define( 'SMW_EQ_SOME', 1 ); -define( 'SMW_EQ_FULL', 2 ); -/**@}*/ - -/**@{ - * Flags to classify available query descriptions, - * used to enable/disable certain features - */ -define( 'SMW_PROPERTY_QUERY', 1 ); // [[some property::...]] -define( 'SMW_CATEGORY_QUERY', 2 ); // [[Category:...]] -define( 'SMW_CONCEPT_QUERY', 4 ); // [[Concept:...]] -define( 'SMW_NAMESPACE_QUERY', 8 ); // [[User:+]] etc. -define( 'SMW_CONJUNCTION_QUERY', 16 ); // any conjunctions -define( 'SMW_DISJUNCTION_QUERY', 32 ); // any disjunctions (OR, ||) -define( 'SMW_ANY_QUERY', 0xFFFFFFFF ); // subsumes all other options -/**@}*/ - -/**@{ - * Constants for defining which concepts to show only if cached - */ -define( 'CONCEPT_CACHE_ALL', 4 ); // show concept elements anywhere only if cached -define( 'CONCEPT_CACHE_HARD', 1 ); // show without cache if concept is not harder than permitted inline queries -define( 'CONCEPT_CACHE_NONE', 0 ); // show all concepts even without any cache -/**@}*/ - -/**@{ - * Constants for identifying javascripts as used in SMWOutputs - */ -/// @deprecated Use module 'ext.smw.tooltips', see SMW_Ouptuts.php. Vanishes in SMW 1.7 at the latest. -define( 'SMW_HEADER_TOOLTIP', 2 ); -/// @deprecated Module removed. Vanishes in SMW 1.7 at the latest. -define( 'SMW_HEADER_SORTTABLE', 3 ); -/// @deprecated Use module 'ext.smw.style', see SMW_Ouptuts.php. Vanishes in SMW 1.7 at the latest. -define( 'SMW_HEADER_STYLE', 4 ); -/**@}*/ - -/**@{ - * Comparators for datavalues - */ -define( 'SMW_CMP_EQ', 1 ); // Matches only datavalues that are equal to the given value. -define( 'SMW_CMP_LEQ', 2 ); // Matches only datavalues that are less or equal than the given value. -define( 'SMW_CMP_GEQ', 3 ); // Matches only datavalues that are greater or equal to the given value. -define( 'SMW_CMP_NEQ', 4 ); // Matches only datavalues that are unequal to the given value. -define( 'SMW_CMP_LIKE', 5 ); // Matches only datavalues that are LIKE the given value. -define( 'SMW_CMP_NLKE', 6 ); // Matches only datavalues that are not LIKE the given value. -define( 'SMW_CMP_LESS', 7 ); // Matches only datavalues that are less than the given value. -define( 'SMW_CMP_GRTR', 8 ); // Matches only datavalues that are greater than the given value. -/**@}*/ - -/**@{ - * Constants for date formats (using binary encoding of nine bits: - * 3 positions x 3 interpretations) - */ -define( 'SMW_MDY', 785 ); // Month-Day-Year -define( 'SMW_DMY', 673 ); // Day-Month-Year -define( 'SMW_YMD', 610 ); // Year-Month-Day -define( 'SMW_YDM', 596 ); // Year-Day-Month -define( 'SMW_MY', 97 ); // Month-Year -define( 'SMW_YM', 76 ); // Year-Month -define( 'SMW_Y', 9 ); // Year -define( 'SMW_YEAR', 1 ); // an entered digit can be a year -define( 'SMW_DAY', 2 ); // an entered digit can be a year -define( 'SMW_MONTH', 4 ); // an entered digit can be a month -define( 'SMW_DAY_MONTH_YEAR', 7 ); // an entered digit can be a day, month or year -define( 'SMW_DAY_YEAR', 3 ); // an entered digit can be either a month or a year -/**@}*/
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/FormatFactory.php b/SemanticMediaWiki/includes/FormatFactory.php deleted file mode 100644 index ea459f1d..00000000 --- a/SemanticMediaWiki/includes/FormatFactory.php +++ /dev/null @@ -1,200 +0,0 @@ -<?php - -namespace SMW; - -use MWException; - -/** - * Factory for "result formats", ie classes implementing QueryResultPrinter. - * - * @since 1.9 - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -final class FormatFactory { - - /** - * Returns an instance of the factory. - * - * @since 1.9 - * - * @return FormatFactory - */ - public static function singleton() { - static $instance = null; - - if ( $instance === null ) { - $instance = new self(); - - global $smwgResultFormats, $smwgResultAliases; - - foreach ( $smwgResultFormats as $formatName => $printerClass ) { - $instance->registerFormat( $formatName, $printerClass ); - } - - foreach ( $smwgResultAliases as $formatName => $aliases ) { - $instance->registerAliases( $formatName, $aliases ); - } - } - - return $instance; - } - - /** - * Constructor. Protected to enforce use of singleton. - */ - //protected function __construct() {} // TODO: enable when tests can deal w/ it - - /** - * Format registry. Format names pointing to their associated QueryResultPrinter implementing classes. - * - * @since 1.9 - * - * @var array - */ - protected $formats = array(); - - /** - * Form alias registry. Aliases pointing to their canonical format name. - * - * @since 1.9 - * - * @var array - */ - protected $aliases = array(); - - /** - * Registers a format. - * If there is a format already with the provided name, - * it will be overridden with the newly provided data. - * - * @since 1.9 - * - * @param string $formatName - * @param string $class - * - * @throws MWException - */ - public function registerFormat( $formatName, $class ) { - if ( !is_string( $formatName ) ) { - throw new MWException( 'Format names can only be of type string' ); - } - - if ( !is_string( $class ) ) { - throw new MWException( 'Format class names can only be of type string' ); - } - - $this->formats[$formatName] = $class; - } - - /** - * Registers the provided format aliases. - * If an aliases is already registered, it will - * be overridden with the newly provided data. - * - * @since 1.9 - * - * @param string $formatName - * @param array $aliases - * - * @throws MWException - */ - public function registerAliases( $formatName, array $aliases ) { - if ( !is_string( $formatName ) ) { - throw new MWException( 'Format names can only be of type string' ); - } - - foreach ( $aliases as $alias ) { - if ( !is_string( $alias ) ) { - throw new MWException( 'Format aliases can only be of type string' ); - } - - $this->aliases[$alias] = $formatName; - } - } - - /** - * Returns the canonical format names. - * - * @since 1.9 - * - * @return array of string - */ - public function getFormats() { - return array_keys( $this->formats ); - } - - /** - * Returns if there is a format or format alias with the provided name. - * - * @since 1.9 - * - * @param string $formatName Format name or alias - * - * @return boolean - */ - public function hasFormat( $formatName ) { - $formatName = $this->getCanonicalName( $formatName ); - return array_key_exists( $formatName, $this->formats ); - } - - /** - * Returns a new instance of the handling result printer for the provided format. - * - * @since 1.9 - * - * @param string $formatName - * - * @return QueryResultPrinter - */ - public function getPrinter( $formatName ) { - $class = $this->getPrinterClass( $formatName ); - return new $class( $formatName ); - } - - /** - * Returns the QueryResultPrinter implementing class that is the printer for the provided format. - * - * @since 1.9 - * - * @param string $formatName Format name or alias - * - * @return string - * @throws MWException - */ - protected function getPrinterClass( $formatName ) { - $formatName = $this->getCanonicalName( $formatName ); - - if ( !array_key_exists( $formatName, $this->formats ) ) { - throw new MWException( 'Unknown format name "' . $formatName . '" has no associated printer class' ); - } - - return $this->formats[$formatName]; - } - - /** - * Resolves format aliases into their associated canonical format name. - * - * @since 1.9 - * - * @param string $formatName Format name or alias - * - * @return string - * @throws MWException - */ - public function getCanonicalName( $formatName ) { - if ( !is_string( $formatName ) ) { - throw new MWException( 'Format names can only be of type string' ); - } - - if ( array_key_exists( $formatName, $this->aliases ) ) { - $formatName = $this->aliases[$formatName]; - } - - return $formatName; - } - -} diff --git a/SemanticMediaWiki/includes/GlobalFunctions.php b/SemanticMediaWiki/includes/GlobalFunctions.php deleted file mode 100644 index 3eb304da..00000000 --- a/SemanticMediaWiki/includes/GlobalFunctions.php +++ /dev/null @@ -1,300 +0,0 @@ -<?php - -use SMW\NamespaceManager; -use SMW\SPARQLStore\SparqlDBConnectionProvider; - -/** - * Global functions specified and used by Semantic MediaWiki. In general, it is - * tried to fit functions in suitable classes as static methods if they clearly - * belong to some particular sub-function of SMW. Most functions here are used - * in diverse contexts so that they do not have fonud a place in any such class - * yet. - * @file - * @ingroup SMW - */ - -/** - * @see NamespaceExaminer - * - * @return boolean - * @deprecated since 1.9 and will be removed in 1.11 - */ -function smwfIsSemanticsProcessed( $namespace ) { - return \SMW\NamespaceExaminer::getInstance()->isSemanticEnabled( $namespace ); -} - -/** - * Takes a title text and turns it safely into its DBKey. This function - * reimplements most of the title normalization as done in Title.php in order - * to achieve conversion with less overhead. The official code could be called - * here if more advanced normalization is needed. - * - * @param string $text - */ -function smwfNormalTitleDBKey( $text ) { - global $wgCapitalLinks; - - $text = trim( $text ); - - if ( $wgCapitalLinks ) { - $text = ucfirst( $text ); - } - - return str_replace( ' ', '_', $text ); -} - -/** - * Takes a text and turns it into a normalised version. This function - * reimplements the title normalization as done in Title.php in order to - * achieve conversion with less overhead. The official code could be called - * here if more advanced normalization is needed. - * - * @param string $text - */ -function smwfNormalTitleText( $text ) { - global $wgCapitalLinks, $wgContLang; - - $text = trim( $text ); - - if ( $wgCapitalLinks ) { - $text = $wgContLang->ucfirst( $text ); - } - - return str_replace( '_', ' ', $text ); -} - -/** - * Escapes text in a way that allows it to be used as XML content (e.g. as a - * string value for some property). - * - * @param string $text - */ -function smwfXMLContentEncode( $text ) { - return str_replace( array( '&', '<', '>' ), array( '&', '<', '>' ), Sanitizer::decodeCharReferences( $text ) ); -} - -/** - * Decodes character references and inserts Unicode characters instead, using - * the MediaWiki Sanitizer. - * - * @param string $text - */ -function smwfHTMLtoUTF8( $text ) { - return Sanitizer::decodeCharReferences( $text ); -} - -/** - * @codeCoverageIgnore - * - * This method formats a float number value according to the given language and - * precision settings, with some intelligence to produce readable output. Used - * to format a number that was not hand-formatted by a user. - * - * @param mixed $value input number - * @param integer $decplaces optional positive integer, controls how many digits after - * the decimal point are shown - */ -function smwfNumberFormat( $value, $decplaces = 3 ) { - global $smwgMaxNonExpNumber; - - $decseparator = wfMessage( 'smw_decseparator' )->text(); - - // If number is a trillion or more, then switch to scientific - // notation. If number is less than 0.0000001 (i.e. twice decplaces), - // then switch to scientific notation. Otherwise print number - // using number_format. This may lead to 1.200, so then use trim to - // remove trailing zeroes. - $doScientific = false; - - // @todo: Don't do all this magic for integers, since the formatting does not fit there - // correctly. E.g. one would have integers formatted as 1234e6, not as 1.234e9, right? - // The "$value!=0" is relevant: we want to scientify numbers that are close to 0, but never 0! - if ( ( $decplaces > 0 ) && ( $value != 0 ) ) { - $absValue = abs( $value ); - if ( $absValue >= $smwgMaxNonExpNumber ) { - $doScientific = true; - } elseif ( $absValue <= pow( 10, - $decplaces ) ) { - $doScientific = true; - } elseif ( $absValue < 1 ) { - if ( $absValue <= pow( 10, - $decplaces ) ) { - $doScientific = true; - } else { - // Increase decimal places for small numbers, e.g. .00123 should be 5 places. - for ( $i = 0.1; $absValue <= $i; $i *= 0.1 ) { - $decplaces++; - } - } - } - } - - if ( $doScientific ) { - // Should we use decimal places here? - $value = sprintf( "%1.6e", $value ); - // Make it more readable by removing trailing zeroes from n.n00e7. - $value = preg_replace( '/(\\.\\d+?)0*e/u', '${1}e', $value, 1 ); - // NOTE: do not use the optional $count parameter with preg_replace. We need to - // remain compatible with PHP 4.something. - if ( $decseparator !== '.' ) { - $value = str_replace( '.', $decseparator, $value ); - } - } else { - // Format to some level of precision; number_format does rounding and locale formatting, - // x and y are used temporarily since number_format supports only single characters for either - $value = number_format( $value, $decplaces, 'x', 'y' ); - $value = str_replace( - array( 'x', 'y' ), - array( $decseparator, wfMessage( 'smw_kiloseparator' )->inContentLanguage()->text() ), - $value - ); - - // Make it more readable by removing ending .000 from nnn.000 - // Assumes substr is faster than a regular expression replacement. - $end = $decseparator . str_repeat( '0', $decplaces ); - $lenEnd = strlen( $end ); - - if ( substr( $value, - $lenEnd ) === $end ) { - $value = substr( $value, 0, - $lenEnd ); - } else { - // If above replacement occurred, no need to do the next one. - // Make it more readable by removing trailing zeroes from nn.n00. - $value = preg_replace( "/(\\$decseparator\\d+?)0*$/u", '$1', $value, 1 ); - } - } - - return $value; -} - -/** - * Formats an array of message strings so that it appears as a tooltip. - * $icon should be one of: 'warning' (default), 'info'. - * - * @param array $messages - * @param string $icon Acts like an enum. Callers must ensure safety, since this value is used directly in the output. - * @param string $seperator - * @param boolean $escape Should the messages be escaped or not (ie when they already are) - * - * @return string - */ -function smwfEncodeMessages( array $messages, $type = 'warning', $seperator = ' <!--br-->', $escape = true ) { - if ( $messages !== array() ) { - - if ( $escape ) { - $messages = array_map( 'htmlspecialchars', $messages ); - } - - if ( count( $messages ) == 1 ) { - $errorList = $messages[0]; - } - else { - foreach ( $messages as &$message ) { - $message = '<li>' . $message . '</li>'; - } - - $errorList = '<ul>' . implode( $seperator, $messages ) . '</ul>'; - } - - // Type will be converted internally - $highlighter = SMW\Highlighter::factory( $type ); - $highlighter->setContent( array ( - 'caption' => null, - 'content' => $errorList - ) ); - - return $highlighter->getHtml(); - } else { - return ''; - } -} - -/** - * Returns an instance for the storage back-end - * - * @return SMWStore - */ -function &smwfGetStore() { - $store = \SMW\StoreFactory::getStore(); - return $store; -} - -/** - * @codeCoverageIgnore - * - * Get the SMWSparqlDatabase object to use for connecting to a SPARQL store, - * or null if no SPARQL backend has been set up. - * - * Currently, it just returns one globally defined object, but the - * infrastructure allows to set up load balancing and task-dependent use of - * stores (e.g. using other stores for fast querying than for storing new - * facts), somewhat similar to MediaWiki's DB implementation. - * - * @since 1.6 - * - * @return SMWSparqlDatabase or null - */ -function &smwfGetSparqlDatabase() { - - if ( !isset( $GLOBALS['smwgSparqlDatabaseMaster'] ) ) { - $connectionProvider = new SparqlDBConnectionProvider(); - $GLOBALS['smwgSparqlDatabaseMaster'] = $connectionProvider->getConnection(); - } - - return $GLOBALS['smwgSparqlDatabaseMaster']; -} - -/** - * Compatibility helper for using Linker methods. - * MW 1.16 has a Linker with non-static methods, - * where in MW 1.19 they are static, and a DummyLinker - * class is introduced, which can be instantaited for - * compat reasons. - * - * @since 1.6 - * - * @return Linker or DummyLinker - */ -function smwfGetLinker() { - static $linker = false; - - if ( $linker === false ) { - $linker = class_exists( 'DummyLinker' ) ? new DummyLinker() : new Linker(); - } - - return $linker; -} - -/** - * Function to switch on Semantic MediaWiki. This function must be called in - * LocalSettings.php after including SMW_Settings.php. It is used to ensure - * that required parameters for SMW are really provided explicitly. For - * readability, this is the only global function that does not adhere to the - * naming conventions. - * - * This function also sets up all autoloading, such that all SMW classes are - * available as early on. Moreover, jobs and special pages are registered. - * - * @param mixed $namespace - * @param boolean $complete - * - * @return true - * - * @codeCoverageIgnore - */ -function enableSemantics( $namespace = null, $complete = false ) { - global $smwgNamespace; - - // $GLOBALS ought to be injected from the top-level but that would require - // to change the interface which would bring no benefits for the end user - // as enableSemantics() is only targeted to be included in LocalSettings - NamespaceManager::initCustomNamespace( $GLOBALS ); - - if ( !$complete && ( $smwgNamespace !== '' ) ) { - // The dot tells that the domain is not complete. It will be completed - // in the Export since we do not want to create a title object here when - // it is not needed in many cases. - $smwgNamespace = '.' . $namespace; - } else { - $smwgNamespace = $namespace; - } - - return true; -} diff --git a/SemanticMediaWiki/includes/HashIdGenerator.php b/SemanticMediaWiki/includes/HashIdGenerator.php deleted file mode 100644 index 42320b6a..00000000 --- a/SemanticMediaWiki/includes/HashIdGenerator.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -namespace SMW; - -/** - * Generating a Hash Id - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * This generating a Hash Id from an arbitrary content - * - * @ingroup Utility - */ -class HashIdGenerator implements IdGenerator { - - /** @var string */ - protected $hashable = false; - - /** @var string */ - protected $prefix; - - /** - * @since 1.9 - * - * @param mixed $hashable - * @param mixed|null $prefix - */ - public function __construct( $hashable, $prefix = null ) { - $this->hashable = $hashable; - $this->prefix = $prefix; - } - - /** - * Sets prefix - * - * @since 1.9 - * - * @param string $prefix - * - * @return HashIdGenerator - */ - public function setPrefix( $prefix ) { - $this->prefix = $prefix; - return $this; - } - - /** - * Returns prefix - * - * @since 1.9 - * - * @return string|null - */ - public function getPrefix() { - return $this->prefix; - } - - /** - * Generates an Id - * - * It returns a string that is concatenated of a prefix and a md5 value - * - * @par Example: - * @code - * $key = new HashIdGenerator( 'Foo', 'Lula' ) - * $key->generateId() returns < Lula > + < 'Foo' md5 hash > - * @endcode - * - * @since 1.9 - * - * @return string - */ - public function generateId() { - return $this->getPrefix() . md5( json_encode( array( $this->hashable ) ) ); - } - -} diff --git a/SemanticMediaWiki/includes/Highlighter.php b/SemanticMediaWiki/includes/Highlighter.php deleted file mode 100644 index c98e789a..00000000 --- a/SemanticMediaWiki/includes/Highlighter.php +++ /dev/null @@ -1,263 +0,0 @@ -<?php - -namespace SMW; - -use SMWOutputs; - -use IContextSource; -use ContextSource; -use Html; - -use MWException; - -/** - * Highlighter utility function for Semantic MediaWiki - * - * 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 - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Highlighter utility function for Semantic MediaWiki - * - * @ingroup SMW - */ -class Highlighter extends ContextSource { - - // Highlighter ID for no types - const TYPE_NOTYPE = 0; - // Highlighter ID for properties - const TYPE_PROPERTY = 1; - // Highlighter ID for text - const TYPE_TEXT = 2; - // Highlighter ID for quantities - const TYPE_QUANTITY = 3; - // Highlighter ID for warnings - const TYPE_WARNING = 4; - // Highlighter ID for informations - const TYPE_INFO = 5; - // Highlighter ID for help - const TYPE_HELP = 6; - // Highlighter ID for notes - const TYPE_NOTE = 7; - // Highlighter ID for service links - const TYPE_SERVICE = 8; - - /** - * @var array $options - */ - protected $options; - - /** - * @var int $type - */ - protected $type; - - /** - * Constructor - * - * @since 1.9 - * - * @param int $type - * @param \IContextSource|null $context - */ - public function __construct( $type, IContextSource $context = null ) { - if ( !$context ) { - $context = \RequestContext::getMain(); - } - $this->setContext( $context ); - $this->type = $type; - } - - /** - * Factory method - * - * @since 1.9 - * - * @param string|int $type - * @param \IContextSource|null $context - * - * @return Highlighter - */ - public static function factory( $type, IContextSource $context = null ){ - if ( $type === '' || !is_int( $type ) ) { - $type = self::getTypeId( $type ); - } - - return new Highlighter( $type, $context ); - } - - /** - * Returns html output - * - * @since 1.9 - * - * @return string - */ - public function getHtml() { - //@todo Introduce temporary fix, for more information see bug 43205 - SMWOutputs::requireResource( 'ext.smw.tooltips' ); - // $this->getOutput()->addModules( 'ext.smw.tooltips' ); - return $this->getContainer(); - } - - /** - * Set content - * - * An external class that invokes content via setContent has to ensure - * that all data are appropriately escaped. - * - * @since 1.9 - * - * @param array $content - * - * @return array - */ - public function setContent( array $content ) { - /** - * @var $content - * $content['caption'] = a text or null - * $content['context'] = a text or null - */ - return $this->options = array_merge( $this->getTypeConfiguration( $this->type ), $content ); - } - - /** - * Returns type id - * - * @since 1.9 - * - * @param string $type - * - * @return integer - */ - public static function getTypeId( $type ) { - // TODO: why do we have a htmlspecialchars here?! - switch ( strtolower ( htmlspecialchars ( $type ) ) ) { - case 'property': return self::TYPE_PROPERTY; - case 'text' : return self::TYPE_TEXT; - case 'quantity': return self::TYPE_QUANTITY; - case 'warning' : return self::TYPE_WARNING; - case 'info' : return self::TYPE_INFO; - case 'help' : return self::TYPE_HELP; - case 'note' : return self::TYPE_NOTE; - case 'service' : return self::TYPE_SERVICE; - default : return self::TYPE_NOTYPE; - } - } - - /** - * Builds Html container - * - * Content that is being invoked has to be escaped - * @see Highlighter::setContent - * - * @since 1.9 - * - * @return string - */ - private function getContainer() { - return Html::rawElement( - 'span', - array( - 'class' => 'smw-highlighter', - 'data-type' => $this->options['type'], - 'data-state' => $this->options['state'], - 'data-title' => $this->msg( $this->options['title'] )->text(), - ), Html::rawElement( - 'span', - array( - 'class' => $this->options['captionclass'] - ), $this->options['caption'] - ) . Html::rawElement( - 'span', - array( - 'class' => 'smwttcontent' - ), $this->options['content'] - ) - ); - } - - /** - * Returns initial configuation settings - * - * @note You could create a class per entity type but does this - * really make sense just to get some configuration parameters? - * - * @since 1.9 - * - * @param string $type - * - * @return array - */ - private function getTypeConfiguration( $type ) { - $settings = array(); - $settings['type'] = $type; - $settings['caption'] = ''; - $settings['content'] = ''; - - switch ( $type ) { - case self::TYPE_PROPERTY: - $settings['state'] = 'inline'; - $settings['title'] = 'smw-ui-tooltip-title-property'; - $settings['captionclass'] = 'smwbuiltin'; - break; - case self::TYPE_TEXT: - $settings['state'] = 'persistent'; - $settings['title'] = 'smw-ui-tooltip-title-info'; - $settings['captionclass'] = 'smwtext'; - break; - case self::TYPE_QUANTITY: - $settings['state'] = 'inline'; - $settings['title'] = 'smw-ui-tooltip-title-quantity'; - $settings['captionclass'] = 'smwtext'; - break; - case self::TYPE_NOTE: - $settings['state'] = 'inline'; - $settings['title'] = 'smw-ui-tooltip-title-note'; - $settings['captionclass'] = 'smwtticon note'; - break; - case self::TYPE_WARNING: - $settings['state'] = 'inline'; - $settings['title'] = 'smw-ui-tooltip-title-warning'; - $settings['captionclass'] = 'smwtticon warning'; - break; - case self::TYPE_SERVICE: - $settings['state'] = 'persistent'; - $settings['title'] = 'smw-ui-tooltip-title-service'; - $settings['captionclass'] = 'smwtticon service'; - break; - case self::TYPE_HELP: - case self::TYPE_INFO: - $settings['state'] = 'persistent'; - $settings['title'] = 'smw-ui-tooltip-title-info'; - $settings['captionclass'] = 'smwtticon info'; - break; - case self::TYPE_NOTYPE: - default: - $settings['state'] = 'persistent'; - $settings['title'] = 'smw-ui-tooltip-title-info'; - $settings['captionclass'] = 'smwbuiltin'; - }; - - return $settings; - } -} diff --git a/SemanticMediaWiki/includes/NamespaceExaminer.php b/SemanticMediaWiki/includes/NamespaceExaminer.php deleted file mode 100644 index 186672bb..00000000 --- a/SemanticMediaWiki/includes/NamespaceExaminer.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -namespace SMW; - -use MWNamespace; - -/** - * Examines if a specific namespace is enabled for the usage of the - * Semantic MediaWiki extension - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -final class NamespaceExaminer { - - /** @var array */ - private static $instance = null; - - /** @var array */ - private $registeredNamespaces = array(); - - /** - * @since 1.9 - * - * @param array $registeredNamespaces - */ - public function __construct( array $registeredNamespaces ) { - $this->registeredNamespaces = $registeredNamespaces; - } - - /** - * Returns a static instance with an invoked global settings array - * - * @par Example: - * @code - * \SMW\NamespaceExaminer::getInstance()->isSemanticEnabled( NS_MAIN ) - * @endcode - * - * @note Used in smwfIsSemanticsProcessed - * - * @since 1.9 - * - * @return NamespaceExaminer - */ - public static function getInstance() { - - if ( self::$instance === null ) { - self::$instance = self::newFromArray( Settings::newFromGlobals()->get( 'smwgNamespacesWithSemanticLinks' ) ); - } - - return self::$instance; - } - - /** - * Registers an array of available namespaces - * - * @par Example: - * @code - * \SMW\NamespaceExaminer::newFromArray( array( ... ) )->isSemanticEnabled( NS_MAIN ) - * @endcode - * - * @since 1.9 - * - * @return NamespaceExaminer - */ - public static function newFromArray( $registeredNamespaces ) { - return new self( $registeredNamespaces ); - } - - /** - * Resets static instance - * - * @since 1.9 - */ - public static function reset() { - self::$instance = null; - } - - /** - * Returns if a namespace is enabled for semantic processing - * - * @since 1.9 - * - * @param integer $namespace - * - * @return boolean - * @throws InvalidNamespaceException - */ - public function isSemanticEnabled( $namespace ) { - - if ( !is_int( $namespace ) ) { - throw new InvalidNamespaceException( "{$namespace} is not a number" ); - } - - if ( !in_array( $namespace, MWNamespace::getValidNamespaces() ) ) { - // Bug 51435 - return false; - } - - return $this->isEnabled( $namespace ); - } - - /** - * Asserts if a namespace is enabled - * - * @since 1.9 - * - * @param integer $namespace - * - * @return boolean - */ - protected function isEnabled( $namespace ) { - return !empty( $this->registeredNamespaces[$namespace] ); - } - -} diff --git a/SemanticMediaWiki/includes/NamespaceManager.php b/SemanticMediaWiki/includes/NamespaceManager.php deleted file mode 100644 index 979f3e02..00000000 --- a/SemanticMediaWiki/includes/NamespaceManager.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -namespace SMW; - -/** - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - * @author others - */ -class NamespaceManager { - - /** @var array */ - protected $globalVars; - - /** - * @since 1.9 - * - * @param array &$globalVars - * @param string|null &directory - */ - public function __construct( &$globalVars, $directory = null ) { - $this->globalVars =& $globalVars; - $this->directory = $directory; - } - - /** - * @since 1.9 - */ - public function run() { - - if ( !$this->isDefinedConstant( 'SMW_NS_PROPERTY' ) ) { - $this->initCustomNamespace( $this->globalVars ); - } - - if ( empty( $this->globalVars['smwgContLang'] ) ) { - $this->initContentLanguage( $this->globalVars['wgLanguageCode'] ); - } - - $this->addNamespaceSettings(); - - return true; - } - - /** - * @see Hooks:CanonicalNamespaces - * - * @since 1.9 - * - * @return array - */ - public static function getCanonicalNames() { - - $canonicalNames = array( - SMW_NS_PROPERTY => 'Property', - SMW_NS_PROPERTY_TALK => 'Property_talk', - SMW_NS_TYPE => 'Type', - SMW_NS_TYPE_TALK => 'Type_talk', - SMW_NS_CONCEPT => 'Concept', - SMW_NS_CONCEPT_TALK => 'Concept_talk' - ); - - return $canonicalNames; - } - - /** - * @since 1.9 - * - * @param integer offset - * - * @return array - */ - public static function buildNamespaceIndex( $offset ) { - - $namespaceIndex = array( - 'SMW_NS_PROPERTY' => $offset + 2, - 'SMW_NS_PROPERTY_TALK' => $offset + 3, - 'SMW_NS_TYPE' => $offset + 4, - 'SMW_NS_TYPE_TALK' => $offset + 5, - 'SF_NS_FORM' => $offset + 6, - 'SF_NS_FORM_TALK' => $offset + 7, - 'SMW_NS_CONCEPT' => $offset + 8, - 'SMW_NS_CONCEPT_TALK' => $offset + 9, - ); - - return $namespaceIndex; - } - - /** - * 100 and 101 used to be occupied by SMW's now obsolete namespaces - * "Relation" and "Relation_Talk" - * - * 106 and 107 are occupied by the Semantic Forms, we define them here - * to offer some (easy but useful) support to SF - * - * @since 1.9 - * - * @param array $globalVars - */ - public static function initCustomNamespace( &$globalVars ) { - - $instance = new self( $globalVars ); - - if ( !isset( $globalVars['smwgNamespaceIndex'] ) ) { - $globalVars['smwgNamespaceIndex'] = 100; - } - - foreach ( $instance->buildNamespaceIndex( $globalVars['smwgNamespaceIndex'] ) as $ns => $index ) { - if ( !$instance->isDefinedConstant( $ns ) ) { - define( $ns, $index ); - }; - } - } - - protected function addNamespaceSettings() { - - $this->isValidConfigurationOrSetDefault( 'wgExtraNamespaces', array() ); - $this->isValidConfigurationOrSetDefault( 'wgNamespaceAliases', array() ); - - /** - * @var SMWLanguage $smwgContLang - */ - $this->globalVars['wgExtraNamespaces'] = $this->globalVars['wgExtraNamespaces'] + $this->globalVars['smwgContLang']->getNamespaces(); - $this->globalVars['wgNamespaceAliases'] = $this->globalVars['wgNamespaceAliases'] + $this->globalVars['smwgContLang']->getNamespaceAliases(); - - // Support subpages only for talk pages by default - $this->globalVars['wgNamespacesWithSubpages'] = $this->globalVars['wgNamespacesWithSubpages'] + array( - SMW_NS_PROPERTY_TALK => true, - SMW_NS_TYPE_TALK => true - ); - - // not modified for Semantic MediaWiki - /* $this->globalVars['wgNamespacesToBeSearchedDefault'] = array( - NS_MAIN => true, - ); - */ - - /** - * Default settings for the SMW specific NS which can only - * be defined after SMW_NS_PROPERTY is declared - */ - $smwNamespacesSettings = array( - SMW_NS_PROPERTY => true, - SMW_NS_PROPERTY_TALK => false, - SMW_NS_TYPE => true, - SMW_NS_TYPE_TALK => false, - SMW_NS_CONCEPT => true, - SMW_NS_CONCEPT_TALK => false, - ); - - // Combine default values with values specified in other places - // (LocalSettings etc.) - $this->globalVars['smwgNamespacesWithSemanticLinks'] = array_replace( - $smwNamespacesSettings, - $this->globalVars['smwgNamespacesWithSemanticLinks'] - ); - - } - - /** - * Initialise a global language object for content language. This must happen - * early on, even before user language is known, to determine labels for - * additional namespaces. In contrast, messages can be initialised much later - * when they are actually needed. - * - * @since 1.9 - */ - protected function initContentLanguage( $langcode ) { - Profiler::In(); - - $this->setLanguage( $langcode ); - $this->isValidLanguageClassOrSetFallback( $this->globalVars['smwContLangClass'], 'en' ); - - $this->globalVars['smwgContLang'] = new $this->globalVars['smwContLangClass']; - - Profiler::Out(); - } - - protected function setLanguage( $langcode ) { - - $this->globalVars['smwContLangFile'] = 'SMW_Language' . str_replace( '-', '_', ucfirst( $langcode ) ); - $this->globalVars['smwContLangClass'] = 'SMWLanguage' . str_replace( '-', '_', ucfirst( $langcode ) ); - - $file = $this->directory . '/' . 'languages' . '/' . $this->globalVars['smwContLangFile'] . '.php'; - - if ( file_exists( $file ) ) { - include_once( $file ); - } - } - - protected function isValidConfigurationOrSetDefault( $element, $default ) { - if ( !isset( $this->globalVars[$element] ) || !is_array( $this->globalVars[$element] ) ) { - $this->globalVars[$element] = $default; - } - } - - protected function isValidLanguageClassOrSetFallback( $langClass, $fallbackLanguageCode ) { - if ( !class_exists( $langClass ) ) { - $this->setLanguage( $fallbackLanguageCode ); - } - } - - protected function isDefinedConstant( $constant ) { - return defined( $constant ); - } - -} diff --git a/SemanticMediaWiki/includes/ObjectStorage.php b/SemanticMediaWiki/includes/ObjectStorage.php deleted file mode 100644 index eba8632e..00000000 --- a/SemanticMediaWiki/includes/ObjectStorage.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -namespace SMW; - -/** - * Class implementing non-persistent storage and retrieval of objects using an - * associative array - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -abstract class ObjectStorage { - - /** @var array */ - protected $storage = array(); - - /** - * @since 1.9 - * - * @param array $storage - */ - public function __construct( array $storage = array() ) { - $this->storage = $storage; - } - - /** - * Returns whether the storage contains an element for a given key - * - * @note Using isset() for performance reasons and checking the NULL - * element with the help of array_key_exists - * - * @since 1.9 - * - * @param mixed $key - * - * @return boolean - */ - protected function contains( $key ) { - return isset( $this->storage[$key] ) || array_key_exists( $key, $this->storage ); - } - - /** - * Append an element to a collection - * - * @since 1.9 - * - * @param string $key - * @param mixed|null $key - */ - protected function attach( $key, $value = null ) { - $this->storage[$key] = $value; - } - - /** - * Finds an element (if any) that is bound to a given key - * - * @since 1.9 - * - * @param string $key - * - * @return mixed|null - */ - protected function lookup( $key ) { - return $this->storage[$key]; - } - - /** - * Remove an element from a collection - * - * @since 1.9 - * - * @param string $key - * - * @return boolean - */ - protected function detach( $key ) { - - if ( $this->contains( $key ) ) { - unset( $this->storage[$key] ); - reset( $this->storage ); - return true; - } - - return false; - } - -} diff --git a/SemanticMediaWiki/includes/ParameterInput.php b/SemanticMediaWiki/includes/ParameterInput.php deleted file mode 100644 index 17cfe527..00000000 --- a/SemanticMediaWiki/includes/ParameterInput.php +++ /dev/null @@ -1,267 +0,0 @@ -<?php - -namespace SMW; - -use ParamProcessor\ParamDefinition; -use Html; -use Xml; - -/** - * Simple class to get a HTML input for the parameter. - * Usable for when creating a GUI from a parameter list. - * - * Based on 'addOptionInput' from Special:Ask in SMW 1.5.6. - * - * TODO: nicify HTML - * - * @since 1.9 - * - * @file - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class ParameterInput { - - /** - * The parameter to print an input for. - * - * @since 1.9 - * - * @var ParamDefinition - */ - protected $param; - - /** - * The current value for the parameter. When provided, - * it'll be used as value for the input, otherwise the - * parameters default value will be used. - * - * @since 1.9 - * - * @var mixed: string or false - */ - protected $currentValue; - - /** - * Name for the input. - * - * @since 1.9 - * - * @var string - */ - protected $inputName; - - /** - * Constructor. - * - * @since 1.9 - * - * @param ParamDefinition $param - * @param mixed $currentValue - */ - public function __construct( ParamDefinition $param, $currentValue = false ) { - $this->currentValue = $currentValue; - $this->inputName = $param->getName(); - $this->param = $param; - } - - /** - * Sets the current value. - * - * @since 1.9 - * - * @param mixed $currentValue - */ - public function setCurrentValue( $currentValue ) { - $this->currentValue = $currentValue; - } - - /** - * Sets the name for the input; defaults to the name of the parameter. - * - * @since 1.9 - * - * @param string $name - */ - public function setInputName( $name ) { - $this->inputName = $name; - } - - /** - * Returns the HTML for the parameter input. - * - * @since 1.9 - * - * @return string - */ - public function getHtml() { - $valueList = array(); - - if ( is_array( $this->param->getAllowedValues() ) ) { - $valueList = $this->param->getAllowedValues(); - } - - if ( $valueList === array() ) { - switch ( $this->param->getType() ) { - case 'char': - case 'float': - case 'integer': - case 'number': - $html = $this->getNumberInput(); - break; - case 'boolean': - $html = $this->getBooleanInput(); - break; - case 'string': - default: - $html = $this->getStrInput(); - break; - } - } - else { - $html = $this->param->isList() ? $this->getCheckboxListInput( $valueList ) : $this->getSelectInput( $valueList ); - } - - return $html; - } - - /** - * Returns the value to initially display with the input. - * - * @since 1.9 - * - * @return string - */ - protected function getValueToUse() { - $value = $this->currentValue === false ? $this->param->getDefault() : $this->currentValue; - - if ( $this->param->isList() && is_array( $value ) ) { - $value = implode( $this->param->getDelimiter(), $value ); - } - - return $value; - } - - /** - * Gets a short text input suitable for numbers. - * - * @since 1.9 - * - * @return string - */ - protected function getNumberInput() { - return Html::input( - $this->inputName, - $this->getValueToUse(), - 'text', - array( - 'size' => 6, - 'style' => "width: 95%;", - ) - ); - } - - /** - * Gets a text input for a string. - * - * @since 1.9 - * - * @return string - */ - protected function getStrInput() { - return Html::input( - $this->inputName, - $this->getValueToUse(), - 'text', - array( - 'size' => 20, - 'style' => "width: 95%;", - ) - ); - } - - /** - * Gets a checkbox. - * - * @since 1.9 - * - * @return string - */ - protected function getBooleanInput() { - return Xml::check( - $this->inputName, - $this->getValueToUse() - ); - } - - /** - * Gets a select menu for the provided values. - * - * @since 1.9 - * - * @param array $valueList - * - * @return string - */ - protected function getSelectInput( array $valueList ) { - $options = array(); - $options[] = '<option value=""></option>'; - - $currentValues = (array)$this->getValueToUse(); - if ( is_null( $currentValues ) ) { - $currentValues = array(); - } - - foreach ( $valueList as $value ) { - $options[] = - '<option value="' . htmlspecialchars( $value ) . '"' . - ( in_array( $value, $currentValues ) ? ' selected' : '' ) . '>' . htmlspecialchars( $value ) . - '</option>'; - } - - return Html::rawElement( - 'select', - array( - 'name' => $this->inputName - ), - implode( "\n", $options ) - ); - } - - /** - * Gets a list of input boxes for the provided values. - * - * @since 1.9 - * - * @param array $valueList - * - * @return string - */ - protected function getCheckboxListInput( array $valueList ) { - $boxes = array(); - - $currentValues = (array)$this->getValueToUse(); - if ( is_null( $currentValues ) ) { - $currentValues = array(); - } - - foreach ( $valueList as $value ) { - $boxes[] = Html::rawElement( - 'span', - array( - 'style' => 'white-space: nowrap; padding-right: 5px;' - ), - Xml::check( - $this->inputName . '[' . htmlspecialchars( $value ). ']', - in_array( $value, $currentValues ) - ) . - Html::element( 'tt', array(), $value ) - ); - } - - return implode( "\n", $boxes ); - } - -} diff --git a/SemanticMediaWiki/includes/ParserData.php b/SemanticMediaWiki/includes/ParserData.php deleted file mode 100644 index 1483df9e..00000000 --- a/SemanticMediaWiki/includes/ParserData.php +++ /dev/null @@ -1,241 +0,0 @@ -<?php - -namespace SMW; - -use SMWDataValue as DataValue; - -use Title; -use ParserOutput; - -/** - * Handling semantic data exchange with a ParserOutput object - * - * Provides access to a semantic data container that is generated - * either from the ParserOutput or is a newly created container - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - * @author Markus Krötzsch - */ -class ParserData { - - /** - * @var Title - */ - private $title; - - /** - * @var ParserOutput - */ - private $parserOutput; - - /** - * @var SemanticData - */ - private $semanticData; - - /** - * @var array - */ - private $errors = array(); - - /** - * @var $updateJobs - */ - private $updateJobs = true; - - /** - * @since 1.9 - * - * @param Title $title - * @param ParserOutput $parserOutput - */ - public function __construct( Title $title, ParserOutput $parserOutput ) { - $this->title = $title; - $this->parserOutput = $parserOutput; - - $this->initData(); - } - - /** - * @since 1.9 - * - * @return Title - */ - public function getTitle() { - return $this->title; - } - - /** - * @since 1.9 - * - * @return DIWikiPage - */ - public function getSubject() { - return DIWikiPage::newFromTitle( $this->title ); - } - - /** - * @since 1.9 - * - * @return ParserOutput - */ - public function getOutput() { - return $this->parserOutput; - } - - /** - * Explicitly disable update jobs (e.g when running store update - * in the job queue) - * - * @since 1.9 - */ - public function disableBackgroundUpdateJobs() { - $this->updateJobs = false; - return $this; - } - - /** - * Returns update status - * - * @since 1.9 - * - * @return boolean - */ - public function getUpdateStatus() { - return $this->updateJobs; - } - - /** - * Returns collected errors occurred during processing - * - * @since 1.9 - * - * @return array - */ - public function getErrors() { - return $this->errors; - } - - /** - * @since 1.9 - * - * @return array - */ - public function addError( array $errors ) { - return $this->errors = array_merge( $errors, $this->errors ); - } - - /** - * @since 1.9 - * - * @param SemanticData $semanticData - */ - public function setSemanticData( SemanticData $semanticData ) { - $this->semanticData = $semanticData; - } - - public function setData( SemanticData $semanticData ) { - $this->setSemanticData( $semanticData ); - } - - /** - * @since 1.9 - * - * @return SemanticData - */ - public function getSemanticData() { - return $this->semanticData; - } - - public function getData() { - return $this->getSemanticData(); - } - - /** - * Clears all data for the given instance - * - * @since 1.9 - */ - public function clearData() { - $this->setData( new SemanticData( $this->getSubject() ) ); - } - - /** - * Update ParserOutput with processed semantic data - * - * @since 1.9 - */ - public function updateOutput(){ - - if ( $this->hasExtensionData() ) { - $this->parserOutput->setExtensionData( 'smwdata', $this->semanticData ); - } else { - $this->parserOutput->mSMWData = $this->semanticData; - } - } - - /** - * Adds a data value to the semantic data container - * - * @par Example: - * @code - * $dataValue = DataValueFactory::getInstance()->newPropertyValue( $userProperty, $userValue ) - * $parserData->addDataValue( $dataValue ) - * @endcode - * - * @since 1.9 - * - * @param SMWDataValue $dataValue - */ - public function addDataValue( DataValue $dataValue ) { - $this->semanticData->addDataValue( $dataValue ); - $this->addError( $this->semanticData->getErrors() ); - } - - /** - * Updates the Store with data attached to the ParserOutput object - * - * @since 1.9 - * - * @return boolean - */ - public function updateStore() { - - $updater = new StoreUpdater( $this->semanticData ); - $updater->setUpdateJobsEnabledState( $this->getUpdateStatus() )->doUpdate(); - - return true; - } - - /** - * Setup the semantic data container either from the ParserOutput or - * if not available create an empty container - * - * @since 1.9 - */ - protected function initData() { - - if ( $this->hasExtensionData() ) { - $this->semanticData = $this->parserOutput->getExtensionData( 'smwdata' ); - } else { - $this->semanticData = isset( $this->parserOutput->mSMWData ) ? $this->parserOutput->mSMWData : null; - } - - if ( !( $this->semanticData instanceof SemanticData ) ) { - $this->clearData(); - } - } - - /** - * FIXME Remove when MW 1.21 becomes mandatory - */ - protected function hasExtensionData() { - return method_exists( $this->parserOutput, 'getExtensionData' ); - } - -} diff --git a/SemanticMediaWiki/includes/Profiler.php b/SemanticMediaWiki/includes/Profiler.php deleted file mode 100644 index 816e9a3e..00000000 --- a/SemanticMediaWiki/includes/Profiler.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -namespace SMW; - -/** - * Encapsulates MediaWiki's profiling class - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * This class encapsulates MediaWiki's profiling class, if enabled enabled - * track the process caller allowing it to generate a call tree - * - * @ingroup Utility - */ -class Profiler { - - /** @var Profiler */ - private static $instance = null; - - /** - * Return a \Profiler instance - * - * @note Profiler::$__instance only made public in 1.22 therefore - * we use our own static to keep overhead at a minimum - * - * @see $wgProfiler - * @see http://www.mediawiki.org/wiki/Profiling#Profiling - * - * @since 1.9 - * - * @return \Profiler|null - */ - public static function getInstance() { - - // Nothing we can do to avoid the global state here until we have - // public access to Profiler::$__instance - $profiler = isset( $GLOBALS['wgProfiler']['class'] ); - - if ( self::$instance === null && $profiler ) { - self::$instance = \Profiler::instance(); - } - - if ( !$profiler ) { - self::reset(); - } - - return self::$instance; - } - - /** - * Begin profiling of a processor - * - * @since 1.9 - * - * @param string $name name of the function we will profile - * @param boolean $caller if the caller should be profiled as well - */ - public static function In( $name = false, $caller = false ) { - - $instance = self::getInstance(); - - if ( $instance instanceof \Profiler ) { - - $processor = $name ? $name : wfGetCaller( 2 ); - $instance->profileIn( $processor ); - - if ( $caller ) { - $instance->profileIn( $processor . '-' . wfGetCaller( 3 ) ); - } - } - - return $instance; - } - - /** - * Stop profiling of a processor - * - * @since 1.9 - * - * @param string $name name of the function we will profile - * @param boolean $caller if the caller should be profiled as well - */ - public static function Out( $name = false, $caller = false ) { - - $instance = self::getInstance(); - - if ( $instance instanceof \Profiler ) { - $processor = $name ? $name : wfGetCaller( 2 ); - - if ( $caller ) { - $instance->profileOut( $processor . '-' . wfGetCaller( 3 ) ); - } - - $instance->profileOut( $processor ); - } - - return $instance; - } - - /** - * Reset the instance - * - * @since 1.9 - */ - public static function reset() { - self::$instance = null; - } -} diff --git a/SemanticMediaWiki/includes/RecurringEvents.php b/SemanticMediaWiki/includes/RecurringEvents.php deleted file mode 100644 index 464365d1..00000000 --- a/SemanticMediaWiki/includes/RecurringEvents.php +++ /dev/null @@ -1,372 +0,0 @@ -<?php - -namespace SMW; - -use Message; - -use SMWDITime; -use SMWTimeValue; - -/** - * Class returns recurring events - * - * @see http://semantic-mediawiki.org/wiki/Help:Recurring_events - * - * @since 1.9 - * - * @file - * @ingroup SMW - * - * @author Yaron Koren - * @author Jeroen De Dauw - * @author mwjames - */ - -/** - * This class determines recurring events based on invoked parameters - * - * @ingroup SMW - */ -class RecurringEvents { - - /** - * Represents Settings object - * @var Settings - */ - protected $settings; - - /** - * Defines the property used - * var $property - */ - protected $property = null; - - /** - * Defines the dates - * var $dates - */ - protected $dates = array(); - - /** - * Defines remaining / unused parameters - * var $parameters - */ - protected $parameters = array(); - - /** - * Defines errors - * var $errors - */ - protected $errors = array(); - - /** - * Constructor - * - * @since 1.9 - * - * @param array $parameters - * @param Settings $settings - */ - public function __construct( array $parameters, Settings $settings ) { - $this->settings = $settings; - $this->parse( $parameters ); - } - - /** - * Returns property used - * - * @since 1.9 - * - * @return string - */ - public function getProperty() { - return $this->property; - } - - /** - * Returns dates - * - * @since 1.9 - * - * @return array - */ - public function getDates() { - return $this->dates; - } - - /** - * Returns unused parameters - * - * @since 1.9 - * - * @return array - */ - public function getParameters() { - return $this->parameters; - } - - /** - * Returns errors - * - * @since 1.9 - * - * @return array - */ - public function getErrors() { - return $this->errors; - } - - /** - * Set error - * - * @since 1.9 - * - * @return mixed - */ - protected function setError( $error ) { - $this->errors = array_merge( $error, $this->errors ); - } - - /** - * Returns the "Julian day" value from an object of type - * SMWTimeValue. - */ - public function getJulianDay( $dateDataValue ) { - if ( is_null( $dateDataValue ) ) { - return null; - } - $dateDataItem = $dateDataValue->getDataItem(); - // This might have returned an 'SMWDIError' object. - if ( $dateDataItem instanceof SMWDITime ) { - return $dateDataItem->getJD(); - } - return null; - } - - /** - * Parse parameters and set internal properties - * - * @since 1.9 - * - * @param $params - */ - protected function parse( $parameters ) { - // Initialize variables. - $all_date_strings = array(); - $unused_params = array(); - $property_name = $start_date = $end_date = $unit = $period = $week_num = null; - $included_dates = array(); - $excluded_dates = array(); - $excluded_dates_jd = array(); - - // Parse parameters and assign values - foreach ( $parameters as $name => $values ) { - - foreach ( $values as $value ) { - switch( $name ) { - case 'property': - $this->property = $value; - break; - case 'start': - $start_date = DataValueFactory::getInstance()->newTypeIDValue( '_dat', $value ); - break; - case 'end': - $end_date = DataValueFactory::getInstance()->newTypeIDValue( '_dat', $value ); - break; - case 'limit': - // Override default limit with query specific limit - $this->settings->set( 'smwgDefaultNumRecurringEvents', (int)$value ); - break; - case 'unit': - $unit = $value; - break; - case 'period': - $period = (int)$value; - break; - case 'week number': - $week_num = (int)$value; - break; - case 'include': - // This is for compatibility only otherwise we break - // to much at once. Instead of writing include=...;... - // it should be include=...;...|+sep=; because the - // ParameterParser class is conditioned to split those - // parameter accordingly - if ( strpos( $value, ';' ) ){ - $included_dates = explode( ';', $value ); - } else { - $included_dates[] = $value; - } - break; - case 'exclude': - // Some as above - if ( strpos( $value, ';' ) ){ - $excluded_dates = explode( ';', $value ); - } else { - $excluded_dates[] = $value; - } - break; - default: - $this->parameters[$name][] = $value; - } - } - } - - if ( $start_date === null ) { - $this->errors[] = new Message( 'smw-events-start-date-missing' ); - return; - } else if ( !( $start_date->getDataItem() instanceof SMWDITime ) ) { - $this->setError( $start_date->getErrors() ); - return; - } - - // Check property - if ( is_null( $this->property ) ) { - $this->errors[] = new Message( 'smw-events-property-missing' ); - return; - } - - // Exclude dates - foreach ( $excluded_dates as $date_str ) { - $excluded_dates_jd[] = $this->getJulianDay( - DataValueFactory::getInstance()->newTypeIDValue( '_dat', $date_str ) - ); - } - - // If the period is null, or outside of normal bounds, set it to 1. - if ( is_null( $period ) || $period < 1 || $period > 500 ) { - $period = 1; - } - - // Handle 'week number', but only if it's of unit 'month'. - if ( $unit == 'month' && ! is_null( $week_num ) ) { - $unit = 'dayofweekinmonth'; - - if ( $week_num < -4 || $week_num > 5 || $week_num == 0 ) { - $week_num = null; - } - } - - if ( $unit == 'dayofweekinmonth' && is_null( $week_num ) ) { - $week_num = ceil( $start_date->getDay() / 7 ); - } - - // Get the Julian day value for both the start and end date. - $end_date_jd = $this->getJulianDay( $end_date ); - - $cur_date = $start_date; - $cur_date_jd = $this->getJulianDay( $cur_date ); - $i = 0; - - do { - $i++; - $exclude_date = ( in_array( $cur_date_jd, $excluded_dates_jd ) ); - - if ( !$exclude_date ) { - $all_date_strings[] = $cur_date->getLongWikiText(); - } - - // Now get the next date. - // Handling is different depending on whether it's - // month/year or week/day since the latter is a set - // number of days while the former isn't. - if ( $unit === 'year' || $unit == 'month' ) { - $cur_year = $cur_date->getYear(); - $cur_month = $cur_date->getMonth(); - $cur_day = $start_date->getDay(); - $cur_time = $cur_date->getTimeString(); - - if ( $unit == 'year' ) { - $cur_year += $period; - $display_month = $cur_month; - } else { // $unit === 'month' - $cur_month += $period; - $cur_year += (int)( ( $cur_month - 1 ) / 12 ); - $cur_month %= 12; - $display_month = ( $cur_month == 0 ) ? 12 : $cur_month; - } - - // If the date is February 29, and this isn't - // a leap year, change it to February 28. - if ( $cur_month == 2 && $cur_day == 29 ) { - if ( !date( 'L', strtotime( "$cur_year-1-1" ) ) ) { - $cur_day = 28; - } - } - - $date_str = "$cur_year-$display_month-$cur_day $cur_time"; - $cur_date = DataValueFactory::getInstance()->newTypeIDValue( '_dat', $date_str ); - $all_date_strings = array_merge( $all_date_strings, $included_dates); - $cur_date_jd = $cur_date->getDataItem()->getJD(); - } elseif ( $unit == 'dayofweekinmonth' ) { - // e.g., "3rd Monday of every month" - $prev_month = $cur_date->getMonth(); - $prev_year = $cur_date->getYear(); - - $new_month = ( $prev_month + $period ) % 12; - if ( $new_month == 0 ) $new_month = 12; - - $new_year = $prev_year + floor( ( $prev_month + $period - 1 ) / 12 ); - $cur_date_jd += ( 28 * $period ) - 7; - - // We're sometime before the actual date now - - // keep incrementing by a week, until we get there. - do { - $cur_date_jd += 7; - $cur_date = $this->getJulianDayTimeValue( $cur_date_jd ); - $right_month = ( $cur_date->getMonth() == $new_month ); - - if ( $week_num < 0 ) { - $next_week_jd = $cur_date_jd; - - do { - $next_week_jd += 7; - $next_week_date = $this->getJulianDayTimeValue( $next_week_jd ); - $right_week = ( $next_week_date->getMonth() != $new_month ) || ( $next_week_date->getYear() != $new_year ); - } while ( !$right_week ); - - $cur_date_jd = $next_week_jd + ( 7 * $week_num ); - $cur_date = $this->getJulianDayTimeValue( $cur_date_jd ); - } else { - $cur_week_num = ceil( $cur_date->getDay() / 7 ); - $right_week = ( $cur_week_num == $week_num ); - - if ( $week_num == 5 && ( $cur_date->getMonth() % 12 == ( $new_month + 1 ) % 12 ) ) { - $cur_date_jd -= 7; - $cur_date = $this->getJulianDayTimeValue( $cur_date_jd ); - $right_month = $right_week = true; - } - } - } while ( !$right_month || !$right_week); - } else { // $unit == 'day' or 'week' - // Assume 'day' if it's none of the above. - $cur_date_jd += ( $unit === 'week' ) ? 7 * $period : $period; - $cur_date = $this->getJulianDayTimeValue( $cur_date_jd ); - } - - // should we stop? - if ( is_null( $end_date ) ) { - $reached_end_date = $i > $this->settings->get( 'smwgDefaultNumRecurringEvents' ); - } else { - $reached_end_date = ( $cur_date_jd > $end_date_jd ) || ( $i > $this->settings->get( 'smwgMaxNumRecurringEvents' ) ); - } - } while ( !$reached_end_date ); - - // Handle the 'include' dates as well. - $all_date_strings = array_filter( array_merge( $all_date_strings, $included_dates ) ); - - // Set dates - $this->dates = $all_date_strings; - } - - /** - * Helper function - creates an object of type SMWTimeValue based - * on a "Julian day" integer - */ - protected function getJulianDayTimeValue( $jd ) { - $timeDataItem = SMWDITime::newFromJD( $jd, SMWDITime::CM_GREGORIAN, SMWDITime::PREC_YMDT ); - $timeValue = new SMWTimeValue( '_dat' ); - $timeValue->setDataItem( $timeDataItem ); - return $timeValue; - } -} diff --git a/SemanticMediaWiki/includes/SMW_Infolink.php b/SemanticMediaWiki/includes/SMW_Infolink.php deleted file mode 100644 index ffcb09c5..00000000 --- a/SemanticMediaWiki/includes/SMW_Infolink.php +++ /dev/null @@ -1,480 +0,0 @@ -<?php -/** - * This file contains the SMWInfolink class. - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * - * @file - * @ingroup SMW - */ - -/** - * This class mainly is a container to store URLs for the factbox in a - * clean way. The class provides methods for creating source code for - * realising them in wiki or html contexts. - * - * @ingroup SMW - */ -class SMWInfolink { - - /** - * The actual link target. - * - * @var string - */ - protected $mTarget; - - /** - * The label for the link. - * - * @var string - */ - protected $mCaption; - - /** - * CSS class of a span to embedd the link into, - * or false if no extra style is required. - * - * @var mixed - */ - protected $mStyle; - - /** - * Indicates whether $target is a page name (true) or URL (false). - * - * @var boolean - */ - protected $mInternal; - - /** - * Array of parameters, format $name => $value, if any. - * - * @var array - */ - protected $mParams; - - /** - * Create a new link to some internal page or to some external URL. - * - * @param boolean $internal Indicates whether $target is a page name (true) or URL (false). - * @param string $caption The label for the link. - * @param string $target The actual link target. - * @param mixed $style CSS class of a span to embedd the link into, or false if no extra style is required. - * @param array $params Array of parameters, format $name => $value, if any. - */ - public function __construct( $internal, $caption, $target, $style = false, array $params = array() ) { - $this->mInternal = $internal; - $this->mCaption = $caption; - $this->mTarget = $target; - $this->mStyle = $style; - $this->mParams = $params; - } - - /** - * Create a new link to an internal page $target. - * All parameters are mere strings as used by wiki users. - * - * @param string $caption The label for the link. - * @param string $target The actual link target. - * @param mixed $style CSS class of a span to embedd the link into, or false if no extra style is required. - * @param array $params Array of parameters, format $name => $value, if any. - * - * @return SMWInfolink - */ - public static function newInternalLink( $caption, $target, $style = false, array $params = array() ) { - return new SMWInfolink( true, $caption, $target, $style, $params ); - } - - /** - * Create a new link to an external location $url. - * - * @param string $caption The label for the link. - * @param string $url The actual link target. - * @param mixed $style CSS class of a span to embedd the link into, or false if no extra style is required. - * @param array $params Array of parameters, format $name => $value, if any. - * - * @return SMWInfolink - */ - public static function newExternalLink( $caption, $url, $style = false, array $params = array() ) { - return new SMWInfolink( false, $caption, $url, $style, $params ); - } - - /** - * Static function to construct links to property searches. - * - * @param string $caption The label for the link. - * @param string $propertyName - * @param string $propertyValue - * @param mixed $style CSS class of a span to embedd the link into, or false if no extra style is required. - * - * @return SMWInfolink - */ - public static function newPropertySearchLink( $caption, $propertyName, $propertyValue, $style = 'smwsearch' ) { - global $wgContLang; - return new SMWInfolink( - true, - $caption, - $wgContLang->getNsText( NS_SPECIAL ) . ':SearchByProperty', - $style, - array( $propertyName, $propertyValue ) - ); - } - - /** - * Static function to construct links to inverse property searches. - * - * @param string $caption The label for the link. - * @param string $subject - * @param string $propertyName - * @param mixed $style CSS class of a span to embed the link into, or false if no extra style is required. - * - * @return SMWInfolink - */ - public static function newInversePropertySearchLink( $caption, $subject, $propertyname, $style = false ) { - global $wgContLang; - return new SMWInfolink( - true, - $caption, - $wgContLang->getNsText( NS_SPECIAL ) . ':PageProperty/' . $subject . '::' . $propertyname, - $style - ); - } - - /** - * Static function to construct links to the browsing special. - * - * @param string $caption The label for the link. - * @param string $titleText - * @param mixed $style CSS class of a span to embedd the link into, or false if no extra style is required. - * - * @return SMWInfolink - */ - public static function newBrowsingLink( $caption, $titleText, $style = 'smwbrowse' ) { - global $wgContLang; - return new SMWInfolink( - true, - $caption, - $wgContLang->getNsText( NS_SPECIAL ) . ':Browse', - $style, - array( $titleText ) - ); - } - - /** - * Set (or add) parameter values for an existing link. - * - * @param mixed $value - * @param mixed $key - */ - public function setParameter( $value, $key = false ) { - if ( $key === false ) { - $this->mParams[] = $value; - } else { - $this->mParams[$key] = $value; - } - } - - /** - * Get the value of some named parameter, or null if no parameter of - * that name exists. - */ - public function getParameter( $key ) { - if ( array_key_exists( $key, $this->mParams ) ) { - return $this->mParams[$key]; - } else { - return null; - } - } - - /** - * Change the link text. - */ - public function setCaption( $caption ) { - $this->mCaption = $caption; - } - - /** - * Change the link's CSS class. - */ - public function setStyle( $style ) { - $this->mStyle = $style; - } - - /** - * Returns a suitable text string for displaying this link in HTML or wiki, depending - * on whether $outputformat is SMW_OUTPUT_WIKI or SMW_OUTPUT_HTML. - * - * The parameter $linker controls linking of values such as titles and should - * be some Linker object (for HTML output). Some default linker will be created - * if needed and not provided. - */ - public function getText( $outputformat, $linker = null ) { - if ( $this->mStyle !== false ) { - SMWOutputs::requireResource( 'ext.smw.style' ); - $start = "<span class=\"$this->mStyle\">"; - $end = '</span>'; - } else { - $start = ''; - $end = ''; - } - - if ( $this->mInternal ) { - if ( count( $this->mParams ) > 0 ) { - $titletext = $this->mTarget . '/' . SMWInfolink::encodeParameters( $this->mParams ); - } else { - $titletext = $this->mTarget; - } - - $title = Title::newFromText( $titletext ); - - if ( !is_null( $title ) ) { - if ( $outputformat == SMW_OUTPUT_WIKI ) { - $link = "[[$titletext|$this->mCaption]]"; - } else { // SMW_OUTPUT_HTML, SMW_OUTPUT_FILE - $link = $this->getLinker( $linker )->link( $title, $this->mCaption ); - } - } else { // Title creation failed, maybe illegal symbols or too long; make a direct URL link - // (only possible if offending target parts belong to some parameter - // that can be separated from title text, - // e.g. as in Special:Bla/il<leg>al -> Special:Bla&p=il<leg>al) - $title = Title::newFromText( $this->mTarget ); - - if ( !is_null( $title ) ) { - if ( $outputformat == SMW_OUTPUT_WIKI ) { - $link = '[' . $title->getFullURL( SMWInfolink::encodeParameters( $this->mParams, false ) ) . " $this->mCaption]"; - } else { // SMW_OUTPUT_HTML, SMW_OUTPUT_FILE - $link = $this->getLinker( $linker )->link( - $title, - $this->mCaption, - array(), - SMWInfolink::encodeParameters( $this->mParams, false ) - ); - } - } else { - return ''; // the title was bad, normally this would indicate a software bug - } - } - } else { - $target = $this->getURL(); - - if ( $outputformat == SMW_OUTPUT_WIKI ) { - $link = "[$target $this->mCaption]"; - } else { // SMW_OUTPUT_HTML, SMW_OUTPUT_FILE - $link = '<a href="' . htmlspecialchars( $target ) . "\">$this->mCaption</a>"; - } - } - - return $start . $link . $end; - } - - /** - * Return hyperlink for this infolink in HTML format. - * - * @return string - */ - public function getHTML( $linker = null ) { - return $this->getText( SMW_OUTPUT_HTML, $linker ); - } - - /** - * Return hyperlink for this infolink in wiki format. - * - * @return string - */ - public function getWikiText( $linker = null ) { - return $this->getText( SMW_OUTPUT_WIKI, $linker ); - } - - /** - * Return a fully qualified URL that points to the link target (whether internal or not). - * This function might be used when the URL is needed outside normal links, e.g. in the HTML - * header or in some metadata file. For making normal links, getText() should be used. - * - * @return string - */ - public function getURL() { - if ( $this->mInternal ) { - $title = Title::newFromText( $this->mTarget ); - - if ( !is_null( $title ) ) { - return $title->getFullURL( SMWInfolink::encodeParameters( $this->mParams, false ) ); - } else { - return ''; // the title was bad, normally this would indicate a software bug - } - } else { - if ( count( $this->mParams ) > 0 ) { - if ( strpos( SMWExporter::expandURI( '&wikiurl;' ), '?' ) === false ) { - $target = $this->mTarget . '?' . SMWInfolink::encodeParameters( $this->mParams, false ); - } else { - $target = $this->mTarget . '&' . SMWInfolink::encodeParameters( $this->mParams, false ); - } - } else { - $target = $this->mTarget; - } - - return $target; - } - } - - - /** - * Return a Linker object, using the parameter $linker if not null, and creatng a new one - * otherwise. $linker is usually a user skin object, while the fallback linker object is - * not customised to user settings. - * - * @return Linker - */ - protected function getLinker( &$linker = null ) { - if ( is_null( $linker ) ) { - $linker = class_exists('DummyLinker') ? new DummyLinker : new Linker; - } - return $linker; - } - - /** - * Encode an array of parameters, formatted as $name => $value, to a parameter - * string that can be used for linking. If $forTitle is true (default), then the - * parameters are encoded for use in a MediaWiki page title (useful for making - * internal links to parameterised special pages), otherwise the parameters are - * encoded HTTP GET style. The parameter name "x" is used to collect parameters - * that do not have any string keys in GET, and hence "x" should never be used - * as a parameter name. - * - * The function SMWInfolink::decodeParameters() can be used to undo this encoding. - * It is strongly recommended to not create any code that depends on the concrete - * way of how parameters are encoded within this function, and to always use the - * respective encoding/decoding methods instead. - * - * @param array $params - * @param boolean $forTitle - */ - static public function encodeParameters( array $params, $forTitle = true ) { - $result = ''; - - if ( $forTitle ) { - foreach ( $params as $name => $value ) { - if ( is_string( $name ) && ( $name !== '' ) ) { - $value = $name . '=' . $value; - } - // Escape certain problematic values. Use SMW-escape - // (like URLencode but - instead of % to prevent double encoding by later MW actions) - // - /// : SMW's parameter separator, must not occur within params - // - : used in SMW-encoding strings, needs escaping too - // [ ] < > < > '' |: problematic in MW titles - // & : sometimes problematic in MW titles ([[&]] is OK, [[&test]] is OK, [[&test;]] is not OK) - // (Note: '&' in strings obtained during parsing already has &entities; replaced by - // UTF8 anyway) - // ' ': are equivalent with '_' in MW titles, but are not equivalent in certain parameter values - // "\n": real breaks not possible in [[...]] - // "#": has special meaning in URLs, triggers additional MW escapes (using . for %) - // '%': must be escaped to prevent any impact of double decoding when replacing - - // by % before urldecode - // '?': if not escaped, strange effects were observed on some sites (printout and other - // parameters ignored without obvious cause); SMW-escaping is always save to do -- it just - // make URLs less readable - // - $value = str_replace( - array( '-', '#', "\n", ' ', '/', '[', ']', '<', '>', '<', '>', '&', '\'\'', '|', '&', '%', '?', '$' ), - array( '-2D', '-23', '-0A', '-20', '-2F', '-5B', '-5D', '-3C', '-3E', '-3C', '-3E', '-26', '-27-27', '-7C', '-26', '-25', '-3F', '-24' ), - $value - ); - - if ( $result !== '' ) { - $result .= '/'; - } - - $result .= $value; - } - } else { // Note: this requires to have HTTP compatible parameter names (ASCII) - $q = array(); // collect unlabelled query parameters here - - foreach ( $params as $name => $value ) { - if ( is_string( $name ) && ( $name !== '' ) ) { - $value = rawurlencode( $name ) . '=' . rawurlencode( $value ); - - if ( $result !== '' ) { - $result .= '&'; - } - - $result .= $value; - } else { - $q[] = $value; - } - } - if ( count( $q ) > 0 ) { // prepend encoding for unlabelled parameters - if ( $result !== '' ) { - $result = '&' . $result; - } - $result = 'x=' . rawurlencode( SMWInfolink::encodeParameters( $q, true ) ) . $result; - } - } - - return $result; - } - - /** - * Obtain an array of parameters from the parameters given to some HTTP service. - * In particular, this function perfoms all necessary decoding as may be needed, e.g., - * to recover the proper paramter strings after encoding for use in wiki title names - * as done by SMWInfolink::encodeParameters(). - * - * If $allparams is set to true, it is assumed that further data should be obtained - * from the global $wgRequest, and all given parameters are read. - * - * $titleparam is the string extracted by MediaWiki from special page calls of the - * form Special:Something/titleparam - * Note: it is assumed that the given $titleparam is already urldecoded, as is normal - * when getting such parameters from MediaWiki. SMW-escaped parameters largely prevent - * double decoding effects (i.e. there are no new "%" after one pass of urldecoding) - * - * The function SMWInfolink::encodeParameters() can be used to create a suitable - * encoding. It is strongly recommended to not create any code that depends on the - * concrete way of how parameters are encoded within this function, and to always use - * the respective encoding/decoding methods instead. - * - * @param string $titleParam - * @param boolean $allParams - */ - static public function decodeParameters( $titleParam = '', $allParams = false ) { - global $wgRequest; - - $result = array(); - - if ( $allParams ) { - $result = $wgRequest->getValues(); - - if ( array_key_exists( 'x', $result ) ) { // Considered to be part of the title param. - if ( $titleParam !== '' ) { - $titleParam .= '/'; - } - $titleParam .= $result['x']; - unset( $result['x'] ); - } - } - - if ( is_array( $titleParam ) ) { - return $titleParam; - } elseif ( $titleParam !== '' ) { - // unescape $p; escaping scheme: all parameters rawurlencoded, "-" and "/" urlencoded, all "%" replaced by "-", parameters then joined with / - $ps = explode( '/', $titleParam ); // params separated by / here (compatible with wiki link syntax) - - foreach ( $ps as $p ) { - if ( $p !== '' ) { - $p = rawurldecode( str_replace( '-', '%', $p ) ); - $parts = explode( '=', $p, 2 ); - - if ( count( $parts ) > 1 ) { - $result[$parts[0]] = $parts[1]; - } else { - $result[] = $p; - } - } - } - } - - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/SMW_Outputs.php b/SemanticMediaWiki/includes/SMW_Outputs.php deleted file mode 100644 index 111dcb03..00000000 --- a/SemanticMediaWiki/includes/SMW_Outputs.php +++ /dev/null @@ -1,200 +0,0 @@ -<?php - -/** - * This class attempts to provide safe yet simple means for managing data that is relevant - * for the final HTML output of MediaWiki. In particular, this concerns additions to the HTML - * header in the form of scripts of stylesheets. - * - * The problem is that many components in SMW create hypertext that should eventually be displayed. - * The normal way of accessing such text are functions of the form getText() which return a - * (hypertext) string. Such a string, however, might refer to styles or scripts that are also - * needed. It is not possible to directly add those scripts to the MediaWiki output, since the form - * of this output depends on the context in which the function is called. Many functions might be - * called both during parsing and directly in special pages that do not use the usual parsing and - * caching mechanisms. - * - * Ideally, all functions that generate hypertext with dependencies would also include parameters to - * record required scripts. Since this would require major API changes, the current solution is to have - * a "temporal" global storage for the required items, managed in this class. It is not safe to use - * such a global store accross hooks -- you never know what happens in between! Hence, every function - * that creates SMW outputs that may require head items must afterwards clear the temporal store by - * writing its contents to the according output. - * - * @file SMW_Ouputs.php - * @ingroup SMW - * - * @author Markus Krötzsch - */ -class SMWOutputs { - - /** - * Protected member for temporarily storing header items. - * Format $id => $headItem where $id is used only to avoid duplicate - * items in the time before they are forwarded to the output. - */ - protected static $headItems = array(); - - /** - * Protected member for temporarily storing additional Javascript - * snippets. Format $id => $scriptText where $id is used only to - * avoid duplicate scripts in the time before they are forwarded - * to the output. - */ - protected static $scripts = array(); - - /// Protected member for temporarily storing resource modules. - protected static $resourceModules = array(); - - /** - * Adds a resource module to the parser output. - * - * @since 1.5.3 - * - * @param string $moduleName - */ - public static function requireResource( $moduleName ) { - self::$resourceModules[$moduleName] = $moduleName; - } - - /** - * Require the presence of header scripts, provided as strings with - * enclosing script tags. Note that the same could be achieved with - * requireHeadItems, but scripts use a special method "addScript" in - * MediaWiki OutputPage, hence we distinguish them. - * - * The id is used to avoid that the requirement for one script is - * recorded multiple times in SMWOutputs. - * - * @param string $id - * @param string $item - */ - public static function requireScript( $id, $script ) { - self::$scripts[$id] = $script; - } - - /** - * Adds head items that are not Resource Loader modules. Should only - * be used for custom head items such as RSS fedd links. - * - * The id is used to avoid that the requirement for one script is - * recorded multiple times in SMWOutputs. - * - * Support for calling this with the old constants SMW_HEADER_STYLE - * and SMW_HEADER_TOOLTIP will vanish in SMW 1.7 at the latest. - * - * @param mixed $id - * @param string $item - */ - public static function requireHeadItem( $id, $item = '' ) { - if ( is_numeric( $id ) ) { - switch ( $id ) { - case SMW_HEADER_TOOLTIP: - self::requireResource( 'ext.smw.tooltips' ); - break; - case SMW_HEADER_STYLE: - self::requireResource( 'ext.smw.style' ); - break; - } - } else { - self::$headItems[$id] = $item; - } - } - - /** - * This function takes output requirements as can be found in a given ParserOutput - * object and puts them back in to the internal temporal requirement list from - * which they can be committed to some other output. It is needed when code that - * would normally call SMWOutputs::requireHeadItem() has need to use a full - * independent parser call (Parser::parse()) that produces its own parseroutput. - * If omitted, all output items potentially committed to this parseroutput during - * parsing will not be passed on to higher levels. - * - * Note that this is not required if the $parseroutput is further processed by - * MediaWiki, but there are cases where the output is discarded and only its text - * is used. - * - * @param ParserOutput $parserOutput - */ - static public function requireFromParserOutput( ParserOutput $parserOutput ) { - // Note: we do not attempt to recover which head items where scripts here. - - $parserOutputHeadItems = $parserOutput->getHeadItems(); - - self::$headItems = array_merge( (array)self::$headItems, $parserOutputHeadItems ); - - /// TODO Is the following needed? - if ( isset( $parserOutput->mModules ) ) { - foreach ( $parserOutput->mModules as $module ) { - self::$resourceModules[$module] = $module; - } - } - } - - /** - * Acutally commit the collected requirements to a given parser that is about to parse - * what will later be the HTML output. This makes sure that HTML output based on the - * parser results contains all required output items. - * - * If the parser creates output for a normal wiki page, then the committed items will - * also become part of the page cache so that they will correctly be added to all page - * outputs built from this cache later on. - * - * @param Parser $parser - */ - static public function commitToParser( Parser $parser ) { - /// TODO find out and document when this b/c code can go away - if ( method_exists( $parser, 'getOutput' ) ) { - $po = $parser->getOutput(); - } else { - $po = $parser->mOutput; - } - - if ( isset( $po ) ) { - self::commitToParserOutput( $po ); - } - } - - /** - * Similar to SMWOutputs::commitToParser() but acting on a ParserOutput object. - * - * @param ParserOutput $parserOutput - */ - static public function commitToParserOutput( ParserOutput $parserOutput ) { - foreach ( self::$scripts as $key => $script ) { - $parserOutput->addHeadItem( $script . "\n", $key ); - } - foreach ( self::$headItems as $key => $item ) { - $parserOutput->addHeadItem( "\t\t" . $item . "\n", $key ); - } - - $parserOutput->addModules( array_values( self::$resourceModules ) ); - - self::$resourceModules = array(); - self::$headItems = array(); - } - - /** - * Acutally commit the collected requirements to a given OutputPage object that - * will later generate the HTML output. This makes sure that HTML output contains - * all required output items. Note that there is no parser caching at this level of - * processing. In particular, data should not be committed to $wgOut in methods - * that run during page parsing, since these would not run next time when the page - * is produced from parser cache. - * - * @param OutputPage $output - */ - static public function commitToOutputPage( OutputPage $output ) { - foreach ( self::$scripts as $script ) { - $output->addScript( $script ); - } - foreach ( self::$headItems as $key => $item ) { - $output->addHeadItem( $key, "\t\t" . $item . "\n" ); - } - - $output->addModules( array_values( self::$resourceModules ) ); - - self::$resourceModules = array(); - self::$headItems = array(); - } - -} diff --git a/SemanticMediaWiki/includes/SMW_PageLister.php b/SemanticMediaWiki/includes/SMW_PageLister.php deleted file mode 100644 index cbd97bfa..00000000 --- a/SemanticMediaWiki/includes/SMW_PageLister.php +++ /dev/null @@ -1,307 +0,0 @@ -<?php - -/** - * Helper class to generate HTML lists of wiki pages, with support for paged - * navigation using the from/until and limit settings as in MediaWiki's - * CategoryPage. - * - * The class attempts to allow as much code as possible to be shared among - * different places where similar lists are used. - * - * Some code adapted from CategoryPage.php - * - * @file SMW_PageLister.php - * @ingroup SMW - * - * @author Nikolas Iwan - * @author Markus Krötzsch - * @author Jeroen De Dauw - */ -class SMWPageLister { - - protected $mDiWikiPages; - protected $mDiProperty; - protected $mLimit; - protected $mFrom; - protected $mUntil; - - /** - * Constructor - * - * @param $diWikiPages array of SMWDIWikiPage - * @param $diProperty mixed SMWDIProperty that the wikipages are values of, or null - * @param $limit integer maximal amount of items to display - * @param $from string if the results were selected starting from this string - * @param $until string if the results were selected reaching until this string - */ - public function __construct( array $diWikiPages, $diProperty, $limit, $from = '', $until = '' ) { - $this->mDiWikiPages = $diWikiPages; - $this->mDiProperty = $diProperty; - $this->mLimit = $limit; - $this->mFrom = $from; - $this->mUntil = $until; - } - - /** - * Generates the prev/next link part to the HTML code of the top and - * bottom section of the page. Whether and how these links appear - * depends on specified boundaries, limit, and results. The title is - * required to create a link to the right page. The query array gives - * optional further parameters to append to all navigation links. - * - * @param $title Title - * @param $query array that associates parameter names to parameter values - * @return string - */ - public function getNavigationLinks( Title $title, $query = array() ) { - global $wgLang; - - $limitText = $wgLang->formatNum( $this->mLimit ); - - $resultCount = count( $this->mDiWikiPages ); - $beyondLimit = ( $resultCount > $this->mLimit ); - - if ( !is_null( $this->mUntil ) && $this->mUntil !== '' ) { - if ( $beyondLimit ) { - $first = \SMW\StoreFactory::getStore()->getWikiPageSortKey( $this->mDiWikiPages[1] ); - } else { - $first = ''; - } - - $last = $this->mUntil; - } elseif ( $beyondLimit || ( !is_null( $this->mFrom ) && $this->mFrom !== '' ) ) { - $first = $this->mFrom; - - if ( $beyondLimit ) { - $last = \SMW\StoreFactory::getStore()->getWikiPageSortKey( $this->mDiWikiPages[$resultCount - 1] ); - } else { - $last = ''; - } - } else { - return ''; - } - - $prevLink = wfMessage( 'prevn', $limitText )->escaped(); - if ( $first !== '' ) { - $prevLink = $this->makeSelfLink( $title, $prevLink, $query + array( 'until' => $first ) ); - } - - $nextLink = wfMessage( 'nextn', $limitText )->escaped(); - if ( $last !== '' ) { - $nextLink = $this->makeSelfLink( $title, $nextLink, $query + array( 'from' => $last ) ); - } - - return "($prevLink) ($nextLink)"; - } - - /** - * Format an HTML link with the given text and parameters. - * - * @return string - */ - protected function makeSelfLink( Title $title, $linkText, array $parameters ) { - return smwfGetLinker()->link( $title, $linkText, array(), $parameters ); - } - - /** - * Make SMWRequestOptions suitable for obtaining a list of results for - * the given limit, and from or until string. One more result than the - * limit will be created, and the results may have to be reversed in - * order if ascending is set to false in the resulting object. - * - * @param $limit integer - * @param $from string can be empty if no from condition is desired - * @param $until string can be empty if no until condition is desired - * @return SMWRequestOptions - */ - public static function getRequestOptions( $limit, $from, $until ) { - $options = new SMWRequestOptions(); - $options->limit = $limit + 1; - $options->sort = true; - - if ( $from !== '' ) { - $options->boundary = $from; - $options->ascending = true; - $options->include_boundary = true; - } elseif ( $until !== '' ) { - $options->boundary = $until; - $options->ascending = false; - $options->include_boundary = false; - } - - return $options; - } - - /** - * Make SMWQuery suitable for obtaining a list of results based on the - * given description, limit, and from or until string. One more result - * than the limit will be created, and the results may have to be - * reversed in order if $until is nonempty. - * - * @param $description SMWDescription main query description - * @param $limit integer - * @param $from string can be empty if no from condition is desired - * @param $until string can be empty if no until condition is desired - * @return SMWQuery - */ - public static function getQuery( SMWDescription $description, $limit, $from, $until ) { - if ( $from !== '' ) { - $diWikiPage = new SMWDIWikiPage( $from, NS_MAIN, '' ); // make a dummy wiki page as boundary - $fromDescription = new SMWValueDescription( $diWikiPage, null, SMW_CMP_GEQ ); - $queryDescription = new SMWConjunction( array( $description, $fromDescription ) ); - $order = 'ASC'; - } elseif ( $until !== '' ) { - $diWikiPage = new SMWDIWikiPage( $until, NS_MAIN, '' ); // make a dummy wiki page as boundary - $untilDescription = new SMWValueDescription( $diWikiPage, null, SMW_CMP_LESS ); // do not include boundary in this case - $queryDescription = new SMWConjunction( array( $description, $untilDescription ) ); - $order = 'DESC'; - } else { - $queryDescription = $description; - $order = 'ASC'; - } - - $queryDescription->addPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, '' ) ); - - $query = new SMWQuery( $queryDescription ); - $query->sortkeys[''] = $order; - $query->setLimit( $limit + 1 ); - - return $query; - } - - /** - * Format a list of data items chunked by letter, either as a - * bullet list or a columnar format, depending on the length. - * - * @param $cutoff integer, use columns for more results than that - * @return string - */ - public function formatList( $cutoff = 6 ) { - $end = count( $this->mDiWikiPages ); - $start = 0; - if ( $end > $this->mLimit ) { - if ( $this->mFrom !== '' ) { - $end -= 1; - } else { - $start += 1; - } - } - - if ( count ( $this->mDiWikiPages ) > $cutoff ) { - return self::getColumnList( $start, $end, $this->mDiWikiPages, $this->mDiProperty ); - } elseif ( count( $this->mDiWikiPages ) > 0 ) { - return self::getShortList( $start, $end, $this->mDiWikiPages, $this->mDiProperty ); - } else { - return ''; - } - } - - /** - * Format a list of SMWDIWikiPage objects chunked by letter in a three-column - * list, ordered vertically. - * - * @param $start integer - * @param $end integer - * @param $diWikiPages array of SMWDIWikiPage - * @param $diProperty SMWDIProperty that the wikipages are values of, or null - * - * @return string - */ - public static function getColumnList( $start, $end, array $diWikiPages, $diProperty ) { - global $wgContLang; - - // Divide list into three equal chunks. - $chunk = (int) ( ( $end - $start + 1 ) / 3 ); - - // Get and display header. - $r = '<table width="100%"><tr valign="top">'; - - $prevStartChar = 'none'; - - // Loop through the chunks. - for ( $startChunk = $start, $endChunk = $chunk, $chunkIndex = 0; - $chunkIndex < 3; - ++$chunkIndex, $startChunk = $endChunk, $endChunk += $chunk + 1 ) { - $r .= "<td>\n"; - $atColumnTop = true; - - // output all diWikiPages - for ( $index = $startChunk ; $index < $endChunk && $index < $end; ++$index ) { - $dataValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $diWikiPages[$index], $diProperty ); - // check for change of starting letter or begining of chunk - $sortkey = \SMW\StoreFactory::getStore()->getWikiPageSortKey( $diWikiPages[$index] ); - $startChar = $wgContLang->convert( $wgContLang->firstChar( $sortkey ) ); - - if ( ( $index == $startChunk ) || - ( $startChar != $prevStartChar ) ) { - if ( $atColumnTop ) { - $atColumnTop = false; - } else { - $r .= "</ul>\n"; - } - - if ( $startChar == $prevStartChar ) { - $cont_msg = ' ' . wfMessage( 'listingcontinuesabbrev' )->escaped(); - } else { - $cont_msg = ''; - } - - $r .= "<h3>" . htmlspecialchars( $startChar ) . $cont_msg . "</h3>\n<ul>"; - - $prevStartChar = $startChar; - } - - $r .= "<li>" . $dataValue->getLongHTMLText( smwfGetLinker() ) . "</li>\n"; - } - - if ( !$atColumnTop ) { - $r .= "</ul>\n"; - } - - $r .= "</td>\n"; - } - - $r .= '</tr></table>'; - - return $r; - } - - /** - * Format a list of diWikiPages chunked by letter in a bullet list. - * - * @param $start integer - * @param $end integer - * @param $diWikiPages array of SMWDataItem - * @param $diProperty SMWDIProperty that the wikipages are values of, or null - * - * @return string - */ - public static function getShortList( $start, $end, array $diWikiPages, $diProperty ) { - global $wgContLang; - - $startDv = \SMW\DataValueFactory::getInstance()->newDataItemValue( $diWikiPages[$start], $diProperty ); - $sortkey = \SMW\StoreFactory::getStore()->getWikiPageSortKey( $diWikiPages[$start] ); - $startChar = $wgContLang->convert( $wgContLang->firstChar( $sortkey ) ); - $r = '<h3>' . htmlspecialchars( $startChar ) . "</h3>\n" . - '<ul><li>' . $startDv->getLongHTMLText( smwfGetLinker() ) . '</li>'; - - $prevStartChar = $startChar; - for ( $index = $start + 1; $index < $end; $index++ ) { - $dataValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $diWikiPages[$index], $diProperty ); - $sortkey = \SMW\StoreFactory::getStore()->getWikiPageSortKey( $diWikiPages[$index] ); - $startChar = $wgContLang->convert( $wgContLang->firstChar( $sortkey ) ); - - if ( $startChar != $prevStartChar ) { - $r .= "</ul><h3>" . htmlspecialchars( $startChar ) . "</h3>\n<ul>"; - $prevStartChar = $startChar; - } - - $r .= '<li>' . $dataValue->getLongHTMLText( smwfGetLinker() ) . '</li>'; - } - - $r .= '</ul>'; - - return $r; - } - -} diff --git a/SemanticMediaWiki/includes/SMW_PageSchemas.php b/SemanticMediaWiki/includes/SMW_PageSchemas.php deleted file mode 100644 index b7b3cd58..00000000 --- a/SemanticMediaWiki/includes/SMW_PageSchemas.php +++ /dev/null @@ -1,378 +0,0 @@ -<?php - -/** - * Functions for handling Semantic MediaWiki data within the Page Schemas - * extension. - * - * @author Ankit Garg - * @author Yaron Koren - * @file SMW_PageSchemas.php - * @ingroup SMW - */ - -class SMWPageSchemas extends PSExtensionHandler { - - public static function getDisplayColor() { - return '#DEF'; - } - - public static function getTemplateDisplayString() { - return 'Connecting property'; - } - - public static function getFieldDisplayString() { - return 'Semantic property'; - } - - /** - * Returns the display info for the "connecting property" (if any) - * of the #subobject call (if any) in this template. - */ - public static function getTemplateDisplayValues( $templateXML ) { - foreach ( $templateXML->children() as $tag => $child ) { - if ( $tag == "semanticmediawiki_ConnectingProperty" ) { - $propName = $child->attributes()->name; - $values = array(); - return array( $propName, $values ); - } - } - return null; - } - - /** - * Returns the display info for the property (if any is defined) - * for a single field in the Page Schemas XML. - */ - public static function getFieldDisplayValues( $fieldXML ) { - foreach ( $fieldXML->children() as $tag => $child ) { - if ( $tag == "semanticmediawiki_Property" ) { - $propName = $child->attributes()->name; - $values = array(); - foreach ( $child->children() as $prop => $value ) { - $values[$prop] = (string)$value; - } - return array( $propName, $values ); - } - } - return null; - } - - /** - * Returns the set of SMW property data from the entire page schema. - */ - static function getAllPropertyData( $pageSchemaObj ) { - $propertyDataArray = array(); - $psTemplates = $pageSchemaObj->getTemplates(); - foreach ( $psTemplates as $psTemplate ) { - $psTemplateFields = $psTemplate->getFields(); - foreach ( $psTemplateFields as $psTemplateField ) { - $prop_array = $psTemplateField->getObject('semanticmediawiki_Property'); - if ( empty( $prop_array ) ) { - continue; - } - // If property name is blank, set it to the - // field name. - if ( !array_key_exists( 'name', $prop_array ) || empty( $prop_array['name'] ) ) { - $prop_array['name'] = $psTemplateField->getName(); - } - $propertyDataArray[] = $prop_array; - } - } - return $propertyDataArray; - } - - /** - * Constructs XML for the "connecting property", based on what was - * submitted in the 'edit schema' form. - */ - public static function createTemplateXMLFromForm() { - global $wgRequest; - - $xmlPerTemplate = array(); - foreach ( $wgRequest->getValues() as $var => $val ) { - if ( substr( $var, 0, 24 ) == 'smw_connecting_property_' ) { - $templateNum = substr( $var, 24 ); - $xml = '<semanticmediawiki_ConnectingProperty name="' . $val . '" />'; - $xmlPerTemplate[$templateNum] = $xml; - } - } - return $xmlPerTemplate; - } - - static function getConnectingPropertyName( $psTemplate ) { - // TODO - there should be a more direct way to get - // this data. - $smwConnectingPropertyArray = $psTemplate->getObject( 'semanticmediawiki_ConnectingProperty' ); - return PageSchemas::getValueFromObject( $smwConnectingPropertyArray, 'name' ); - } - - /** - * Sets the list of property pages defined by the passed-in - * Page Schemas object. - */ - public static function getPagesToGenerate( $pageSchemaObj ) { - $pagesToGenerate = array(); - - $psTemplates = $pageSchemaObj->getTemplates(); - foreach ( $psTemplates as $psTemplate ) { - $smwConnectingPropertyName = self::getConnectingPropertyName( $psTemplate ); - if ( is_null( $smwConnectingPropertyName ) ) { - continue; - } - $pagesToGenerate[] = Title::makeTitleSafe( SMW_NS_PROPERTY, $smwConnectingPropertyName ); - } - - $propertyDataArray = self::getAllPropertyData( $pageSchemaObj ); - foreach ( $propertyDataArray as $propertyData ) { - $title = Title::makeTitleSafe( SMW_NS_PROPERTY, $propertyData['name'] ); - $pagesToGenerate[] = $title; - } - return $pagesToGenerate; - } - - /** - * Constructs XML for the SMW property, based on what was submitted - * in the 'edit schema' form. - */ - public static function createFieldXMLFromForm() { - global $wgRequest; - - $fieldNum = -1; - $xmlPerField = array(); - foreach ( $wgRequest->getValues() as $var => $val ) { - if ( substr( $var, 0, 18 ) == 'smw_property_name_' ) { - $fieldNum = substr( $var, 18 ); - $xml = '<semanticmediawiki_Property name="' . $val . '" >'; - } elseif ( substr( $var, 0, 18 ) == 'smw_property_type_'){ - $xml .= '<Type>' . $val . '</Type>'; - } elseif ( substr( $var, 0, 16 ) == 'smw_linked_form_') { - if ( $val !== '' ) { - $xml .= '<LinkedForm>' . $val . '</LinkedForm>'; - } - } elseif ( substr( $var, 0, 11 ) == 'smw_values_') { - if ( $val !== '' ) { - // replace the comma substitution character that has no chance of - // being included in the values list - namely, the ASCII beep - $listSeparator = ','; - $allowed_values_str = str_replace( "\\$listSeparator", "\a", $val ); - $allowed_values_array = explode( $listSeparator, $allowed_values_str ); - foreach ( $allowed_values_array as $value ) { - // replace beep back with comma, trim - $value = str_replace( "\a", $listSeparator, trim( $value ) ); - $xml .= '<AllowedValue>' . $value . '</AllowedValue>'; - } - } - $xml .= '</semanticmediawiki_Property>'; - $xmlPerField[$fieldNum] = $xml; - } - } - return $xmlPerField; - } - - /** - * Returns the HTML necessary for getting information about the - * "connecting property" within the Page Schemas 'editschema' page. - */ - public static function getTemplateEditingHTML( $psTemplate) { - // Only display this if the Semantic Internal Objects extension - // isn't displaying something similar. - if ( class_exists( 'SIOPageSchemas' ) ) { - return null; - } - - $prop_array = array(); - $hasExistingValues = false; - if ( !is_null( $psTemplate ) ) { - $prop_array = $psTemplate->getObject( 'semanticmediawiki_ConnectingProperty' ); - if ( !is_null( $prop_array ) ) { - $hasExistingValues = true; - } - } - $text = '<p>' . 'Name of property to connect this template\'s fields to the rest of the page:' . ' ' . '(should only be used if this template can have multiple instances)' . ' '; - $propName = PageSchemas::getValueFromObject( $prop_array, 'name' ); - $text .= Html::input( 'smw_connecting_property_num', $propName, array( 'size' => 15 ) ) . "\n"; - - return array( $text, $hasExistingValues ); - } - - /** - * Returns the HTML necessary for getting information about a regular - * semantic property within the Page Schemas 'editschema' page. - */ - public static function getFieldEditingHTML( $psTemplateField ) { - global $smwgContLang; - - $prop_array = array(); - $hasExistingValues = false; - if ( !is_null( $psTemplateField ) ) { - $prop_array = $psTemplateField->getObject('semanticmediawiki_Property'); - if ( !is_null( $prop_array ) ) { - $hasExistingValues = true; - } - } - $html_text = '<p>' . wfMessage( 'ps-optional-name' )->text() . ' '; - $propName = PageSchemas::getValueFromObject( $prop_array, 'name' ); - $html_text .= Html::input( 'smw_property_name_num', $propName, array( 'size' => 15 ) ) . "\n"; - $propType = PageSchemas::getValueFromObject( $prop_array, 'Type' ); - $select_body = ""; - $datatype_labels = $smwgContLang->getDatatypeLabels(); - foreach ( $datatype_labels as $label ) { - $optionAttrs = array(); - if ( $label == $propType) { - $optionAttrs['selected'] = 'selected'; - } - $select_body .= "\t" . Xml::element( 'option', $optionAttrs, $label ) . "\n"; - } - $propertyDropdownAttrs = array( - 'id' => 'property_dropdown', - 'name' => 'smw_property_type_num', - 'value' => $propType - ); - $html_text .= "Type: " . Xml::tags( 'select', $propertyDropdownAttrs, $select_body ) . "</p>\n"; - - // This can't be last, because of the hacky way the XML is - // ocnstructed from this form's output. - if ( defined( 'SF_VERSION' ) ) { - $html_text .= '<p>' . wfMessage( 'sf_createproperty_linktoform' )->text() . ' '; - $linkedForm = PageSchemas::getValueFromObject( $prop_array, 'LinkedForm' ); - $html_text .= Html::input( 'smw_linked_form_num', $linkedForm, array( 'size' => 15 ) ) . "\n"; - $html_text .= "(for Page properties only)</p>\n"; - } - - $html_text .= '<p>If you want this property to only be allowed to have certain values, enter the list of allowed values, separated by commas (if a value contains a comma, replace it with "\,"):</p>'; - $allowedValsInputAttrs = array( - 'size' => 80 - ); - $allowedValues = PageSchemas::getValueFromObject( $prop_array, 'allowed_values' ); - if ( is_null( $allowedValues ) ) { - $allowed_val_string = ''; - } else { - $allowed_val_string = implode( ', ', $allowedValues ); - } - $html_text .= '<p>' . Html::input( 'smw_values_num', $allowed_val_string, 'text', $allowedValsInputAttrs ) . "</p>\n"; - - return array( $html_text, $hasExistingValues ); - } - - /** - * Creates the property page for each property specified in the - * passed-in Page Schemas XML object. - */ - public static function generatePages( $pageSchemaObj, $selectedPages ) { - global $smwgContLang, $wgUser; - - $datatypeLabels = $smwgContLang->getDatatypeLabels(); - $pageTypeLabel = $datatypeLabels['_wpg']; - - $jobs = array(); - $jobParams = array(); - $jobParams['user_id'] = $wgUser->getId(); - - // First, create jobs for all "connecting properties". - $psTemplates = $pageSchemaObj->getTemplates(); - foreach ( $psTemplates as $psTemplate ) { - $smwConnectingPropertyName = self::getConnectingPropertyName( $psTemplate ); - if ( is_null( $smwConnectingPropertyName ) ) { - continue; - } - $propTitle = Title::makeTitleSafe( SMW_NS_PROPERTY, $smwConnectingPropertyName ); - if ( !in_array( $propTitle, $selectedPages ) ) { - continue; - } - - $jobParams['page_text'] = self::createPropertyText( $pageTypeLabel, null, null ); - $jobs[] = new PSCreatePageJob( $propTitle, $jobParams ); - } - - // Second, create jobs for all regular properties. - $propertyDataArray = self::getAllPropertyData( $pageSchemaObj ); - foreach ( $propertyDataArray as $propertyData ) { - $propTitle = Title::makeTitleSafe( SMW_NS_PROPERTY, $propertyData['name'] ); - if ( !in_array( $propTitle, $selectedPages ) ) { - continue; - } - $jobParams['page_text'] = self::createPropertyText( $propertyData['Type'], $propertyData['allowed_values'], $propertyData['LinkedForm'] ); - $jobs[] = new PSCreatePageJob( $propTitle, $jobParams ); - } - Job::batchInsert( $jobs ); - } - - /** - * Creates the text for a property page. - */ - public function createPropertyText( $propertyType, $allowedValues, $linkedForm = null ) { - /** - * @var SMWLanguage $smwgContLang - */ - global $smwgContLang, $wgContLang; - - $propLabels = $smwgContLang->getPropertyLabels(); - $hasTypeLabel = $propLabels['_TYPE']; - $typeTag = "[[$hasTypeLabel::$propertyType]]"; - $text = wfMessage( 'smw-createproperty-isproperty', $typeTag )->inContentLanguage()->text(); - - if ( $linkedForm !== '' && defined( 'SF_VERSION' ) ) { - global $sfgContLang; - $sfPropLabels = $sfgContLang->getPropertyLabels(); - $defaultFormTag = "[[{$sfPropLabels[SF_SP_HAS_DEFAULT_FORM]}::$linkedForm]]"; - $text .= ' ' . wfMessage( 'sf_property_linkstoform', $defaultFormTag )->inContentLanguage()->text(); - } - - if ( $allowedValues != null) { - $text .= "\n\n" . wfMessage( 'smw-createproperty-allowedvals', $wgContLang->formatNum( count( $allowedValues ) ) )->inContentLanguage()->text(); - - foreach ( $allowedValues as $value ) { - if ( method_exists( $smwgContLang, 'getPropertyLabels' ) ) { - $prop_labels = $smwgContLang->getPropertyLabels(); - $text .= "\n* [[" . $prop_labels['_PVAL'] . "::$value]]"; - } else { - $spec_props = $smwgContLang->getSpecialPropertiesArray(); - // FIXME: SMW_SP_POSSIBLE_VALUE is undefined! - $text .= "\n* [[" . $spec_props[SMW_SP_POSSIBLE_VALUE] . "::$value]]"; - } - } - } - - return $text; - } - - /** - * Returns either the "connecting property", or a field property, based - * on the XML passed from the Page Schemas extension. - */ - public static function createPageSchemasObject( $tagName, $xml ) { - if ( $tagName == "semanticmediawiki_ConnectingProperty" ) { - foreach ( $xml->children() as $tag => $child ) { - if ( $tag == $tagName ) { - $smw_array = array(); - $propName = $child->attributes()->name; - $smw_array['name'] = (string)$propName; - foreach ( $child->children() as $prop => $value ) { - $smw_array[$prop] = (string)$value; - } - return $smw_array; - } - } - } elseif ( $tagName == "semanticmediawiki_Property" ) { - foreach ( $xml->children() as $tag => $child ) { - if ( $tag == $tagName ) { - $smw_array = array(); - $propName = $child->attributes()->name; - $smw_array['name'] = (string)$propName; - $allowed_values = array(); - $count = 0; - foreach ( $child->children() as $prop => $value ) { - if ( $prop == "AllowedValue" ) { - $allowed_values[$count++] = $value; - } else { - $smw_array[$prop] = (string)$value; - } - } - $smw_array['allowed_values'] = $allowed_values; - return $smw_array; - } - } - } - return null; - } -} diff --git a/SemanticMediaWiki/includes/SemanticData.php b/SemanticMediaWiki/includes/SemanticData.php deleted file mode 100644 index 3190cac0..00000000 --- a/SemanticMediaWiki/includes/SemanticData.php +++ /dev/null @@ -1,641 +0,0 @@ -<?php - -namespace SMW; - -use MWException; -use SMWDataValue; -use SMWDIContainer; -use SMWDataItem; -use SMWContainerSemanticData; -use SMWPropertyValue; - -/** - * Class for representing chunks of semantic data for one given - * subject. This consists of property-value pairs, grouped by property, - * and possibly by SMWSemanticData objects about subobjects. - * - * Data about subobjects can be added in two ways: by directly adding it - * using addSubSemanticData() or by adding a property value of type - * SMWDIContainer. - * - * By its very design, the container is unable to hold inverse properties. - * For one thing, it would not be possible to identify them with mere keys. - * Since SMW cannot annotate pages with inverses, this is not a limitation. - * - * @ingroup SMW - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - */ -class SemanticData { - - /** - * Cache for the localized version of the namespace prefix "Property:". - * - * @var string - */ - static protected $mPropertyPrefix = ''; - - /** - * States whether this is a stub object. Stubbing might happen on - * serialisation to save DB space. - * - * @todo Check why this is public and document this here. Or fix it. - * - * @var boolean - */ - public $stubObject; - - /** - * Array mapping property keys (string) to arrays of SMWDataItem - * objects. - * - * @var SMWDataItem[] - */ - protected $mPropVals = array(); - - /** - * Array mapping property keys (string) to DIProperty objects. - * - * @var DIProperty[] - */ - protected $mProperties = array(); - - /** - * States whether the container holds any normal properties. - * - * @var boolean - */ - protected $mHasVisibleProps = false; - - /** - * States whether the container holds any displayable predefined - * $mProperties (as opposed to predefined properties without a display - * label). For some settings we need this to decide if a Factbox is - * displayed. - * - * @var boolean - */ - protected $mHasVisibleSpecs = false; - - /** - * States whether repeated values should be avoided. Not needing - * duplicate elimination (e.g. when loading from store) can save some - * time, especially in subclasses like SMWSqlStubSemanticData, where - * the first access to a data item is more costy. - * - * @note This setting is merely for optimization. The SMW data model - * never cares about the multiplicity of identical data assignments. - * - * @var boolean - */ - protected $mNoDuplicates; - - /** - * DIWikiPage object that is the subject of this container. - * Subjects can never be null (and this is ensured in all methods setting - * them in this class). - * - * @var DIWikiPage - */ - protected $mSubject; - - /** - * Semantic data associated to subobjects of the subject of this - * SMWSemanticData. - * These key-value pairs of subObjectName (string) =>SMWSemanticData. - * - * @since 1.8 - * @var SemanticData[] - */ - protected $subSemanticData = array(); - - /** - * Internal flag that indicates if this semantic data will accept - * subdata. Semantic data objects that are subdata already do not allow - * (second level) subdata to be added. This ensures that all data is - * collected on the top level, and in particular that there is only one - * way to represent the same data with subdata. This is also useful for - * diff computation. - */ - protected $subDataAllowed = true; - - /** @var array */ - protected $errors = array(); - - /** - * Constructor. - * - * @param DIWikiPage $subject to which this data refers - * @param boolean $noDuplicates stating if duplicate data should be avoided - */ - public function __construct( DIWikiPage $subject, $noDuplicates = true ) { - $this->clear(); - $this->mSubject = $subject; - $this->mNoDuplicates = $noDuplicates; - } - - /** - * This object is added to the parser output of MediaWiki, but it is - * not useful to have all its data as part of the parser cache since - * the data is already stored in more accessible format in SMW. Hence - * this implementation of __sleep() makes sure only the subject is - * serialised, yielding a minimal stub data container after - * unserialisation. This is a little safer than serialising nothing: - * if, for any reason, SMW should ever access an unserialised parser - * output, then the Semdata container will at least look as if properly - * initialised (though empty). - * - * @return array - */ - public function __sleep() { - return array( 'mSubject' ); - } - - /** - * Return subject to which the stored semantic annotations refer to. - * - * @return DIWikiPage subject - */ - public function getSubject() { - return $this->mSubject; - } - - /** - * Get the array of all properties that have stored values. - * - * @return array of DIProperty objects - */ - public function getProperties() { - ksort( $this->mProperties, SORT_STRING ); - return $this->mProperties; - } - - /** - * Get the array of all stored values for some property. - * - * @param DIProperty $property - * @return SMWDataItem[] - */ - public function getPropertyValues( DIProperty $property ) { - if ( $property->isInverse() ) { // we never have any data for inverses - return array(); - } - - if ( array_key_exists( $property->getKey(), $this->mPropVals ) ) { - return $this->mPropVals[$property->getKey()]; - } else { - return array(); - } - } - - /** - * Returns collected errors occurred during processing - * - * @since 1.9 - * - * @return array - */ - public function getErrors() { - return $this->errors; - } - - /** - * Adds an error array - * - * @since 1.9 - * - * @return array - */ - public function addError( array $errors ) { - return $this->errors = array_merge( $errors, $this->errors ); - } - - /** - * Generate a hash value to simplify the comparison of this data - * container with other containers. Subdata is taken into account. - * - * The hash uses PHP's md5 implementation, which is among the fastest - * hash algorithms that PHP offers. - * - * @note This function may be used to obtain keys for SemanticData - * objects or to do simple equalitiy tests. Equal hashes with very - * high probability indicate equal data. However, the hash is - * sensitive to the order of properties and values, so it does not - * yield a reliable way to detect inequality: objects with different - * hashes may still contain the same data, added in different order. - * - * @return string - */ - public function getHash() { - $stringToHash = ''; - - // here and below, use "_#_" to separate values; really not much care needed here - $stringToHash .= '_#_' . $this->mSubject->getSerialization(); - - foreach ( $this->getProperties() as $property ) { - $stringToHash .= '_#_' . $property->getKey() . '##'; - - foreach ( $this->getPropertyValues( $property ) as $di ) { - $stringToHash .= '_#_' . $di->getSerialization(); - } - $stringToHash = md5( $stringToHash ); // intermediate hashing to safe memory - } - - foreach ( $this->getSubSemanticData() as $data ) { - $stringToHash .= '#' . $data->getHash(); - } - - return md5( $stringToHash ); - } - - /** - * Return the array of subSemanticData objects for this SemanticData - * - * @since 1.8 - * @return SMWContainerSemanticData[] subobject => SMWContainerSemanticData - */ - public function getSubSemanticData() { - return $this->subSemanticData; - } - - /** - * Return true if there are any visible properties. - * - * @note While called "visible" this check actually refers to the - * function DIProperty::isShown(). The name is kept for - * compatibility. - * - * @return boolean - */ - public function hasVisibleProperties() { - return $this->mHasVisibleProps; - } - - /** - * Return true if there are any special properties that can - * be displayed. - * - * @note While called "visible" this check actually refers to the - * function DIProperty::isShown(). The name is kept for - * compatibility. - * - * @return boolean - */ - public function hasVisibleSpecialProperties() { - return $this->mHasVisibleSpecs; - } - - /** - * Store a value for a property identified by its SMWDataItem object. - * - * @note There is no check whether the type of the given data item - * agrees with the type of the property. Since property types can - * change, all parts of SMW are prepared to handle mismatched data item - * types anyway. - * - * @param $property DIProperty - * @param $dataItem SMWDataItem - */ - public function addPropertyObjectValue( DIProperty $property, SMWDataItem $dataItem ) { - if( $dataItem instanceof SMWDIContainer ) { - $this->addSubSemanticData( $dataItem->getSemanticData() ); - $dataItem = $dataItem->getSemanticData()->getSubject(); - } - - if ( $property->isInverse() ) { // inverse properties cannot be used for annotation - return; - } - - if ( !array_key_exists( $property->getKey(), $this->mPropVals ) ) { - $this->mPropVals[$property->getKey()] = array(); - $this->mProperties[$property->getKey()] = $property; - } - - if ( $this->mNoDuplicates ) { - $this->mPropVals[$property->getKey()][$dataItem->getHash()] = $dataItem; - } else { - $this->mPropVals[$property->getKey()][] = $dataItem; - } - - if ( !$property->isUserDefined() ) { - if ( $property->isShown() ) { - $this->mHasVisibleSpecs = true; - $this->mHasVisibleProps = true; - } - } else { - $this->mHasVisibleProps = true; - } - } - - /** - * Store a value for a given property identified by its text label - * (without namespace prefix). - * - * @param $propertyName string - * @param $dataItem SMWDataItem - */ - public function addPropertyValue( $propertyName, SMWDataItem $dataItem ) { - $propertyKey = smwfNormalTitleDBKey( $propertyName ); - - if ( array_key_exists( $propertyKey, $this->mProperties ) ) { - $property = $this->mProperties[$propertyKey]; - } else { - if ( self::$mPropertyPrefix === '' ) { - global $wgContLang; - self::$mPropertyPrefix = $wgContLang->getNsText( SMW_NS_PROPERTY ) . ':'; - } // explicitly use prefix to cope with things like [[Property:User:Stupid::somevalue]] - - $propertyDV = SMWPropertyValue::makeUserProperty( self::$mPropertyPrefix . $propertyName ); - - if ( !$propertyDV->isValid() ) { // error, maybe illegal title text - return; - } - - $property = $propertyDV->getDataItem(); - } - - $this->addPropertyObjectValue( $property, $dataItem ); - } - - /** - * Adds a DataValue object to the semantic data container - * - * @par Example: - * @code - * $dataValue = DataValueFactory::getInstance()->newPropertyValue( $userProperty, $userValue ) - * $semanticData->addDataValue( $dataValue ) - * @endcode - * - * @since 1.9 - * - * @param SMWDataValue $dataValue - */ - public function addDataValue( SMWDataValue $dataValue ) { - Profiler::In( __METHOD__, true ); - - if ( $dataValue->getProperty() instanceof DIProperty ) { - if ( !$dataValue->isValid() ) { - $this->addPropertyObjectValue( - new DIProperty( DIProperty::TYPE_ERROR ), - $dataValue->getProperty()->getDiWikiPage() - ); - $this->addError( $dataValue->getErrors() ); - } else { - $this->addPropertyObjectValue( - $dataValue->getProperty(), - $dataValue->getDataItem() - ); - } - } else { - $this->addError( $dataValue->getErrors() ); - } - - Profiler::Out( __METHOD__, true ); - } - - /** - * Remove a value for a property identified by its SMWDataItem object. - * This method removes a property-value specified by the property and - * dataitem. If there are no more property-values for this property it - * also removes the property from the mProperties. - * - * @note There is no check whether the type of the given data item - * agrees with the type of the property. Since property types can - * change, all parts of SMW are prepared to handle mismatched data item - * types anyway. - * - * @param $property DIProperty - * @param $dataItem SMWDataItem - * - * @since 1.8 - */ - public function removePropertyObjectValue( DIProperty $property, SMWDataItem $dataItem ) { - //delete associated subSemanticData - if( $dataItem instanceof SMWDIContainer ) { - $this->removeSubSemanticData( $dataItem->getSemanticData() ); - $dataItem = $dataItem->getSemanticData()->getSubject(); - } - - if ( $property->isInverse() ) { // inverse properties cannot be used for annotation - return; - } - - if ( !array_key_exists( $property->getKey(), $this->mPropVals ) || !array_key_exists( $property->getKey(), $this->mProperties ) ) { - return; - } - - if ( $this->mNoDuplicates ) { - //this didn't get checked for my tests, but should work - unset( $this->mPropVals[$property->getKey()][$dataItem->getHash()] ); - } else { - foreach( $this->mPropVals[$property->getKey()] as $index => $di ) { - if( $di->equals( $dataItem ) ) - unset( $this->mPropVals[$property->getKey()][$index] ); - } - $this->mPropVals[$property->getKey()] = array_values( $this->mPropVals[$property->getKey()] ); - } - - if ( $this->mPropVals[$property->getKey()] === array() ) { - unset( $this->mProperties[$property->getKey()] ); - unset( $this->mPropVals[$property->getKey()] ); - } - } - - /** - * Delete all data other than the subject. - */ - public function clear() { - $this->mPropVals = array(); - $this->mProperties = array(); - $this->mHasVisibleProps = false; - $this->mHasVisibleSpecs = false; - $this->stubObject = false; - $this->subSemanticData = array(); - } - - /** - * Return true if this SemanticData is empty. - * This is the case when the subject has neither property values nor - * data for subobjects. - * - * since 1.8 - * @return boolean - */ - public function isEmpty() { - return empty( $this->mProperties ) && empty( $this->subSemanticData ); - } - - /** - * Add all data from the given SMWSemanticData. - * Only works if the imported SMWSemanticData has the same subject as - * this SMWSemanticData; an exception is thrown otherwise. - * - * @since 1.7 - * - * @param SemanticData $semanticData object to copy from - * - * @throws MWException if subjects do not match - */ - public function importDataFrom( SemanticData $semanticData ) { - - if( !$this->mSubject->equals( $semanticData->getSubject() ) ) { - throw new MWException( "SMWSemanticData can only represent data about one subject. Importing data for another subject is not possible." ); - } - - // Shortcut when copying into empty objects that don't ask for - // more duplicate elimination: - if ( count( $this->mProperties ) == 0 && - ( $semanticData->mNoDuplicates >= $this->mNoDuplicates ) ) { - $this->mProperties = $semanticData->getProperties(); - $this->mPropVals = array(); - - foreach ( $this->mProperties as $property ) { - $this->mPropVals[$property->getKey()] = $semanticData->getPropertyValues( $property ); - } - - $this->mHasVisibleProps = $semanticData->hasVisibleProperties(); - $this->mHasVisibleSpecs = $semanticData->hasVisibleSpecialProperties(); - } else { - foreach ( $semanticData->getProperties() as $property ) { - $values = $semanticData->getPropertyValues( $property ); - - foreach ( $values as $dataItem ) { - $this->addPropertyObjectValue( $property, $dataItem); - } - } - } - - foreach( $semanticData->getSubSemanticData() as $semData ) { - $this->addSubSemanticData( $semData ); - } - } - - /** - * Removes data from the given SMWSemanticData. - * If the subject of the data that is to be removed is not equal to the - * subject of this SMWSemanticData, it will just be ignored (nothing to - * remove). Likewise, removing data that is not present does not change - * anything. - * - * @since 1.8 - * - * @param SemanticData $semanticData - */ - public function removeDataFrom( SemanticData $semanticData ) { - if( !$this->mSubject->equals( $semanticData->getSubject() ) ) { - return; - } - - foreach ( $semanticData->getProperties() as $property ) { - $values = $semanticData->getPropertyValues( $property ); - foreach ( $values as $dataItem ) { - $this->removePropertyObjectValue( $property, $dataItem ); - } - } - - foreach( $semanticData->getSubSemanticData() as $semData ) { - $this->removeSubSemanticData( $semData ); - } - } - - /** - * Whether the SemanticData has a SubSemanticData container and if - * specified has a particluar subobject using its name as identifier - * - * @since 1.9 - * - * @param string $subobjectName|null - * - * @return boolean - */ - public function hasSubSemanticData( $subobjectName = null ) { - - if ( $this->subSemanticData === array() ) { - return false; - } - - return $subobjectName !== null ? isset( $this->subSemanticData[ $subobjectName ] ) : true; - } - - /** - * Find a particular subobject container using its name as identifier - * - * @since 1.9 - * - * @param string $subobjectName - * - * @return SMWContainerSemanticData|[] - */ - public function findSubSemanticData( $subobjectName ) { - - if ( $this->hasSubSemanticData( $subobjectName ) ) { - return $this->subSemanticData[ $subobjectName ]; - } - - return array(); - } - - /** - * Add data about subobjects. - * Will only work if the data that is added is about a subobject of - * this SMWSemanticData's subject. Otherwise an exception is thrown. - * The SMWSemanticData object that is given will belong to this object - * after the operation; it should not be modified further by the caller. - * - * @since 1.8 - * - * @param SemanticData $semanticData - * - * @throws MWException if not adding data about a subobject of this data - */ - public function addSubSemanticData( SemanticData $semanticData ) { - if ( !$this->subDataAllowed ) { - throw new MWException( "Cannot add subdata. Are you trying to add data to an SMWSemanticData object that is already used as a subdata object?" ); - } - $subobjectName = $semanticData->getSubject()->getSubobjectName(); - if ( $subobjectName == '' ) { - throw new MWException( "Cannot add data that is not about a subobject." ); - } - if( $semanticData->getSubject()->getDBkey() !== $this->getSubject()->getDBkey() ) { - throw new MWException( "Data for a subobject of {$semanticData->getSubject()->getDBkey()} cannot be added to {$this->getSubject()->getDBkey()}." ); - } - - if( $this->hasSubSemanticData( $subobjectName ) ) { - $this->subSemanticData[$subobjectName]->importDataFrom( $semanticData ); - } else { - $semanticData->subDataAllowed = false; - foreach ( $semanticData->getSubSemanticData() as $subsubdata ) { - $this->addSubSemanticData( $subsubdata ); - } - $semanticData->subSemanticData = array(); - $this->subSemanticData[$subobjectName] = $semanticData; - } - } - - /** - * Remove data about a subobject. - * If the removed data is not about a subobject of this object, - * it will silently be ignored (nothing to remove). Likewise, - * removing data that is not present does not change anything. - * - * @since 1.8 - * @param SMWSemanticData - */ - public function removeSubSemanticData( SemanticData $semanticData ) { - if( $semanticData->getSubject()->getDBkey() !== $this->getSubject()->getDBkey() ) { - return; - } - - $subobjectName = $semanticData->getSubject()->getSubobjectName(); - - if( $this->hasSubSemanticData( $subobjectName ) ) { - $this->subSemanticData[$subobjectName]->removeDataFrom( $semanticData ); - - if( $this->subSemanticData[$subobjectName]->isEmpty() ) { - unset( $this->subSemanticData[$subobjectName] ); - } - } - } - -} diff --git a/SemanticMediaWiki/includes/Settings.php b/SemanticMediaWiki/includes/Settings.php deleted file mode 100644 index 303fe99a..00000000 --- a/SemanticMediaWiki/includes/Settings.php +++ /dev/null @@ -1,233 +0,0 @@ -<?php - -namespace SMW; - -/** - * Encapsulate Semantic MediaWiki settings - * - * @note Initial idea has been borrowed from EducationProgram Extension/Jeroen De Dauw - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Encapsulate Semantic MediaWiki settings to access values through a - * specified interface - * - * @ingroup SMW - */ -class Settings extends SimpleDictionary { - - /** @var Settings */ - private static $instance = null; - - /** - * Assemble individual SMW related settings into one accessible array for - * easy instantiation since we don't have unique way of accessing only - * SMW related settings ( e.g. $smwgSettings['...']) we need this method - * as short cut to invoke only smwg* related settings - * - * @par Example: - * @code - * $settings = Settings::newFromGlobals(); - * $settings->get( 'smwgDefaultStore' ); - * @endcode - * - * @since 1.9 - * - * @return Settings - */ - public static function newFromGlobals() { - - $settings = array( - 'smwgScriptPath' => $GLOBALS['smwgScriptPath'], - 'smwgIP' => $GLOBALS['smwgIP'], - 'smwgDefaultStore' => $GLOBALS['smwgDefaultStore'], - 'smwgSparqlDatabaseConnector' => $GLOBALS['smwgSparqlDatabaseConnector'], - 'smwgSparqlDatabase' => $GLOBALS['smwgSparqlDatabase'], - 'smwgSparqlQueryEndpoint' => $GLOBALS['smwgSparqlQueryEndpoint'], - 'smwgSparqlUpdateEndpoint' => $GLOBALS['smwgSparqlUpdateEndpoint'], - 'smwgSparqlDataEndpoint' => $GLOBALS['smwgSparqlDataEndpoint'], - 'smwgSparqlDefaultGraph' => $GLOBALS['smwgSparqlDefaultGraph'], - 'smwgHistoricTypeNamespace' => $GLOBALS['smwgHistoricTypeNamespace'], - 'smwgNamespaceIndex' => $GLOBALS['smwgNamespaceIndex'], - 'smwgShowFactbox' => $GLOBALS['smwgShowFactbox'], - 'smwgShowFactboxEdit' => $GLOBALS['smwgShowFactboxEdit'], - 'smwgToolboxBrowseLink' => $GLOBALS['smwgToolboxBrowseLink'], - 'smwgInlineErrors' => $GLOBALS['smwgInlineErrors'], - 'smwgUseCategoryHierarchy' => $GLOBALS['smwgUseCategoryHierarchy'], - 'smwgCategoriesAsInstances' => $GLOBALS['smwgCategoriesAsInstances'], - 'smwgLinksInValues' => $GLOBALS['smwgLinksInValues'], - 'smwgDefaultNumRecurringEvents' => $GLOBALS['smwgDefaultNumRecurringEvents'], - 'smwgMaxNumRecurringEvents' => $GLOBALS['smwgMaxNumRecurringEvents'], - 'smwgBrowseShowInverse' => $GLOBALS['smwgBrowseShowInverse'], - 'smwgBrowseShowAll' => $GLOBALS['smwgBrowseShowAll'], - 'smwgSearchByPropertyFuzzy' => $GLOBALS['smwgSearchByPropertyFuzzy'], - 'smwgTypePagingLimit' => $GLOBALS['smwgTypePagingLimit'], - 'smwgConceptPagingLimit' => $GLOBALS['smwgConceptPagingLimit'], - 'smwgPropertyPagingLimit' => $GLOBALS['smwgPropertyPagingLimit'], - 'smwgQEnabled' => $GLOBALS['smwgQEnabled'], - 'smwgQMaxLimit' => $GLOBALS['smwgQMaxLimit'], - 'smwgIgnoreQueryErrors' => $GLOBALS['smwgIgnoreQueryErrors'], - 'smwgQSubcategoryDepth' => $GLOBALS['smwgQSubcategoryDepth'], - 'smwgQEqualitySupport' => $GLOBALS['smwgQEqualitySupport'], - 'smwgQSortingSupport' => $GLOBALS['smwgQSortingSupport'], - 'smwgQRandSortingSupport' => $GLOBALS['smwgQRandSortingSupport'], - 'smwgQDefaultNamespaces' => $GLOBALS['smwgQDefaultNamespaces'], - 'smwgQComparators' => $GLOBALS['smwgQComparators'], - 'smwStrictComparators' => $GLOBALS['smwStrictComparators'], - 'smwgQMaxSize' => $GLOBALS['smwgQMaxSize'], - 'smwgQMaxDepth' => $GLOBALS['smwgQMaxDepth'], - 'smwgQFeatures' => $GLOBALS['smwgQFeatures'], - 'smwgQDefaultLimit' => $GLOBALS['smwgQDefaultLimit'], - 'smwgQMaxInlineLimit' => $GLOBALS['smwgQMaxInlineLimit'], - 'smwgQPrintoutLimit' => $GLOBALS['smwgQPrintoutLimit'], - 'smwgQDefaultLinking' => $GLOBALS['smwgQDefaultLinking'], - 'smwgQConceptCaching' => $GLOBALS['smwgQConceptCaching'], - 'smwgQConceptMaxSize' => $GLOBALS['smwgQConceptMaxSize'], - 'smwgQConceptMaxDepth' => $GLOBALS['smwgQConceptMaxDepth'], - 'smwgQConceptFeatures' => $GLOBALS['smwgQConceptFeatures'], - 'smwgQConceptCacheLifetime' => $GLOBALS['smwgQConceptCacheLifetime'], - 'smwgResultFormats' => $GLOBALS['smwgResultFormats'], - 'smwgResultAliases' => $GLOBALS['smwgResultAliases'], - 'smwgQuerySources' => $GLOBALS['smwgQuerySources'], - 'smwgPDefaultType' => $GLOBALS['smwgPDefaultType'], - 'smwgAllowRecursiveExport' => $GLOBALS['smwgAllowRecursiveExport'], - 'smwgExportBacklinks' => $GLOBALS['smwgExportBacklinks'], - 'smwgMaxNonExpNumber' => $GLOBALS['smwgMaxNonExpNumber'], - 'smwgEnableUpdateJobs' => $GLOBALS['smwgEnableUpdateJobs'], - 'smwgNamespacesWithSemanticLinks' => $GLOBALS['smwgNamespacesWithSemanticLinks'], - 'smwgPageSpecialProperties' => $GLOBALS['smwgPageSpecialProperties'], - 'smwgDeclarationProperties' => $GLOBALS['smwgDeclarationProperties'], - 'smwgTranslate' => $GLOBALS['smwgTranslate'], - 'smwgAdminRefreshStore' => $GLOBALS['smwgAdminRefreshStore'], - 'smwgAutocompleteInSpecialAsk' => $GLOBALS['smwgAutocompleteInSpecialAsk'], - 'smwgAutoRefreshSubject' => $GLOBALS['smwgAutoRefreshSubject'], - 'smwgAutoRefreshOnPurge' => $GLOBALS['smwgAutoRefreshOnPurge'], - 'smwgAutoRefreshOnPageMove' => $GLOBALS['smwgAutoRefreshOnPageMove'], - 'smwgContLang' => $GLOBALS['smwgContLang'], - 'smwgMaxPropertyValues' => $GLOBALS['smwgMaxPropertyValues'], - 'smwgQSubpropertyDepth' => $GLOBALS['smwgQSubpropertyDepth'], - 'smwgNamespace' => $GLOBALS['smwgNamespace'], - 'smwgMasterStore' => $GLOBALS['smwgMasterStore'], - 'smwgIQRunningNumber' => $GLOBALS['smwgIQRunningNumber'], - 'smwgCacheType' => $GLOBALS['smwgCacheType'], - 'smwgCacheUsage' => $GLOBALS['smwgCacheUsage'], - 'smwgFixedProperties' => $GLOBALS['smwgFixedProperties'], - 'smwgPropertyLowUsageThreshold' => $GLOBALS['smwgPropertyLowUsageThreshold'], - 'smwgPropertyZeroCountDisplay' => $GLOBALS['smwgPropertyZeroCountDisplay'], - 'smwgShowHiddenCategories' => $GLOBALS['smwgShowHiddenCategories'], - 'smwgFactboxUseCache' => $GLOBALS['smwgFactboxUseCache'], - 'smwgFactboxCacheRefreshOnPurge' => $GLOBALS['smwgFactboxCacheRefreshOnPurge'], - 'smwgQueryProfiler' => $GLOBALS['smwgQueryProfiler'], - 'smwgEnabledSpecialPage' => $GLOBALS['smwgEnabledSpecialPage'], - 'smwgOnDeleteAction' => $GLOBALS['smwgOnDeleteAction'] - ); - - $settings = $settings + array( - 'smwgCanonicalNames' => NamespaceManager::getCanonicalNames() - ); - - if ( self::$instance === null ) { - self::$instance = self::newFromArray( $settings ) ; - } - - return self::$instance; - } - - /** - * Factory method for immediate instantiation of a settings object for a - * given array - * - * @par Example: - * @code - * $settings = Settings::newFromArray( array( 'Foo' => 'Bar' ) ); - * $settings->get( 'Foo' ); - * @endcode - * - * @since 1.9 - * - * @return Settings - */ - public static function newFromArray( array $settings ) { - return new self( $settings ); - } - - /** - * Returns settings for a given key (nested settings are supported) - * - * @par Example: - * @code - * $settings = Settings::newFromArray( array( - * 'Foo' => 'Bar' - * 'Parent' => array( - * 'Child' => array( 'Lisa', 'Lula', array( 'Lila' ) ) - * ) - * ); - * - * $settings->get( 'Child' ) will return array( 'Lisa', 'Lula', array( 'Lila' ) ) - * @endcode - * - * @since 1.9 - * - * @param string $key - * - * @return mixed - * @throws InvalidSettingsArgumentException - */ - public function get( $key ) { - - if ( !$this->has( $key ) ) { - - // If the key wasn't found it could be because of a nested array - // therefore iterate and verify otherwise throw an exception - $value = $this->doIterate( $key ); - if ( $value !== null ) { - return $value; - } - - throw new InvalidSettingsArgumentException( "'{$key}' is not a valid settings key" ); - } - - return $this->lookup( $key ); - } - - /** - * Resets the instance - * - * @since 1.9 - */ - public static function clear() { - self::$instance = null; - } - - /** - * Iterates over a nested array to find a element - * - * @since 1.9 - * - * @param string $key - * - * @return mixed|null - */ - private function doIterate( $key ) { - - $iterator = new \RecursiveIteratorIterator( - new \RecursiveArrayIterator( $this->toArray() ), - \RecursiveIteratorIterator::CHILD_FIRST - ); - - foreach( $iterator as $it => $value ) { - if ( $key === $it ) { - return $value; - } - } - - return null; - } -} diff --git a/SemanticMediaWiki/includes/Setup.php b/SemanticMediaWiki/includes/Setup.php deleted file mode 100644 index c32f81ae..00000000 --- a/SemanticMediaWiki/includes/Setup.php +++ /dev/null @@ -1,637 +0,0 @@ -<?php - -namespace SMW; - -use SMW\MediaWiki\Hooks\LinksUpdateConstructed; -use SMW\MediaWiki\Hooks\ArticlePurge; -use SMW\MediaWiki\Hooks\TitleMoveComplete; -use SMW\MediaWiki\Hooks\BaseTemplateToolbox; -use SMW\MediaWiki\Hooks\ArticleDelete; -use SMW\MediaWiki\Hooks\SpecialStatsAddExtra; -use SMW\MediaWiki\Hooks\InternalParseBeforeLinks; -use SMW\MediaWiki\Hooks\SkinAfterContent; -use SMW\MediaWiki\Hooks\OutputPageParserOutput; -use SMW\MediaWiki\Hooks\BeforePageDisplay; -use SMW\MediaWiki\Hooks\FileUpload; -use SMW\MediaWiki\Hooks\NewRevisionFromEditComplete; -use SMW\MediaWiki\Hooks\ParserAfterTidy; -use SMW\MediaWiki\Hooks\ResourceLoaderGetConfigVars; -use SMW\MediaWiki\Hooks\GetPreferences; -use SMW\MediaWiki\Hooks\SkinTemplateNavigation; -use SMW\MediaWiki\Hooks\ExtensionSchemaUpdates; -use SMW\MediaWiki\Hooks\ResourceLoaderTestModules; -use SMW\MediaWiki\Hooks\ExtensionTypes; -use SMW\MediaWiki\Hooks\TitleIsAlwaysKnown; -use SMW\MediaWiki\Hooks\BeforeDisplayNoArticleText; -use SMW\MediaWiki\Hooks\ArticleFromTitle; - -/** - * Extension setup and registration - * - * Register all hooks, set up extension credits etc. - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -final class Setup implements ContextAware { - - /** @var array */ - protected $globals; - - /** @var string */ - protected $directory; - - /** @var Settings */ - protected $settings; - - /** @var ContextResource */ - protected $context = null; - - /** - * @since 1.9 - * - * @param array &$globals - * @param string $directory - * @param ContextResource|null $context - */ - public function __construct( &$globals, $directory, ContextResource $context = null ) { - $this->globals =& $globals; - $this->directory = $directory; - $this->context = $context; - } - - /** - * @since 1.9 - */ - public function run() { - Profiler::In(); - - $this->init(); - $this->loadSettings(); - - $this->registerI18n(); - $this->registerWebApi(); - $this->registerJobClasses(); - $this->registerSpecialPages(); - $this->registerPermissions(); - - $this->registerParamDefinitions(); - $this->registerFooterIcon(); - $this->registerFunctionHooks(); - $this->registerParserHooks(); - - Profiler::Out(); - } - - /** - * Init some globals that are not part of the configuration settings - * - * @since 1.9 - */ - protected function init() { - - $this->globals['smwgMasterStore'] = null; - $this->globals['smwgIQRunningNumber'] = 0; - - if ( !isset( $this->globals['smwgNamespace'] ) ) { - $this->globals['smwgNamespace'] = parse_url( $this->globals['wgServer'], PHP_URL_HOST ); - } - - if ( !isset( $this->globals['smwgScriptPath'] ) ) { - $this->globals['smwgScriptPath'] = ( $this->globals['wgExtensionAssetsPath'] === false ? $this->globals['wgScriptPath'] . '/extensions' : $this->globals['wgExtensionAssetsPath'] ) . '/SemanticMediaWiki'; - } - - if ( is_file( $this->directory . "/resources/Resources.php" ) ) { - $this->globals['wgResourceModules'] = array_merge( $this->globals['wgResourceModules'], include( $this->directory . "/resources/Resources.php" ) ); - } - - } - - /** - * @see ContextAware::withContext - * - * @since 1.9 - * - * @return ContextResource - */ - public function withContext() { - return $this->context; - } - - /** - * Load Semantic MediaWiki specific settings - * - * @since 1.9 - */ - protected function loadSettings() { - $this->settings = $this->registerSettings( Settings::newFromGlobals( $this->globals ) ); - } - - /** - * @since 1.9 - */ - protected function registerSettings( Settings $settings ) { - $this->withContext()->getDependencyBuilder()->getContainer()->registerObject( 'Settings', $settings ); - Application::getInstance()->registerObject( 'Settings', $settings ); - return $settings; - } - - /** - * @see https://www.mediawiki.org/wiki/Manual:$wgExtensionMessagesFiles - * - * @since 1.9 - */ - protected function registerI18n() { - - $smwgIP = $this->settings->get( 'smwgIP' ); - - $this->globals['wgMessagesDirs']['SemanticMediaWiki'] = $smwgIP . 'i18n'; - $this->globals['wgExtensionMessagesFiles']['SemanticMediaWiki'] = $smwgIP . 'languages/SMW_Messages.php'; - $this->globals['wgExtensionMessagesFiles']['SemanticMediaWikiAlias'] = $smwgIP . 'languages/SMW_Aliases.php'; - $this->globals['wgExtensionMessagesFiles']['SemanticMediaWikiMagic'] = $smwgIP . 'languages/SMW_Magic.php'; - $this->globals['wgExtensionMessagesFiles']['SemanticMediaWikiNamespaces'] = $smwgIP . 'languages/SemanticMediaWiki.namespaces.php'; - - } - - /** - * @see https://www.mediawiki.org/wiki/Manual:$wgAPIModules - * - * @since 1.9 - */ - protected function registerWebApi() { - - $this->globals['wgAPIModules']['smwinfo'] = '\SMW\MediaWiki\Api\Info'; - $this->globals['wgAPIModules']['ask'] = '\SMW\MediaWiki\Api\Ask'; - $this->globals['wgAPIModules']['askargs'] = '\SMW\MediaWiki\Api\AskArgs'; - $this->globals['wgAPIModules']['browsebysubject'] = '\SMW\MediaWiki\Api\BrowseBySubject'; - - } - - /** - * @see https://www.mediawiki.org/wiki/Manual:$wgJobClasses - * - * @since 1.9 - */ - protected function registerJobClasses() { - - $this->globals['wgJobClasses']['SMW\UpdateJob'] = 'SMW\MediaWiki\Jobs\UpdateJob'; - $this->globals['wgJobClasses']['SMW\RefreshJob'] = 'SMW\MediaWiki\Jobs\RefreshJob'; - $this->globals['wgJobClasses']['SMW\UpdateDispatcherJob'] = 'SMW\MediaWiki\Jobs\UpdateDispatcherJob'; - $this->globals['wgJobClasses']['SMW\DeleteSubjectJob'] = 'SMW\MediaWiki\Jobs\DeleteSubjectJob'; - - // Legacy definition to be removed with 1.10 - $this->globals['wgJobClasses']['SMWUpdateJob'] = 'SMW\MediaWiki\Jobs\UpdateJob'; - $this->globals['wgJobClasses']['SMWRefreshJob'] = 'SMW\MediaWiki\Jobs\RefreshJob'; - - } - - /** - * @see https://www.mediawiki.org/wiki/Manual:$wgAvailableRights - * @see https://www.mediawiki.org/wiki/Manual:$wgGroupPermissions - * - * @since 1.9 - */ - protected function registerPermissions() { - - // Rights - $this->globals['wgAvailableRights'][] = 'smw-admin'; - - // User group rights - $this->globals['wgGroupPermissions']['sysop']['smw-admin'] = true; - $this->globals['wgGroupPermissions']['smwadministrator']['smw-admin'] = true; - - } - - /** - * @see https://www.mediawiki.org/wiki/Manual:$wgSpecialPages - * - * @since 1.9 - */ - protected function registerSpecialPages() { - - $specials = array( - 'Ask' => array( - 'page' => 'SMWAskPage', - 'group' => 'smw_group' - ), - 'Browse' => array( - 'page' => 'SMWSpecialBrowse', - 'group' => 'smw_group' - ), - 'PageProperty' => array( - 'page' => 'SMWPageProperty', - 'group' => 'smw_group' - ), - 'SearchByProperty' => array( - 'page' => 'SMWSearchByProperty', - 'group' => 'smw_group' - ), - 'SMWAdmin' => array( - 'page' => 'SMWAdmin', - 'group' => 'smw_group' - ), - 'SemanticStatistics' => array( - 'page' => 'SMW\SpecialSemanticStatistics', - 'group' => 'wiki' - ), - 'Concepts' => array( - 'page' => 'SMW\SpecialConcepts', - 'group' => 'pages' - ), - 'ExportRDF' => array( - 'page' => 'SMWSpecialOWLExport', - 'group' => 'smw_group' - ), - 'Types' => array( - 'page' => 'SMWSpecialTypes', - 'group' => 'pages' - ), - 'URIResolver' => array( - 'page' => 'SMWURIResolver' - ), - 'Properties' => array( - 'page' => 'SMW\SpecialProperties', - 'group' => 'pages' - ), - 'UnusedProperties' => array( - 'page' => 'SMW\SpecialUnusedProperties', - 'group' => 'maintenance' - ), - 'WantedProperties' => array( - 'page' => 'SMW\SpecialWantedProperties', - 'group' => 'maintenance' - ), - ); - - // Register data - foreach ( $specials as $special => $page ) { - $this->globals['wgSpecialPages'][$special] = $page['page']; - - if ( isset( $page['group'] ) ) { - $this->globals['wgSpecialPageGroups'][$special] = $page['group']; - } - } - - } - - /** - * @since 1.9 - */ - protected function registerParamDefinitions() { - $this->globals['wgParamDefinitions']['smwformat'] = array( - 'definition'=> 'SMWParamFormat', - ); - } - - /** - * @see https://www.mediawiki.org/wiki/Manual:$wgFooterIcons - * - * @since 1.9 - */ - protected function registerFooterIcon() { - $this->globals['wgFooterIcons']['poweredby']['semanticmediawiki'] = array( - 'src' => $this->globals['wgScriptPath'] . '/extensions/' - . end( ( explode( '/extensions/', str_replace( DIRECTORY_SEPARATOR, '/', __DIR__), 2 ) ) ) - . '/../resources/images/smw_button.png', - 'url' => 'https://www.semantic-mediawiki.org/wiki/Semantic_MediaWiki', - 'alt' => 'Powered by Semantic MediaWiki', - ); - } - - /** - * @see https://www.mediawiki.org/wiki/Manual:$this->globals['wgHooks'] - * - * @note $this->globals['wgHooks'] contains a list of hooks which specifies for every event an - * array of functions to be called. - * - * @since 1.9 - */ - protected function registerFunctionHooks() { - - $settings = $this->settings; - $globals = $this->globals; - $basePath = $this->directory; - $installPath = $this->globals['IP']; - - /** - * Hook: Called by BaseTemplate when building the toolbox array and - * returning it for the skin to output. - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/BaseTemplateToolbox - * - * @since 1.9 - */ - $this->globals['wgHooks']['BaseTemplateToolbox'][] = function ( $skinTemplate, &$toolbox ) { - $baseTemplateToolbox = new BaseTemplateToolbox( $skinTemplate, $toolbox ); - return $baseTemplateToolbox->process(); - }; - - /** - * Hook: Allows extensions to add text after the page content and article - * metadata. - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/SkinAfterContent - * - * @since 1.9 - */ - $this->globals['wgHooks']['SkinAfterContent'][] = function ( &$data, $skin = null ) { - $skinAfterContent = new SkinAfterContent( $data, $skin ); - return $skinAfterContent->process(); - }; - - /** - * Hook: Called after parse, before the HTML is added to the output - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/OutputPageParserOutput - * - * @since 1.9 - */ - $this->globals['wgHooks']['OutputPageParserOutput'][] = function ( &$outputPage, $parserOutput ) { - $outputPageParserOutput = new OutputPageParserOutput( $outputPage, $parserOutput ); - return $outputPageParserOutput->process(); - }; - - /** - * Hook: Add changes to the output page, e.g. adding of CSS or JavaScript - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay - * - * @since 1.9 - */ - $this->globals['wgHooks']['BeforePageDisplay'][] = function ( &$outputPage, &$skin ) { - $beforePageDisplay = new BeforePageDisplay( $outputPage, $skin ); - return $beforePageDisplay->process(); - }; - - /** - * Hook: InternalParseBeforeLinks is used to process the expanded wiki - * code after <nowiki>, HTML-comments, and templates have been treated. - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/InternalParseBeforeLinks - * - * @since 1.9 - */ - $this->globals['wgHooks']['InternalParseBeforeLinks'][] = function ( &$parser, &$text ) { - $internalParseBeforeLinks = new InternalParseBeforeLinks( $parser, $text ); - return $internalParseBeforeLinks->process(); - }; - - /** - * Hook: NewRevisionFromEditComplete called when a revision was inserted - * due to an edit - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/NewRevisionFromEditComplete - * - * @since 1.9 - */ - $this->globals['wgHooks']['NewRevisionFromEditComplete'][] = function ( $wikiPage, $revision, $baseId, $user ) { - $newRevisionFromEditComplete = new NewRevisionFromEditComplete( $wikiPage, $revision, $baseId, $user ); - return $newRevisionFromEditComplete->process(); - }; - - /** - * Hook: TitleMoveComplete occurs whenever a request to move an article - * is completed - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/TitleMoveComplete - * - * @since 1.9 - */ - $this->globals['wgHooks']['TitleMoveComplete'][] = function ( &$oldTitle, &$newTitle, &$user, $oldId, $newId ) { - $titleMoveComplete = new TitleMoveComplete( $oldTitle, $newTitle, $user, $oldId, $newId ); - return $titleMoveComplete->process(); - }; - - /** - * Hook: ArticlePurge executes before running "&action=purge" - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticlePurge - * - * @since 1.9 - */ - $this->globals['wgHooks']['ArticlePurge'][] = function ( &$wikiPage ) { - $articlePurge = new ArticlePurge( $wikiPage ); - return $articlePurge->process(); - }; - - /** - * Hook: ArticleDelete occurs whenever the software receives a request - * to delete an article - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleDelete - * - * @since 1.9 - */ - $this->globals['wgHooks']['ArticleDelete'][] = function ( &$wikiPage, &$user, &$reason, &$error ) { - $articleDelete = new ArticleDelete( $wikiPage, $user, $reason, $error ); - return $articleDelete->process(); - }; - - /** - * Hook: LinksUpdateConstructed called at the end of LinksUpdate() construction - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/LinksUpdateConstructed - * - * @since 1.9 - */ - $this->globals['wgHooks']['LinksUpdateConstructed'][] = function ( $linksUpdate ) { - $linksUpdateConstructed = new LinksUpdateConstructed( $linksUpdate ); - return $linksUpdateConstructed->process(); - }; - - /** - * Hook: ParserAfterTidy to add some final processing to the fully-rendered page output - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ParserAfterTidy - * - * @since 1.9 - */ - $this->globals['wgHooks']['ParserAfterTidy'][] = function ( &$parser, &$text ) { - $parserAfterTidy = new ParserAfterTidy( $parser, $text ); - return $parserAfterTidy->process(); - }; - - /** - * Hook: Add extra statistic at the end of Special:Statistics - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/SpecialStatsAddExtra - * - * @since 1.9 - */ - $this->globals['wgHooks']['SpecialStatsAddExtra'][] = function ( &$extraStats ) use ( $globals ) { - $specialStatsAddExtra = new SpecialStatsAddExtra( $extraStats, $globals['wgVersion'], $globals['wgLang'] ); - return $specialStatsAddExtra->process(); - }; - - /** - * Hook: For extensions adding their own namespaces or altering the defaults - * - * @Bug 34383 - * @see https://www.mediawiki.org/wiki/Manual:Hooks/CanonicalNamespaces - * - * @since 1.9 - */ - $this->globals['wgHooks']['CanonicalNamespaces'][] = function ( &$list ) { - $list = $list + NamespaceManager::getCanonicalNames(); - return true; - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/FileUpload - * - * @since 1.9.1 - */ - $this->globals['wgHooks']['FileUpload'][] = function ( $file, $reupload ) { - $fileUpload = new FileUpload( $file, $reupload ); - return $fileUpload->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderGetConfigVars - */ - $this->globals['wgHooks']['ResourceLoaderGetConfigVars'][] = function ( &$vars ) { - $resourceLoaderGetConfigVars = new ResourceLoaderGetConfigVars( $vars ); - return $resourceLoaderGetConfigVars->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/GetPreferences - */ - $this->globals['wgHooks']['GetPreferences'][] = function ( $user, &$preferences ) { - $getPreferences = new GetPreferences( $user, $preferences ); - return $getPreferences->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/SkinTemplateNavigation - */ - $this->globals['wgHooks']['SkinTemplateNavigation'][] = function ( &$skinTemplate, &$links ) { - $skinTemplateNavigation = new SkinTemplateNavigation( $skinTemplate, $links ); - return $skinTemplateNavigation->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/LoadExtensionSchemaUpdates - */ - $this->globals['wgHooks']['LoadExtensionSchemaUpdates'][] = function ( $databaseUpdater ) { - $extensionSchemaUpdates = new ExtensionSchemaUpdates( $databaseUpdater ); - return $extensionSchemaUpdates->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderTestModules - */ - $this->globals['wgHooks']['ResourceLoaderTestModules'][] = function ( &$testModules, &$resourceLoader ) use ( $basePath, $installPath ) { - - $resourceLoaderTestModules = new ResourceLoaderTestModules( - $resourceLoader, - $testModules, - $basePath, - $installPath - ); - - return $resourceLoaderTestModules->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ExtensionTypes - */ - $this->globals['wgHooks']['ExtensionTypes'][] = function ( &$extTypes ) { - $extensionTypes = new ExtensionTypes( $extTypes ); - return $extensionTypes->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/TitleIsAlwaysKnown - */ - $this->globals['wgHooks']['TitleIsAlwaysKnown'][] = function ( $title, &$result ) { - $titleIsAlwaysKnown = new TitleIsAlwaysKnown( $title, $result ); - return $titleIsAlwaysKnown->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforeDisplayNoArticleText - */ - $this->globals['wgHooks']['BeforeDisplayNoArticleText'][] = function ( $article ) { - $beforeDisplayNoArticleText = new BeforeDisplayNoArticleText( $article ); - return $beforeDisplayNoArticleText->process(); - }; - - /** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleFromTitle - */ - $this->globals['wgHooks']['ArticleFromTitle'][] = function ( &$title, &$article ) { - $articleFromTitle = new ArticleFromTitle( $title, $article ); - return $articleFromTitle->process(); - }; - - // Old-style registration - - $this->globals['wgHooks']['AdminLinks'][] = 'SMWHooks::addToAdminLinks'; - $this->globals['wgHooks']['PageSchemasRegisterHandlers'][] = 'SMWHooks::onPageSchemasRegistration'; - } - - /** - * @since 1.9 - */ - protected function registerParserHooks() { - - $settings = $this->settings; - $builder = $this->withContext()->getDependencyBuilder(); - - /** - * Called when the parser initialises for the first time - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ParserFirstCallInit - * - * @since 1.9 - */ - $this->globals['wgHooks']['ParserFirstCallInit'][] = function ( \Parser &$parser ) use ( $builder, $settings ) { - - /** - * {{#ask}} - * - * @since 1.9 - */ - $parser->setFunctionHook( 'ask', function( $parser ) use ( $builder, $settings ) { - $ask = $builder->newObject( 'AskParserFunction', array( 'Parser' => $parser ) ); - return $settings->get( 'smwgQEnabled' ) ? $ask->parse( func_get_args() ) : $ask->isQueryDisabled(); - } ); - - /** - * {{#show}} - * - * @since 1.9 - */ - $parser->setFunctionHook( 'show', function( $parser ) use ( $builder, $settings ) { - $show = $builder->newObject( 'ShowParserFunction', array( 'Parser' => $parser ) ); - return $settings->get( 'smwgQEnabled' ) ? $show->parse( func_get_args() ) : $show->isQueryDisabled(); - } ); - - /** - * {{#subobject}} - * - * @since 1.9 - */ - $parser->setFunctionHook( 'subobject', function( $parser ) use ( $builder ) { - $instance = $builder->newObject( 'SubobjectParserFunction', array( 'Parser' => $parser ) ); - return $instance->parse( ParameterFormatterFactory::newFromArray( func_get_args() ) ); - } ); - - $parser->setFunctionHook( 'concept', array( 'SMW\ConceptParserFunction', 'render' ) ); - $parser->setFunctionHook( 'set', array( 'SMW\SetParserFunction', 'render' ) ); - $parser->setFunctionHook( 'set_recurring_event', array( 'SMW\RecurringEventsParserFunction', 'render' ) ); - $parser->setFunctionHook( 'declare', array( 'SMW\DeclareParserFunction', 'render' ), SFH_OBJECT_ARGS ); - - return true; - }; - - $this->globals['wgHooks']['ParserFirstCallInit'][] = 'SMW\DocumentationParserFunction::staticInit'; - $this->globals['wgHooks']['ParserFirstCallInit'][] = 'SMW\InfoParserFunction::staticInit'; - - } - -} diff --git a/SemanticMediaWiki/includes/SimpleDictionary.php b/SemanticMediaWiki/includes/SimpleDictionary.php deleted file mode 100644 index 5caadafa..00000000 --- a/SemanticMediaWiki/includes/SimpleDictionary.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -namespace SMW; - -use InvalidArgumentException; -use OutOfBoundsException; - -/** - * Class handling the implementation of a simple dictionary - * - * Implementing a dictionary (associative array, hash array) which is a - * collection of key, value pairs. - * - * @par Example: - * @code - * $dictionary = new SimpleDictionary( array( 'Foo' => 'Bar' ) ); - * - * $dictionary->has( 'Foo' ) returns true - * $dictionary->get( 'Foo' ) returns 'Bar' - * $dictionary->set( 'Foo', array( 'Lula', 'Bar') ) - * $dictionary->remove( 'Foo' ) - * @endcode - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SimpleDictionary extends ObjectStorage implements ObjectDictionary { - - /** - * Returns whether a specific element is accessible - * - * @since 1.9 - * - * @param mixed $key - * - * @return boolean - * @throws InvalidArgumentException - */ - public function has( $key ) { - - if ( !( (string)$key === $key ) ) { - throw new InvalidArgumentException( 'The invoked key is not a string' ); - } - - return $this->contains( $key ); - } - - /** - * Adds a new element (key, value pair) to an existing collection - * - * @since 1.9 - * - * @param string $key - * @param mixed $value - * - * @return SimpleDictionary - * @throws InvalidArgumentException - */ - public function set( $key, $value ) { - - if ( !( (string)$key === $key ) ) { - throw new InvalidArgumentException( 'The invoked key is not a string' ); - } - - $this->attach( $key, $value ); - return $this; - } - - /** - * Returns a container value - * - * @since 1.9 - * - * @param string $key - * - * @return mixed - * @throws OutOfBoundsException - */ - public function get( $key ) { - - if ( !( $this->has( $key ) ) ) { - throw new OutOfBoundsException( "'{$key}' is unknown" ); - } - - return $this->lookup( $key ); - } - - /** - * Removes an element from a collection - * - * @since 1.9 - * - * @param string $key - * - * @return SimpleDictionary - * @throws InvalidArgumentException - */ - public function remove( $key ) { - - if ( !( (string)$key === $key ) ) { - throw new InvalidArgumentException( 'The invoked key is not a string' ); - } - - $this->detach( $key ); - return $this; - } - - /** - * Returns invoked array without conversion - * - * @since 1.9 - * - * @return array - */ - public function toArray() { - return $this->storage; - } - - /** - * Merges elements of one or more arrays together - * - * @since 1.9 - * - * @param array $mergeable - * - * @return SimpleDictionary - */ - public function merge( array $mergeable ) { - $this->storage = array_merge( $this->storage, $mergeable ); - return $this; - } - -} diff --git a/SemanticMediaWiki/includes/StoreUpdater.php b/SemanticMediaWiki/includes/StoreUpdater.php deleted file mode 100644 index 4eefe7cc..00000000 --- a/SemanticMediaWiki/includes/StoreUpdater.php +++ /dev/null @@ -1,170 +0,0 @@ -<?php - -namespace SMW; - -use WikiPage; -use Title; -use User; - -/** - * Initiates an update of the Store - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class StoreUpdater { - - /** - * @var SemanticData - */ - private $semanticData; - - /** - * @var boolean|null - */ - private $updateJobsEnabledState = null; - - /** - * @var boolean|null - */ - private $processSemantics = null; - - /** - * @since 1.9 - * - * @param SemanticData $semanticData - */ - public function __construct( SemanticData $semanticData ) { - $this->semanticData = $semanticData; - } - - /** - * @since 1.9 - * - * @return DIWikiPage - */ - public function getSubject() { - return $this->semanticData->getSubject(); - } - - /** - * @since 1.9 - * - * @param boolean $status - */ - public function setUpdateJobsEnabledState( $status ) { - $this->updateJobsEnabledState = (bool)$status; - return $this; - } - - /** - * This function takes care of storing the collected semantic data and - * clearing out any outdated entries for the processed page. It assumes - * that parsing has happened and that all relevant information are - * contained and provided for. - * - * Optionally, this function also takes care of triggering indirect updates - * that might be needed for an overall database consistency. If the saved page - * describes a property or data type, the method checks whether the property - * type, the data type, the allowed values, or the conversion factors have - * changed. If so, it triggers UpdateDispatcherJob for the relevant articles, - * which then asynchronously undergoes an update. - * - * @since 1.9 - * - * @return boolean - */ - public function doUpdate() { - return $this->canPerformUpdate() ? $this->performUpdate() : false; - } - - private function canPerformUpdate() { - - $title = $this->getSubject()->getTitle(); - - // Protect against null and namespace -1 see Bug 50153 - if ( $title === null || $title->isSpecialPage() ) { - return false; - } - - return true; - } - - /** - * @note Make sure to have a valid revision (null means delete etc.) and - * check if semantic data should be processed and displayed for a page in - * the given namespace - */ - private function performUpdate() { - Profiler::In(); - - $this->application = Application::getInstance(); - - if ( $this->updateJobsEnabledState === null ) { - $this->setUpdateJobsEnabledState( $this->application->getSettings()->get( 'smwgEnableUpdateJobs' ) ); - } - - $title = $this->getSubject()->getTitle(); - $wikiPage = $this->application->newPageCreator()->createPage( $title ); - $revision = $wikiPage->getRevision(); - - $this->updateSemanticData( $title, $wikiPage, $revision ); - - Profiler::Out(); - return $this->doRealUpdate( $this->inspectPropertyType() ); - } - - private function updateSemanticData( Title $title, WikiPage $wikiPage, $revision ) { - - $this->processSemantics = $revision !== null && $this->isEnabledNamespace( $title ); - - if ( !$this->processSemantics ) { - return $this->semanticData = new SemanticData( $this->getSubject() ); - } - - $pageInfoProvider = $this->application - ->newPropertyAnnotatorFactory() - ->newPageInfoProvider( $wikiPage, $revision, User::newFromId( $revision->getUser() ) ); - - $propertyAnnotator = $this->application - ->newPropertyAnnotatorFactory() - ->newPredefinedPropertyAnnotator( $this->semanticData, $pageInfoProvider ); - - $propertyAnnotator->addAnnotation(); - } - - /** - * @note Comparison must happen *before* the storage update; - * even finding uses of a property fails after its type changed. - */ - private function inspectPropertyType() { - - if ( $this->updateJobsEnabledState ) { - $propertyTypeDiffFinder = new PropertyTypeDiffFinder( $this->application->getStore(), $this->semanticData ); - $propertyTypeDiffFinder->findDiff(); - } - } - - private function doRealUpdate() { - - Profiler::In(); - - if ( $this->processSemantics ) { - $this->application->getStore()->updateData( $this->semanticData ); - } else { - $this->application->getStore()->clearData( $this->semanticData->getSubject() ); - } - - Profiler::Out(); - return true; - } - - private function isEnabledNamespace( $title ) { - return NamespaceExaminer::newFromArray( $this->application->getSettings()->get( 'smwgNamespacesWithSemanticLinks' ) )->isSemanticEnabled( $title->getNamespace() ); - } - -} diff --git a/SemanticMediaWiki/includes/Subobject.php b/SemanticMediaWiki/includes/Subobject.php deleted file mode 100644 index 524d2f30..00000000 --- a/SemanticMediaWiki/includes/Subobject.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -namespace SMW; - -use SMWContainerSemanticData; -use SMWDIContainer; -use SMWDataValue; - -use Title; -use InvalidArgumentException; - -/** - * @see http://www.semantic-mediawiki.org/wiki/Help:Subobject - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class Subobject { - - /** @var Title */ - protected $title; - - /** @var SMWContainerSemanticData */ - protected $semanticData; - - /** @var array */ - protected $errors = array(); - - /** - * @since 1.9 - * - * @param Title $title - */ - public function __construct( Title $title ) { - $this->title = $title; - } - - /** - * Returns the Title object - * - * @since 1.9 - * - * @return Title - */ - public function getTitle() { - return $this->title; - } - - /** - * Returns the subobject Id - * - * @since 1.9 - * - * @return string - */ - public function getId() { - return $this->getSemanticData()->getSubject()->getSubobjectName(); - } - - /** - * Returns an generated identifier - * - * @since 1.9 - * - * @param IdGenerator $id - * - * @return string - */ - public function generateId( IdGenerator $id ) { - return $id->generateId(); - } - - /** - * Returns an array of collected errors - * - * @since 1.9 - * - * @return array - */ - public function getErrors() { - return $this->errors; - } - - /** - * Add errors that appeared during internal processing - * - * @since 1.9 - * - * @param array $error - */ - protected function addError( array $error ) { - $this->errors = array_merge( $this->errors, $error ); - } - - /** - * @since 2.0 - * - * @param string $identifier - * - * @return self - * @throws InvalidArgumentException - */ - public function setEmptySemanticDataForId( $identifier ) { - - if ( $identifier === '' ) { - throw new InvalidArgumentException( 'Expected a valid (non-empty) indentifier' ); - } - - $subWikiPage = new DIWikiPage( - $this->title->getDBkey(), - $this->title->getNamespace(), - $this->title->getInterwiki(), - $identifier - ); - - $this->semanticData = new SMWContainerSemanticData( $subWikiPage ); - - return $this; - } - - /** - * @deprecated since 2.0 - */ - public function setSemanticData( $identifier ) { - $this->setEmptySemanticDataForId( $identifier ); - } - - /** - * Returns semantic data container for a subobject - * - * @since 1.9 - * - * @return SMWContainerSemanticData - */ - public function getSemanticData() { - - if ( !( $this->semanticData instanceof SMWContainerSemanticData ) ) { - throw new InvalidSemanticDataException( 'The semantic data container is not initialized' ); - } - - return $this->semanticData; - } - - /** - * Returns the property data item for the subobject - * - * @since 1.9 - * - * @return DIProperty - */ - public function getProperty() { - return new DIProperty( DIProperty::TYPE_SUBOBJECT ); - } - - /** - * Returns the container data item for the subobject - * - * @since 1.9 - * - * @return SMWDIContainer - */ - public function getContainer() { - return new SMWDIContainer( $this->getSemanticData() ); - } - - /** - * @since 1.9 - * - * @param DataValue $dataValue - * - * @throws InvalidSemanticDataException - */ - public function addDataValue( SMWDataValue $dataValue ) { - - if ( !( $this->semanticData instanceof SMWContainerSemanticData ) ) { - throw new InvalidSemanticDataException( 'The semantic data container is not initialized' ); - } - - $this->semanticData->addDataValue( $dataValue ); - $this->addError( $this->semanticData->getErrors() ); - } - -} diff --git a/SemanticMediaWiki/includes/articlepages/ConceptPage.php b/SemanticMediaWiki/includes/articlepages/ConceptPage.php deleted file mode 100644 index b20ebdbb..00000000 --- a/SemanticMediaWiki/includes/articlepages/ConceptPage.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -namespace SMW; - -use Html; -use SMWPageLister; -use SMWConceptDescription; - -/** - * Special handling for relation/attribute description pages. - * Some code based on CategoryPage.php - * - * Indicate class aliases in a way PHPStorm and Eclipse understand. - * This is purely an IDE helper file, and is not loaded by the extension. - * - * @since 1.9 - * - * @file - * @ingroup SMW - * - * @license GNU GPL v2+ - * @author: Markus Krötzsch - * @author: mwjames - */ - -/** - * Implementation of MediaWiki's Article that shows additional information on - * Concept: pages. Very similar to CategoryPage. - * @ingroup SMW - */ -class ConceptPage extends \SMWOrderedListPage { - - /** - * Initialize parameters to use a higher limit. This operation is very - * similar to showing members of categories. - */ - protected function initParameters() { - global $smwgConceptPagingLimit; - $this->limit = $smwgConceptPagingLimit; - return true; - } - - /** - * Returns the HTML which is added to $wgOut after the article text. - * - * @return string - */ - protected function getHtml() { - wfProfileIn( __METHOD__ . ' (SMW)' ); - - if ( $this->limit > 0 ) { // limit==0: configuration setting to disable this completely - $store = \SMW\StoreFactory::getStore(); - $concept = $store->getConceptCacheStatus( $this->getDataItem() ); - $description = new SMWConceptDescription( $this->getDataItem() ); - $query = SMWPageLister::getQuery( $description, $this->limit, $this->from, $this->until ); - $queryResult = $store->getQueryResult( $query ); - - $diWikiPages = $queryResult->getResults(); - if ( $this->until !== '' ) { - $diWikiPages = array_reverse( $diWikiPages ); - } - - $errors = $queryResult->getErrors(); - } else { - $diWikiPages = array(); - $errors = array(); - } - - $pageLister = new SMWPageLister( $diWikiPages, null, $this->limit, $this->from, $this->until ); - $this->mTitle->setFragment( '#SMWResults' ); // Make navigation point to the result list. - $navigation = $pageLister->getNavigationLinks( $this->mTitle ); - - $titleText = htmlspecialchars( $this->mTitle->getText() ); - $resultNumber = min( $this->limit, count( $diWikiPages ) ); - - // Concept cache information - if ( $concept instanceof DIConcept && $concept->getCacheStatus() === 'full' ){ - $cacheInformation = Html::element( - 'span', - array( 'class' => 'smw-concept-cache-information' ), - ' ' . $this->getContext()->msg( - 'smw-concept-cache-text', - $this->getContext()->getLanguage()->formatNum( $concept->getCacheCount() ), - $this->getContext()->getLanguage()->date( $concept->getCacheDate() ) - )->text() - ); - } else { - $cacheInformation = ''; - } - - wfProfileOut( __METHOD__ . ' (SMW)' ); - - return Html::element( 'br', array( 'id' => 'smwfootbr' ) ) . - Html::element( 'a', array( 'name' => 'SMWResults' ) , null ) . - Html::rawElement( 'div', array( 'id' => 'mw-pages'), - Html::rawElement( 'h2', array(), $this->getContext()->msg( 'smw_concept_header', $titleText )->text() ) . - Html::element( 'span', array(), $this->getContext()->msg( 'smw_conceptarticlecount', $resultNumber )->parse() ) . - smwfEncodeMessages( $errors ) . ' '. $navigation . - $cacheInformation . - $pageLister->formatList() - ); - } -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/articlepages/SMW_OrderedListPage.php b/SemanticMediaWiki/includes/articlepages/SMW_OrderedListPage.php deleted file mode 100644 index 9e6e49ec..00000000 --- a/SemanticMediaWiki/includes/articlepages/SMW_OrderedListPage.php +++ /dev/null @@ -1,121 +0,0 @@ -<?php - -/** - * Abstract subclass of MediaWiki's Article that handles the common tasks of - * article pages for Concept and Property pages. This is mainly parameter - * handling and some very basic output control. - * - * @file SMW_OrderedListPage.php - * @ingroup SMW - * - * @author Nikolas Iwan - * @author Markus Krötzsch - * @author Jeroen De Dauw - */ -abstract class SMWOrderedListPage extends Article { - - /** - * Limit for results per page. - * - * @var integer - */ - protected $limit; - - /** - * Start string: print $limit results from here. - * - * @var string - */ - protected $from; - - /** - * End string: print $limit results strictly before this article. - * - * @var string - */ - protected $until; - - /** - * Cache for the current skin, obtained from $wgUser. - * - * @var Skin - */ - protected $skin; - - /** - * Property that the displayed values are for, if any. - * - * @since 1.6 - * - * @var SMWDIProperty - */ - protected $mProperty = null; - - /** - * Overwrite view() from Article.php to add additional HTML to the - * output. - */ - public function view() { - global $wgRequest, $wgUser; - - parent::view(); - - // Copied from CategoryPage - $diff = $wgRequest->getVal( 'diff' ); - $diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) ); - if ( !isset( $diff ) || !$diffOnly ) { - $this->showList(); - } - } - - /** - * Main method for adding all additional HTML to the output stream. - */ - protected function showList() { - global $wgOut, $wgRequest; - - wfProfileIn( __METHOD__ . ' (SMW)' ); - - $this->from = $wgRequest->getVal( 'from', '' ); - $this->until = $wgRequest->getVal( 'until', '' ); - - if ( $this->initParameters() ) { - $wgOut->addHTML( $this->getHtml() ); - SMWOutputs::commitToOutputPage( $wgOut ); - } - - wfProfileOut( __METHOD__ . ' (SMW)' ); - } - - /** - * Initialise some parameters that might be changed by subclasses - * (e.g. $limit). Method can be overwritten in this case. - * If the method returns false, nothing will be printed besides - * the original article. - * - * @return true - */ - protected function initParameters() { - $this->limit = 20; - return true; - } - - /** - * Returns the HTML which is added to $wgOut after the article text. - * - * @return string - */ - protected abstract function getHtml(); - - /** - * Like Article's getTitle(), but returning a suitable SMWDIWikiPage. - * - * @since 1.6 - * - * @return SMWDIWikiPage - */ - protected function getDataItem() { - return SMWDIWikiPage::newFromTitle( $this->getTitle() ); - } - -} diff --git a/SemanticMediaWiki/includes/articlepages/SMW_PropertyPage.php b/SemanticMediaWiki/includes/articlepages/SMW_PropertyPage.php deleted file mode 100644 index 0c5d7923..00000000 --- a/SemanticMediaWiki/includes/articlepages/SMW_PropertyPage.php +++ /dev/null @@ -1,223 +0,0 @@ -<?php - -/** - * Implementation of MediaWiki's Article that shows additional information on - * property pages. Very similar to CategoryPage, but with different printout - * that also displays values for each subject with the given property. - * - * @file SMW_PropertyPage.php - * @ingroup SMW - * - * @author Markus Krötzsch - */ -class SMWPropertyPage extends SMWOrderedListPage { - - /** - * @see SMWOrderedListPage::initParameters() - * @note We use a smaller limit here; property pages might become large. - */ - protected function initParameters() { - global $smwgPropertyPagingLimit; - $this->limit = $smwgPropertyPagingLimit; - $this->mProperty = SMWDIProperty::newFromUserLabel( $this->mTitle->getText() ); - return true; - } - - /** - * Returns the HTML which is added to $wgOut after the article text. - * - * @return string - */ - protected function getHtml() { - wfProfileIn( __METHOD__ . ' (SMW)' ); - - $list = $this->getSubpropertyList() . $this->getPropertyValueList(); - $result = $this->getPredefinedPropertyIntro() . ( $list !== '' ? Html::element( 'br', array( 'id' => 'smwfootbr' ) ) . $list : '' ); - - wfProfileOut( __METHOD__ . ' (SMW)' ); - return $result; - } - - - /** - * Returns an introductory text for a predefined property - * - * @note In order to enable a more detailed description for a specific - * predefined property a concatenated message key can be used (e.g - * 'smw-pa-property-predefined' + <internal property key> => '_asksi' ) - * - * @since 1.9 - * - * @return string - */ - protected function getPredefinedPropertyIntro() { - - if ( !$this->mProperty->isUserDefined() ) { - - $propertyName = htmlspecialchars( $this->mTitle->getText() ); - $propertyKey = 'smw-pa-property-predefined' . strtolower( $this->mProperty->getKey() ); - $messageKey = wfMessage( $propertyKey )->exists() ? $propertyKey : 'smw-pa-property-predefined-default'; - - return Html::rawElement( - 'div', - array( 'class' => 'smw-pa-property-predefined-intro' ), - wfMessage( $messageKey, $propertyName )->parse() - ); - } - - return ''; - } - - /** - * Get the HTML for displaying subproperties of this property. This list - * is usually short and we implement no additional navigation. - * - * @return string - */ - protected function getSubpropertyList() { - $store = \SMW\StoreFactory::getStore(); - $options = new SMWRequestOptions(); - $options->sort = true; - $options->ascending = true; - $subproperties = $store->getPropertySubjects( new SMWDIProperty( '_SUBP' ), $this->getDataItem(), $options ); - - $result = ''; - - $resultCount = count( $subproperties ); - if ( $resultCount > 0 ) { - $titleText = htmlspecialchars( $this->mTitle->getText() ); - $result .= "<div id=\"mw-subcategories\">\n<h2>" . wfMessage( 'smw_subproperty_header', $titleText )->text() . "</h2>\n<p>"; - - if ( !$this->mProperty->isUserDefined() ) { - $result .= wfMessage( 'smw_isspecprop' )->text() . ' '; - } - - $result .= wfMessage( 'smw_subpropertyarticlecount' )->numParams( $resultCount )->text() . "</p>\n"; - - if ( $resultCount < 6 ) { - $result .= SMWPageLister::getShortList( 0, $resultCount, $subproperties, null ); - } else { - $result .= SMWPageLister::getColumnList( 0, $resultCount, $subproperties, null ); - } - - $result .= "\n</div>"; - } - - return $result; - } - - /** - * Get the HTML for displaying values of this property, based on the - * current from/until and limit settings. - * - * @return string - */ - protected function getPropertyValueList() { - if ( $this->limit > 0 ) { // limit==0: configuration setting to disable this completely - $store = \SMW\StoreFactory::getStore(); - $options = SMWPageLister::getRequestOptions( $this->limit, $this->from, $this->until ); - $diWikiPages = $store->getAllPropertySubjects( $this->mProperty, $options ); - - if ( !$options->ascending ) { - $diWikiPages = array_reverse( $diWikiPages ); - } - } else { - return ''; - } - - $result = ''; - - if ( count( $diWikiPages ) > 0 ) { - $pageLister = new SMWPageLister( $diWikiPages, null, $this->limit, $this->from, $this->until ); - $this->mTitle->setFragment( '#SMWResults' ); // Make navigation point to the result list. - $navigation = $pageLister->getNavigationLinks( $this->mTitle ); - - $titleText = htmlspecialchars( $this->mTitle->getText() ); - $resultNumber = min( $this->limit, count( $diWikiPages ) ); - - $result .= "<a name=\"SMWResults\"></a><div id=\"mw-pages\">\n" . - '<h2>' . wfMessage( 'smw_attribute_header', $titleText )->text() . "</h2>\n<p>"; - if ( !$this->mProperty->isUserDefined() ) { - $result .= wfMessage( 'smw_isspecprop' )->text() . ' '; - } - $result .= wfMessage( 'smw_attributearticlecount' )->numParams( $resultNumber )->text() . "</p>\n" . - $navigation . $this->subjectObjectList( $diWikiPages ) . $navigation . "\n</div>"; - } - - return $result; - } - - /** - * Format $diWikiPages chunked by letter in a table that shows subject - * articles in one column and object articles/values in the other one. - * - * @param $diWikiPages array - * @return string - */ - protected function subjectObjectList( array $diWikiPages ) { - global $wgContLang, $smwgMaxPropertyValues; - $store = \SMW\StoreFactory::getStore(); - - $ac = count( $diWikiPages ); - - if ( $ac > $this->limit ) { - if ( $this->until !== '' ) { - $start = 1; - } else { - $start = 0; - $ac = $ac - 1; - } - } else { - $start = 0; - } - - $r = '<table style="width: 100%; ">'; - $prev_start_char = 'None'; - - for ( $index = $start; $index < $ac; $index++ ) { - $diWikiPage = $diWikiPages[$index]; - $dvWikiPage = \SMW\DataValueFactory::getInstance()->newDataItemValue( $diWikiPage, null ); - $sortkey = \SMW\StoreFactory::getStore()->getWikiPageSortKey( $diWikiPage ); - $start_char = $wgContLang->convert( $wgContLang->firstChar( $sortkey ) ); - - // Header for index letters - if ( $start_char != $prev_start_char ) { - $r .= '<tr><th class="smwpropname"><h3>' . htmlspecialchars( $start_char ) . "</h3></th><th></th></tr>\n"; - $prev_start_char = $start_char; - } - - // Property name - $searchlink = SMWInfolink::newBrowsingLink( '+', $dvWikiPage->getShortHTMLText() ); - $r .= '<tr><td class="smwpropname">' . $dvWikiPage->getShortHTMLText( smwfGetLinker() ) . - ' ' . $searchlink->getHTML( smwfGetLinker() ) . '</td><td class="smwprops">'; - - // Property values - $ropts = new SMWRequestOptions(); - $ropts->limit = $smwgMaxPropertyValues + 1; - $values = $store->getPropertyValues( $diWikiPage, $this->mProperty, $ropts ); - $i = 0; - - foreach ( $values as $di ) { - if ( $i != 0 ) { - $r .= ', '; - } - $i++; - - if ( $i < $smwgMaxPropertyValues + 1 ) { - $dv = \SMW\DataValueFactory::getInstance()->newDataItemValue( $di, $this->mProperty ); - $r .= $dv->getShortHTMLText( smwfGetLinker() ) . $dv->getInfolinkText( SMW_OUTPUT_HTML, smwfGetLinker() ); - } else { - $searchlink = SMWInfolink::newInversePropertySearchLink( '…', $dvWikiPage->getWikiValue(), $this->mTitle->getText() ); - $r .= $searchlink->getHTML( smwfGetLinker() ); - } - } - - $r .= "</td></tr>\n"; - } - - $r .= '</table>'; - - return $r; - } - -} diff --git a/SemanticMediaWiki/includes/cache/CacheHandler.php b/SemanticMediaWiki/includes/cache/CacheHandler.php deleted file mode 100644 index 38500e71..00000000 --- a/SemanticMediaWiki/includes/cache/CacheHandler.php +++ /dev/null @@ -1,204 +0,0 @@ -<?php - -namespace SMW; - -use ObjectCache; -use BagOStuff; - -/** - * Encapsulate access to MW's BagOStuff class - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class CacheHandler { - - /** @var BagOStuff */ - protected $cache = null; - - /** @var string */ - protected $key = false; - - /** @var boolean */ - protected $cacheEnabled = false; - - /** @var CacheHandler[] */ - private static $instance = array(); - - /** - * @since 1.9 - * - * @param BagOStuff|null $cache - */ - public function __construct( BagOStuff $cache = null ) { - $this->cache = $cache; - } - - /** - * Factory method that creates a CacheHandler instance and instantiate a - * BagOStuff object from available settings ($smwgCacheType) while - * invoking additional parameters ($wgCachePrefix etc.) - * - * @par Example: - * @code - * $cache = new CacheHandler::newFromId()->setkey( new CachIdGenerator( 'Foo' ) ) - * - * $cache->set( 'CacheableObject' ) - * $cache->get() returns 'CacheableObject' - * $cache->delete() deletes 'CacheableObject' - * @endcode - * - * @note If a BagOStuff instance is not available setCacheEnabled() is - * disabled by default which prevents to run into unintended behaviour - * while trying to access BagOStuff methods. - * - * @note This method is exposed to $wgObjectCaches, $wgCachePrefix globals - * which can't and shouldn't be accessed otherwise. It is the task of this - * method alone to invoke globals and avoid leakage into the object - * life cycle. - * - * @note This method serves invoked instances from a static variable due to - * the fact that the actual working object is being accessed through - * getCache() and therefore not in direct conflict with its testability. - * - * @since 1.9 - * - * @param string $id Ids available in wgObjectCaches - * - * @return CacheHandler - */ - public static function newFromId( $id = false ) { - - $cacheType = $id ? $id : Settings::newFromGlobals()->get( 'smwgCacheType' ); - - if ( !isset( self::$instance[$cacheType] ) ) { - - if ( $cacheType && array_key_exists( $cacheType, $GLOBALS['wgObjectCaches'] ) ) { - $cache = new self( ObjectCache::getInstance( $cacheType ) ); - } else { - $cache = new self; - } - - $cache->setCacheEnabled( true ); - - self::$instance[$cacheType] = $cache; - } - - return self::$instance[$cacheType]; - } - - /** - * Returns key - * - * @since 1.9 - * - * @return string - */ - public function getKey() { - return $this->key; - } - - /** - * Sets key - * - * @since 1.9 - * - * @param IdGenerator $id - * - * @return CacheHandler - */ - public function setKey( IdGenerator $id ) { - $this->key = $id->generateId(); - return $this; - } - - /** - * Returns invoked cache instance - * - * @since 1.9 - * - * @return BagOStuff|null - */ - public function getCache() { - return $this->cache; - } - - /** - * Stores an object in cache for the invoked key - * - * @since 1.9 - * - * @param mixed $value - * @param int $exptime - * - * @return boolean - */ - public function set( $value, $exptime = 0 ) { - return $this->isEnabled() ? $this->getCache()->set( $this->getKey(), $value, $exptime ) : false; - } - - /** - * Returns object from cache for the invoked key - * - * @since 1.9 - * - * @return mixed|false - */ - public function get() { - return $this->isEnabled() ? $this->getCache()->get( $this->getKey() ) : false; - } - - /** - * Deletes object from cache for the invoked key - * - * @since 1.9 - * - * @return boolean - */ - public function delete() { - return $this->isEnabled() ? $this->getCache()->delete( $this->getKey() ) : false; - } - - /** - * Sets availability for the current instance - * - * @note It will assert the availability of the BagOStuff object by default - * and return false independently from the parameter invoked (this - * safeguards against overriding the availability status of a non-BagOStuff - * instance) - * - * @since 1.9 - * - * @param boolean $cacheEnabled - * - * @return CacheHandler - */ - public function setCacheEnabled( $cacheEnabled ) { - $this->cacheEnabled = $this->getCache() instanceof BagOStuff ? (bool)$cacheEnabled : false; - return $this; - } - - /** - * Returns current status of the cache instance - * - * @since 1.9 - * - * @return boolean - */ - public function isEnabled() { - return $this->cacheEnabled && $this->key; - } - - /** - * Reset instance - * - * @since 1.9 - */ - public static function reset() { - self::$instance = array(); - } -} diff --git a/SemanticMediaWiki/includes/cache/CacheIdGenerator.php b/SemanticMediaWiki/includes/cache/CacheIdGenerator.php deleted file mode 100644 index fb443aa2..00000000 --- a/SemanticMediaWiki/includes/cache/CacheIdGenerator.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -namespace SMW; - -/** - * This class is responsible for generating a cache key - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * This class is responsible for generating a cache key - * - * @ingroup Cache - */ -class CacheIdGenerator extends HashIdGenerator { - - /** - * Returns a prefix - * - * @since 1.9 - * - * @return string - */ - public function getPrefix() { - return $this->prefix === null ? $this->buildPrefix( 'smw' ) : $this->buildPrefix( 'smw' . ':' . $this->prefix ); - } - - /** - * Builds a prefix string - * - * @note Somehow eliminate the global function wfWikiID - * - * @since 1.9 - * - * @return string - */ - protected function buildPrefix( $prefix ) { - $CachePrefix = $GLOBALS['wgCachePrefix'] === false ? wfWikiID() : $GLOBALS['wgCachePrefix']; - return $CachePrefix . ':' . $prefix . ':'; - } - -} diff --git a/SemanticMediaWiki/includes/cache/CacheableResultMapper.php b/SemanticMediaWiki/includes/cache/CacheableResultMapper.php deleted file mode 100644 index fa1633b7..00000000 --- a/SemanticMediaWiki/includes/cache/CacheableResultMapper.php +++ /dev/null @@ -1,158 +0,0 @@ -<?php - -namespace SMW; - -use InvalidArgumentException; -use MWTimestamp; - -/** - * Handling of cached results - * - * Convenience class that fetches results from cache or recaches the results and - * stores meta information (cache time etc.) about each set with the object - * - * @code - * $dictionary = new SimpleDictionary( array( - * 'id' => ..., - * 'type' => ..., - * 'enabled' => ..., - * 'expiry' => ... - * ) ); - * - * $resultCache = new CacheableResultMapper( $dictionary ); - * $resultCache->recache( array() ); - * $resultCache->fetchFromCache(); - * $resultCache->getCacheDate(); - * @endcode - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class CacheableResultMapper { - - /** @var ObjectDictionary */ - protected $cacheSetup; - - /** - * @since 1.9 - * - * @param ObjectDictionary $cacheSetup - */ - public function __construct( ObjectDictionary $cacheSetup ) { - $this->cacheSetup = $cacheSetup; - } - - /** - * Fetches results from cache for a given CacheIdGenerator - * - * @since 1.9 - * - * @return array|false - */ - public function fetchFromCache() { - $result = $this->getCache() - ->setCacheEnabled( $this->cacheSetup->get( 'enabled' ) ) - ->setKey( $this->getIdGenerator() )->get(); - - return $result ? $this->mapping( $result ) : $result; - } - - /** - * Stores results in the cache - * - * @note Each cache object stores the time and its results as serialized - * array in order to allow any arbitrary content to be cacheable - * - * @note Results are serialized as they can contain an array of objects - * where when retrieved from cache those objects are going to be - * unserialized to restore its former condition - * - * @since 1.9 - * - * @param array $results - */ - public function recache( array $results ) { - $this->getCache() - ->setCacheEnabled( $this->cacheSetup->get( 'enabled' ) && $results !== array() ) - ->setKey( $this->getIdGenerator() ) - ->set( array( 'time' => $this->getTimestamp(), 'result' => serialize( $results ) ), $this->cacheSetup->get( 'expiry' ) - ); - } - - /** - * Returns a CacheIdGenerator objects - * - * @since 1.9 - * - * @return CacheIdGenerator - */ - public function getIdGenerator() { - return new CacheIdGenerator( $this->cacheSetup->get( 'id' ), $this->cacheSetup->get( 'prefix' ) ); - } - - /** - * Returns the timestamp of the cached objects - * - * @since 1.9 - * - * @return integer|null - */ - public function getCacheDate() { - return $this->cacheSetup->has( 'cacheDate' ) ? $this->cacheSetup->get( 'cacheDate' ) : null; - } - - /** - * Returns a CacheHandler instance - * - * @since 1.9 - * - * @return CacheHandler - */ - public function getCache() { - return CacheHandler::newFromId( $this->cacheSetup->get( 'type' ) ); - } - - /** - * Mapping of cached content - * - * Returns unserialized objects and the timestamp of the cached content - * - * @since 1.9 - * - * @param array $resultCache - * - * @return array - */ - protected function mapping( array $resultCache ) { - $this->cacheSetup->set( 'cacheDate', isset( $resultCache['time'] ) ? $resultCache['time'] : null ); - return isset( $resultCache['result'] ) ? unserialize( $resultCache['result'] ) : array(); - } - - /** - * Returns a timestamp - * - * @todo Apparently MW 1.19 does not have a MWTimestamp class, please - * remove this clutter as soon as MW 1.19 is not supported any longer - * - * @since 1.9 - * - * @return integer - */ - protected function getTimestamp() { - - if ( class_exists( 'MWTimestamp' ) ) { - $timestamp = new MWTimestamp(); - return $timestamp->getTimestamp( TS_UNIX ); - } else { - // @codeCoverageIgnoreStart - return wfTimestamp( TS_UNIX ); - // @codeCoverageIgnoreEnd - } - - } - -} diff --git a/SemanticMediaWiki/includes/context/ContextAware.php b/SemanticMediaWiki/includes/context/ContextAware.php deleted file mode 100644 index e04e8669..00000000 --- a/SemanticMediaWiki/includes/context/ContextAware.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface that describes access to a ContextResource object - * - * @note It is expected that a context object is either injected using a constructor - * or implements the ContextInjector interface - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface ContextAware { - - /** - * Returns a ContextResource object - * - * @since 1.9 - * - * @return ContextResource - */ - public function withContext(); - -} diff --git a/SemanticMediaWiki/includes/context/ContextInjector.php b/SemanticMediaWiki/includes/context/ContextInjector.php deleted file mode 100644 index baf6dbab..00000000 --- a/SemanticMediaWiki/includes/context/ContextInjector.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface that describes a method to inject a ContextResource object - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface ContextInjector { - - /** - * Invokes a ContextResource object - * - * @since 1.9 - */ - public function invokeContext( ContextResource $context ); - -} diff --git a/SemanticMediaWiki/includes/context/ContextResource.php b/SemanticMediaWiki/includes/context/ContextResource.php deleted file mode 100644 index 63e08a12..00000000 --- a/SemanticMediaWiki/includes/context/ContextResource.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface that describes a ContextResource object - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface ContextResource { - - /** - * Returns a Store object - * - * @since 1.9 - * - * @return Store - */ - public function getStore(); - - /** - * Returns a Settings object - * - * @since 1.9 - * - * @return Settings - */ - public function getSettings(); - - /** - * Returns a DependencyBuilder object - * - * @since 1.9 - * - * @return DependencyBuilder - */ - public function getDependencyBuilder(); - -} diff --git a/SemanticMediaWiki/includes/context/EmptyContext.php b/SemanticMediaWiki/includes/context/EmptyContext.php deleted file mode 100644 index f383b5e6..00000000 --- a/SemanticMediaWiki/includes/context/EmptyContext.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -namespace SMW; - -/** - * Implementing a ContextResource interface and returning null - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class EmptyContext implements ContextResource { - - /** @var DependencyBuilder */ - private $dependencyBuilder = null; - - /** - * @since 1.9 - */ - public function __construct() { - $this->dependencyBuilder = $this->register( null ); - } - - /** - * Returns a Store object - * - * @since 1.9 - * - * @return Store - */ - public function getStore() { - return $this->getDependencyBuilder()->newObject( 'Store' ); - } - - /** - * Returns a Settings object - * - * @since 1.9 - * - * @return Settings - */ - public function getSettings() { - return $this->getDependencyBuilder()->newObject( 'Settings' ); - } - - /** - * Returns a DependencyBuilder object - * - * @since 1.9 - * - * @return DependencyBuilder - */ - public function getDependencyBuilder() { - return $this->dependencyBuilder; - } - - /** - * Register a builder - * - * @since 1.9 - */ - protected function register( DependencyBuilder $builder = null ) { - - if ( $builder === null ) { - $builder = new SimpleDependencyBuilder( new NullDependencyContainer() ); - } - - $builder->getContainer()->registerObject( 'Settings', null ); - $builder->getContainer()->registerObject( 'Store', null ); - $builder->getContainer()->registerObject( 'ExtensionContext', $this ); - - return $builder; - } - -} diff --git a/SemanticMediaWiki/includes/context/ExtensionContext.php b/SemanticMediaWiki/includes/context/ExtensionContext.php deleted file mode 100644 index eed18d2a..00000000 --- a/SemanticMediaWiki/includes/context/ExtensionContext.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -namespace SMW; - -/** - * Default implementation of the ContextResource interface - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class ExtensionContext implements ContextResource { - - /** @var DependencyBuilder */ - private $dependencyBuilder = null; - - /** - * @since 1.9 - * - * @param DependencyBuilder|null $builder - */ - public function __construct( DependencyBuilder $builder = null ) { - $this->dependencyBuilder = $this->register( $builder ); - } - - /** - * Returns a Store object - * - * @since 1.9 - * - * @return Store - */ - public function getStore() { - return $this->getDependencyBuilder()->newObject( 'Store' ); - } - - /** - * Returns a Settings object - * - * @since 1.9 - * - * @return Settings - */ - public function getSettings() { - return $this->getDependencyBuilder()->newObject( 'Settings' ); - } - - /** - * Returns a DependencyBuilder object - * - * @since 1.9 - * - * @return DependencyBuilder - */ - public function getDependencyBuilder() { - return $this->dependencyBuilder; - } - - /** - * Register a builder - * - * @note Always register a builder with a self-reference to the current - * context object to ensure all objects are accessing the context derive - * from the same "root" - * - * @since 1.9 - */ - protected function register( DependencyBuilder $builder = null ) { - - if ( $builder === null ) { - $builder = new SimpleDependencyBuilder( new SharedDependencyContainer() ); - } - - $builder->getContainer()->registerObject( 'ExtensionContext', $this ); - return $builder; - } - -} diff --git a/SemanticMediaWiki/includes/dataitems/DIConcept.php b/SemanticMediaWiki/includes/dataitems/DIConcept.php deleted file mode 100644 index b376fd86..00000000 --- a/SemanticMediaWiki/includes/dataitems/DIConcept.php +++ /dev/null @@ -1,201 +0,0 @@ -<?php - -namespace SMW; - -use SMWDataItem; -use SMWDataItemException; - -/** - * This class implements Concept data items. - * - * @note These special data items for storing concept declaration data in SMW - * should vanish at some point since Container values could encode this data - * just as well. - * - * @since 1.6 - * - * @ingroup SMWDataItems - * - * @author Markus Krötzsch - * @author mwjames - */ -class DIConcept extends \SMWDataItem { - - /** - * Query string for this concept. Possibly long. - * @var string - */ - protected $m_concept; - /** - * Documentation for this concept. Possibly long. - * @var string - */ - protected $m_docu; - /** - * Flags of query features. - * @var integer - */ - protected $m_features; - /** - * Size of the query. - * @var integer - */ - protected $m_size; - /** - * Depth of the query. - * @var integer - */ - protected $m_depth; - - /** - * Status - * @var integer - */ - protected $cacheStatus; - - /** - * Date - * @var integer - */ - protected $cacheDate; - - /** - * Count - * @var integer - */ - protected $cacheCount; - - /** - * @param string $concept the concept query string - * @param string $docu user documentation - * @param integer $queryefeatures flags about query features - * @param integer $size concept query size - * @param integer $depth concept query depth - */ - public function __construct( $concept, $docu, $queryfeatures, $size, $depth ) { - $this->m_concept = $concept; - $this->m_docu = $docu; - $this->m_features = $queryfeatures; - $this->m_size = $size; - $this->m_depth = $depth; - } - - public function getDIType() { - return SMWDataItem::TYPE_CONCEPT; - } - - public function getConceptQuery() { - return $this->m_concept; - } - - public function getDocumentation() { - return $this->m_docu; - } - - public function getQueryFeatures() { - return $this->m_features; - } - - public function getSize() { - return $this->m_size; - } - - public function getDepth() { - return $this->m_depth; - } - - public function getSortKey() { - return $this->m_docu; - } - - public function getSerialization() { - return serialize( $this ); - } - - /** - * Sets cache status - * - * @since 1.9 - * - * @param string - */ - public function setCacheStatus( $status ) { - $this->cacheStatus = $status; - } - - /** - * Sets cache date - * - * @since 1.9 - * - * @param string - */ - public function setCacheDate( $date ) { - $this->cacheDate = $date; - } - - /** - * Sets cache count - * - * @since 1.9 - * - * @param int - */ - public function setCacheCount( $count ) { - $this->cacheCount = $count; - } - - /** - * Returns cache status - * - * @since 1.9 - * - * @return string - */ - public function getCacheStatus() { - return $this->cacheStatus; - } - - /** - * Returns cache date - * - * @since 1.9 - * - * @return string - */ - public function getCacheDate() { - return $this->cacheDate; - } - - /** - * Returns cache count - * - * @since 1.9 - * - * @return int - */ - public function getCacheCount() { - return $this->cacheCount; - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * @return DIConcept - */ - public static function doUnserialize( $serialization ) { - $result = unserialize( $serialization ); - if ( $result === false ) { - throw new DataItemException( "Unserialization failed." ); - } - return $result; - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_CONCEPT ) { - return false; - } - return $di->getSerialization() === $this->getSerialization(); - } - -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_Blob.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_Blob.php deleted file mode 100644 index cbe59f50..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_Blob.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItems - */ - -/** - * This class implements blob (long string) data items. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWDIBlob extends SMWDataItem { - - /** - * Internal value. - * @var string - */ - protected $m_string; - - public function __construct( $string ) { - $this->m_string = $string; - } - - public function getDIType() { - return SMWDataItem::TYPE_BLOB; - } - - public function getString() { - return $this->m_string; - } - - public function getSortKey() { - return $this->m_string; - } - - /** - * @see SMWDataItem::getSortKeyDataItem() - * @return SMWDataItem - */ - public function getSortKeyDataItem() { - return $this; - } - - public function getSerialization() { - return $this->m_string; - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * @return SMWDIBlob - */ - public static function doUnserialize( $serialization ) { - return new SMWDIBlob( $serialization ); - } - - public function equals( SMWDataItem $di ) { - if ( !( $di instanceof SMWDIBlob ) ) { - return false; - } - - return $di->getString() === $this->m_string; - } -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_Bool.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_Bool.php deleted file mode 100644 index ae6def98..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_Bool.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItems - */ -use SMW\DataItemException; - -/** - * This class implements Boolean data items. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWDIBoolean extends SMWDataItem { - - /** - * Internal value. - * @var bool - */ - protected $m_boolean; - - public function __construct( $boolean ) { - if ( !is_bool( $boolean ) ) { - throw new DataItemException( "Initialization value '$boolean' is not a boolean." ); - } - - $this->m_boolean = ( $boolean == true ); - } - - public function getDIType() { - return SMWDataItem::TYPE_BOOLEAN; - } - - public function getBoolean() { - return $this->m_boolean; - } - - public function getSerialization() { - return $this->m_boolean ? 't' : 'f'; - } - - public function getSortKey() { - return $this->m_boolean ? 1 : 0; - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * @return SMWDIBoolean - */ - public static function doUnserialize( $serialization ) { - if ( $serialization == 't' ) { - return new SMWDIBoolean( true ); - } elseif ( $serialization == 'f' ) { - return new SMWDIBoolean( false ); - } else { - throw new DataItemException( "Boolean data item unserialised from illegal value '$serialization'" ); - } - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_BOOLEAN ) { - return false; - } - return $di->getBoolean() === $this->m_boolean; - } -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_Container.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_Container.php deleted file mode 100644 index e38f0ed5..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_Container.php +++ /dev/null @@ -1,199 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItems - */ - -use SMW\DataItemException; - -/** - * Subclass of SMWSemanticData that is used to store the data in SMWDIContainer - * objects. It is special since the subject that the stored property-value pairs - * refer may or may not be specified explicitly. This can be tested with - * hasAnonymousSubject(). When trying to access the subject in anonymous state, - * an Exception will be thrown. Anonymous container data items are used when no - * page context is available, e.g. when specifying such a value in a search form - * where the parent page is not known. - * - * Besides this change, the subclass mainly is needed to restroe the disabled - * serialization of SMWSemanticData. - * - * See also the documentation of SMWDIContainer. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWContainerSemanticData extends SMWSemanticData { - - /** - * Construct a data container that refers to an anonymous subject. See - * the documentation of the class for details. - * - * @since 1.7 - * - * @param boolean $noDuplicates stating if duplicate data should be avoided - */ - public static function makeAnonymousContainer( $noDuplicates = true ) { - $subject = new SMWDIWikiPage( 'SMWInternalObject', NS_SPECIAL, '' ); - return new SMWContainerSemanticData( $subject, $noDuplicates ); - } - - /** - * Restore complete serialization which is disabled in SMWSemanticData. - */ - public function __sleep() { - return array( 'mSubject', 'mProperties', 'mPropVals', - 'mHasVisibleProps', 'mHasVisibleSpecs', 'mNoDuplicates' ); - } - - /** - * Check if the subject of this container is an anonymous object. - * See the documenation of the class for details. - * - * @return boolean - */ - public function hasAnonymousSubject() { - if ( $this->mSubject->getNamespace() == NS_SPECIAL && - $this->mSubject->getDBkey() == 'SMWInternalObject' && - $this->mSubject->getInterwiki() === '' ) { - return true; - } else { - return false; - } - } - - /** - * Return subject to which the stored semantic annotation refer to, or - * throw an exception if the subject is anonymous (if the data has not - * been contextualized with setMasterPage() yet). - * - * @return SMWDIWikiPage subject - */ - public function getSubject() { - if ( $this->hasAnonymousSubject() ) { - throw new DataItemException("Trying to get the subject of a container data item that has not been given any. This container can only be used as a search pattern."); - } else { - return $this->mSubject; - } - } - - /** - * Change the object to become an exact copy of the given - * SMWSemanticData object. This is used to make other types of - * SMWSemanticData into an SMWContainerSemanticData. To copy objects of - * the same type, PHP clone() should be used. - * - * @since 1.7 - * - * @param $semanticData SMWSemanticData object to copy from - */ - public function copyDataFrom( SMWSemanticData $semanticData ) { - $this->mSubject = $semanticData->getSubject(); - $this->mProperties = $semanticData->getProperties(); - $this->mPropVals = array(); - foreach ( $this->mProperties as $property ) { - $this->mPropVals[$property->getKey()] = $semanticData->getPropertyValues( $property ); - } - $this->mHasVisibleProps = $semanticData->hasVisibleProperties(); - $this->mHasVisibleSpecs = $semanticData->hasVisibleSpecialProperties(); - $this->mNoDuplicates = $semanticData->mNoDuplicates; - } - -} - -/** - * This class implements container data items that can store SMWSemanticData - * objects. Containers are not dataitems in the proper sense: they do not - * represent a single, opaque value that can be assigned to a property. Rather, - * a container represents a "subobject" with a number of property-value - * assignments. When a container is stored, these individual data assignments - * are stored -- the data managed by SMW never contains any "container", just - * individual property assignments for the subobject. Likewise, when a container - * is used in search, it is interpreted as a patterns of possible property - * assignments, and this pattern is searched for. - * - * The data encapsulated in a container data item is essentially an - * SMWSemanticData object of class SMWContainerSemanticData. This class allows - * the subject to be kept anonymous if not known (if no context page is - * available for finding a suitable subobject name). See the repsective - * documentation for details. - * - * Being a mere placeholder/template for other data, an SMWDIContainer is not - * immutable as the other basic data items. New property-value pairs can always - * be added to the internal SMWContainerSemanticData. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWDIContainer extends SMWDataItem { - - /** - * Internal value. - * - * @var SMWSemanticData - */ - protected $m_semanticData; - - /** - * Constructor. The given SMWContainerSemanticData object will be owned - * by the constructed object afterwards, and in particular will not - * allow further changes. - * - * @param $semanticData SMWContainerSemanticData - */ - public function __construct( SMWContainerSemanticData $semanticData ) { - $this->m_semanticData = $semanticData; - } - - public function getDIType() { - return SMWDataItem::TYPE_CONTAINER; - } - - public function getSemanticData() { - return $this->m_semanticData; - } - - public function getSortKey() { - return ''; - } - - public function getSerialization() { - return serialize( $this->m_semanticData ); - } - - /** - * Get a hash string for this data item. - * - * @return string - */ - public function getHash() { - return $this->m_semanticData->getHash(); - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * - * @return SMWDIContainer - */ - public static function doUnserialize( $serialization ) { - /// TODO May issue an E_NOTICE when problems occur; catch this - $data = unserialize( $serialization ); - if ( !( $data instanceof SMWContainerSemanticData ) ) { - throw new DataItemException( "Could not unserialize SMWDIContainer from the given string." ); - } - return new SMWDIContainer( $data ); - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_CONTAINER ) { - return false; - } - - return $di->getSerialization() === $this->getSerialization(); - } -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_Error.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_Error.php deleted file mode 100644 index 110633eb..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_Error.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItems - */ - -/** - * This class implements error list data items. These data items are used to - * pass around lists of error messages within the application. They are not - * meant to be stored or exported, but they can be useful to a user. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWDIError extends SMWDataItem { - - /** - * List of error messages. Should always be safe for HTML. - * @var array of strings - */ - protected $m_errors; - - public function __construct( $errors ) { - $this->m_errors = $errors; - } - - public function getDIType() { - return SMWDataItem::TYPE_ERROR; - } - - public function getErrors() { - return $this->m_errors; - } - - public function getSortKey() { - return 'error'; - } - - public function getSerialization() { - return serialize( $this->m_errors ); - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * @todo Be more careful with unserialization. It can create E_NOTICEs. - * @return SMWDIError - */ - public static function doUnserialize( $serialization ) { - return new SMWDIError( unserialize( $serialization ) ); - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_ERROR ) { - return false; - } - - return $di->getSerialization() === $this->getSerialization(); - } -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_GeoCoord.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_GeoCoord.php deleted file mode 100644 index a7549881..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_GeoCoord.php +++ /dev/null @@ -1,193 +0,0 @@ -<?php - -use SMW\DataItemException; - -/** - * Implementation of dataitems that are geographic coordinates. - * - * @since 1.6 - * - * @file SMW_DI_GeoCoord.php - * @ingroup SemanticMaps - * - * @licence GNU GPL v3 - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class SMWDIGeoCoord extends SMWDataItem { - - /** - * The locations latitude. - * - * @since 1.6 - * @var float - */ - protected $latitude; - - /** - * The locations longitude. - * - * @since 1.6 - * @var float - */ - protected $longitude; - - /** - * The locations altitude. - * - * @since 1.7 - * @var float|null - */ - protected $altitude = null; - - /** - * Constructor. - * Takes a latitude and longitude, and optionally an altitude. These can be provided in 2 forms: - * * An associative array with lat, lon and alt keys - * * Lat, lon and alt arguments - * - * The second way to provide the arguments, as well as the altitude argument, where introduced in SMW 1.7. - */ - public function __construct() { - $args = func_get_args(); - - $count = count( $args ); - - if ( $count === 1 && is_array( $args[0] ) ) { - if ( array_key_exists( 'lat', $args[0] ) && array_key_exists( 'lon', $args[0] ) ) { - $this->latitude = (float)$args[0]['lat']; - $this->longitude = (float)$args[0]['lon']; - - if ( array_key_exists( 'alt', $args[0] ) ) { - $this->altitude = (float)$args[0]['alt']; - } - } - else { - throw new DataItemException( 'Invalid coordinate data passed to the SMWDIGeoCoord constructor' ); - } - } - elseif ( $count === 2 || $count === 3 ) { - $this->latitude = (float)$args[0]; - $this->longitude = (float)$args[1]; - - if ( $count === 3 ) { - $this->altitude = (float)$args[2]; - } - } - else { - throw new DataItemException( 'Invalid coordinate data passed to the SMWDIGeoCoord constructor' ); - } - } - - /** - * (non-PHPdoc) - * @see SMWDataItem::getDIType() - */ - public function getDIType() { - return SMWDataItem::TYPE_GEO; - } - - /** - * Returns the coordinate set as an array with lat and long (and alt) keys - * pointing to float values. - * - * @since 1.6 - * - * @return array - */ - public function getCoordinateSet() { - $coords = array( 'lat' => $this->latitude, 'lon' => $this->longitude ); - - if ( !is_null( $this->altitude ) ) { - $coords['alt'] = $this->altitude; - } - - return $coords; - } - - /** - * (non-PHPdoc) - * @see SMWDataItem::getSortKey() - */ - public function getSortKey() { - // Maybe also add longitude here? Or is there a more meaningfull value we can return? - return $this->latitude; - } - - /** - * (non-PHPdoc) - * @see SMWDataItem::getSerialization() - */ - public function getSerialization() { - return implode( ',', $this->getCoordinateSet() ); - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * @note PHP can convert any string to some number, so we do not do - * validation here (because this would require less efficient parsing). - * - * @since 1.6 - * - * @param string $serialization - * - * @return SMWDIGeoCoord - */ - public static function doUnserialize( $serialization ) { - $parts = explode( ',', $serialization ); - $count = count( $parts ); - - if ( $count !== 2 && $count !== 3 ) { - throw new DataItemException( 'Unserialization of coordinates failed' ); - } - - $coords = array( 'lat' => (float)$parts[0], 'lon' => (float)$parts[1] ); - - if ( $count === 3 ) { - $coords['alt'] = (float)$parts[2]; - } - - return new self( $coords ); - } - - /** - * Returns the latitude. - * - * @since 1.6 - * - * @return float - */ - public function getLatitude() { - return $this->latitude; - } - - /** - * Returns the longitude. - * - * @since 1.6 - * - * @return float - */ - public function getLongitude() { - return $this->longitude; - } - - /** - * Returns the altitude if set, null otherwise. - * - * @since 1.7 - * - * @return float|null - */ - public function getAltitude() { - return $this->altitude; - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_GEO ) { - return false; - } - - return $di->getSerialization() === $this->getSerialization(); - } -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_Number.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_Number.php deleted file mode 100644 index 8e63bb3f..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_Number.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItems - */ - -use SMW\DataItemException; - -/** - * This class implements number data items. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWDINumber extends SMWDataItem { - - /** - * Internal value. - * @var numeric - */ - protected $m_number; - - public function __construct( $number ) { - if ( !is_numeric( $number ) ) { - throw new DataItemException( "Initialization value '$number' is not a number." ); - } - $this->m_number = $number; - } - - public function getDIType() { - return SMWDataItem::TYPE_NUMBER; - } - - public function getNumber() { - return $this->m_number; - } - - public function getSortKey() { - return $this->m_number; - } - - /** - * @see SMWDataItem::getSortKeyDataItem() - * @return SMWDataItem - */ - public function getSortKeyDataItem() { - return $this; - } - - public function getSerialization() { - return strval( $this->m_number ); - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * @note PHP can convert any string to some number, so we do not do - * validation here (because this would require less efficient parsing). - * @return SMWDINumber - */ - public static function doUnserialize( $serialization ) { - return new SMWDINumber( floatval( $serialization ) ); - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_NUMBER ) { - return false; - } - - return $di->getNumber() === $this->m_number; - } - -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_Property.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_Property.php deleted file mode 100644 index df1ad2f0..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_Property.php +++ /dev/null @@ -1,511 +0,0 @@ -<?php - -namespace SMW; - -use SMWDataItem; -use SMWDIUri; -use SMWDIWikiPage; -use SMWLanguage; - -use InvalidArgumentException; -use RuntimeException; -use SMW\InvalidPropertyException; -use SMW\InvalidPredefinedPropertyException; - -/** - * This class implements Property data items. - * - * The static part of this class also manages global registrations of - * predefined (built-in) properties, and maintains an association of - * property IDs, localized labels, and aliases. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class DIProperty extends SMWDataItem { - - // Property subobject data item ID - const TYPE_SUBOBJECT = '_SOBJ'; - // Property improper value data item ID - const TYPE_ERROR = '_ERRP'; - // Property instance of a category - const TYPE_CATEGORY = '_INST'; - // Property "subcategory of" - const TYPE_SUBCATEGORY = '_SUBC'; - // Property sort key of a page - const TYPE_SORTKEY = '_SKEY'; - // Property modification date - const TYPE_MODIFICATION_DATE = '_MDAT'; - // Property "creation date" - const TYPE_CREATION_DATE = '_CDAT'; - // Property "last editor is" - const TYPE_LAST_EDITOR = '_LEDT'; - // Property "is a new page" - const TYPE_NEW_PAGE = '_NEWP'; - // Property "has type" - const TYPE_HAS_TYPE = '_TYPE'; - // Property "corresponds to" - const TYPE_CONVERSION = '_CONV'; - // Property "has query" - const TYPE_ASKQUERY = '_ASK'; - - // Property "has media type" - const TYPE_MEDIA = '_MEDIA'; - // Property "has mime type" - const TYPE_MIME = '_MIME'; - - /** - * Array for assigning types to predefined properties. Each - * property is associated with an array with the following - * elements: - * - * * ID of datatype to be used for this property - * - * * Boolean, stating if this property is shown in Factbox, Browse, and - * similar interfaces; (note that this is only relevant if the - * property can be displayed at all, i.e. has a translated label in - * the wiki language; invisible properties are never shown). - * - * @var array - */ - static private $m_prop_types; - - /** - * Array with entries "property id" => "property label" - * @var array - */ - static private $m_prop_labels; - - /** - * Array with entries "property alias" => "property id" - * @var array - */ - static private $m_prop_aliases; - - /** - * Either an internal SMW property key (starting with "_") or the DB - * key of a property page in the wiki. - * @var string - */ - private $m_key; - - /** - * Whether to take the inverse of this property or not. - * @var boolean - */ - private $m_inverse; - - /** - * Cache for property type ID. - * @var string - */ - private $m_proptypeid; - - /** - * Initialise a property. This constructor checks that keys of - * predefined properties do really exist (in the current configuration - * of the wiki). No check is performed to see if a user label is in - * fact the label or alias of a predefined property. If this should be - * done, the function self::newFromUserLabel() can be used. - * - * @param $key string key for the property (internal SMW key or wikipage DB key) - * @param $inverse boolean states if the inverse of the property is constructed - */ - public function __construct( $key, $inverse = false ) { - if ( ( $key === '' ) || ( $key{0} == '-' ) ) { - throw new InvalidPropertyException( "Illegal property key \"$key\"." ); - } - - if ( $key{0} == '_' ) { - self::initPropertyRegistration(); - if ( !array_key_exists( $key, self::$m_prop_types ) ) { - throw new InvalidPredefinedPropertyException( "There is no predefined property with \"$key\"." ); - } - } - - $this->m_key = $key; - $this->m_inverse = $inverse; - } - - public function getDIType() { - return SMWDataItem::TYPE_PROPERTY; - } - - public function getKey() { - return $this->m_key; - } - - public function isInverse() { - return $this->m_inverse; - } - - public function getSortKey() { - return $this->m_key; - } - - /** - * Specifies whether values of this property should be shown in the - * Factbox. A property may wish to prevent this if either - * (1) its information is really dull, e.g. being a mere copy of - * information that is obvious from other things that are shown, or - * (2) the property is set in a hook after parsing, so that it is not - * reliably available when Factboxes are displayed. If a property is - * internal so it should never be observed by users, then it is better - * to just not associate any translated label with it, so it never - * appears anywhere. - * - * Examples of properties that are not shown include Modification date - * (not available in time), and Has improper value for (errors are - * shown directly on the page anyway). - * - * @return boolean - */ - public function isShown() { - return ( ( $this->isUserDefined() ) || - ( array_key_exists( $this->m_key, self::$m_prop_types ) && - self::$m_prop_types[$this->m_key][1] ) ); - } - - /** - * Return true if this is a usual wiki property that is defined by a - * wiki page, and not a property that is pre-defined in the wiki. - * - * @return boolean - */ - public function isUserDefined() { - return $this->m_key{0} != '_'; - } - - /** - * Find a user-readable label for this property, or return '' if it is - * a predefined property that has no label. For inverse properties, the - * label starts with a "-". - * - * @return string - */ - public function getLabel() { - $prefix = $this->m_inverse ? '-' : ''; - if ( $this->isUserDefined() ) { - return $prefix . str_replace( '_', ' ', $this->m_key ); - } else { - return self::findPropertyLabel( $this->m_key ); - } - } - - /** - * Get an object of type SMWDIWikiPage that represents the page which - * relates to this property, or null if no such page exists. The latter - * can happen for special properties without user-readable label, and - * for inverse properties. - * - * It is possible to construct subobjects of the property's wikipage by - * providing an optional subobject name. - * - * @param string $subobjectName - * @return SMWDIWikiPage|null - */ - public function getDiWikiPage( $subobjectName = '' ) { - if ( $this->m_inverse ) { - return null; - } - - if ( $this->isUserDefined() ) { - $dbkey = $this->m_key; - } else { - $dbkey = str_replace( ' ', '_', $this->getLabel() ); - } - - try { - return new SMWDIWikiPage( $dbkey, SMW_NS_PROPERTY, '', $subobjectName ); - } catch ( DataItemException $e ) { - return null; - } - } - - /** - * @since 2.0 - * - * @return self - * @throws RuntimeException - * @throws InvalidArgumentException - */ - public function setPropertyTypeId( $propertyTypeId ) { - - if ( !DataTypeRegistry::getInstance()->isKnownTypeId( $propertyTypeId ) ) { - throw new RuntimeException( "{$propertyTypeId} is an unknown type id" ); - } - - if ( $this->isUserDefined() && $this->m_proptypeid === null ) { - $this->m_proptypeid = $propertyTypeId; - return $this; - } - - if ( !$this->isUserDefined() && $propertyTypeId === self::getPredefinedPropertyTypeId( $this->m_key ) ) { - $this->m_proptypeid = $propertyTypeId; - return $this; - } - - throw new InvalidArgumentException( 'Property type can not be altered for a predefined object' ); - } - - /** - * Find the property's type ID, either by looking up its predefined ID - * (if any) or by retrieving the relevant information from the store. - * If no type is stored for a user defined property, the global default - * type will be used. - * - * @return string type ID - */ - public function findPropertyTypeID() { - global $smwgPDefaultType; - - if ( !isset( $this->m_proptypeid ) ) { - if ( $this->isUserDefined() ) { // normal property - $diWikiPage = new SMWDIWikiPage( $this->getKey(), SMW_NS_PROPERTY, '' ); - $typearray = \SMW\StoreFactory::getStore()->getPropertyValues( $diWikiPage, new self( '_TYPE' ) ); - - if ( count( $typearray ) >= 1 ) { // some types given, pick one (hopefully unique) - $typeDataItem = reset( $typearray ); - - if ( $typeDataItem instanceof SMWDIUri ) { - $this->m_proptypeid = $typeDataItem->getFragment(); - } else { - $this->m_proptypeid = $smwgPDefaultType; - // This is important. If a page has an invalid assignment to "has type", no - // value will be stored, so the elseif case below occurs. But if the value - // is retrieved within the same run, then the error value for "has type" is - // cached and thus this case occurs. This is why it is important to tolerate - // this case -- it is not necessarily a DB error. - } - } elseif ( count( $typearray ) == 0 ) { // no type given - $this->m_proptypeid = $smwgPDefaultType; - } - } else { // pre-defined property - $this->m_proptypeid = self::getPredefinedPropertyTypeId( $this->m_key ); - } - } - - return $this->m_proptypeid; - } - - - public function getSerialization() { - return ( $this->m_inverse ? '-' : '' ) . $this->m_key; - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * - * @param string $serialization - * - * @return DIProperty - */ - public static function doUnserialize( $serialization ) { - $inverse = false; - - if ( $serialization{0} == '-' ) { - $serialization = substr( $serialization, 1 ); - $inverse = true; - } - - return new self( $serialization, $inverse ); - } - - /** - * Construct a property from a user-supplied label. The main difference - * to the normal constructor of DIProperty is that it is checked - * whether the label refers to a known predefined property. - * Note that this function only gives access to the registry data that - * DIProperty stores, but does not do further parsing of user input. - * For example, '-' as first character is not interpreted for inverting - * a property. Likewise, no normalization of title strings is done. To - * process wiki input, SMWPropertyValue should be used. - * - * @param $label string label for the property - * @param $inverse boolean states if the inverse of the property is constructed - * - * @return DIProperty object - */ - public static function newFromUserLabel( $label, $inverse = false ) { - $id = self::findPropertyID( $label ); - - if ( $id === false ) { - return new self( str_replace( ' ', '_', $label ), $inverse ); - } else { - return new self( $id, $inverse ); - } - } - - /** - * Find and return the ID for the pre-defined property of the given - * local label. If the label does not belong to a pre-defined property, - * return false. - * - * @param string $label normalized property label - * @param boolean $useAlias determining whether to check if the label is an alias - * - * @return mixed string property ID or false - */ - public static function findPropertyID( $label, $useAlias = true ) { - self::initPropertyRegistration(); - $id = array_search( $label, self::$m_prop_labels ); - - if ( $id !== false ) { - return $id; - } elseif ( $useAlias && array_key_exists( $label, self::$m_prop_aliases ) ) { - return self::$m_prop_aliases[$label]; - } else { - return false; - } - } - - /** - * Get the type ID of a predefined property, or '' if the property - * is not predefined. - * The function is guaranteed to return a type ID for keys of - * properties where isUserDefined() returns false. - * - * @param $key string key of the property - * - * @return string type ID - */ - public static function getPredefinedPropertyTypeId( $key ) { - self::initPropertyRegistration(); - if ( array_key_exists( $key, self::$m_prop_types ) ) { - return self::$m_prop_types[$key][0]; - } else { - return ''; - } - } - - /** - * Get the translated user label for a given internal property ID. - * Returns empty string for properties without a translation (these are - * usually internal, generated by SMW but not shown to the user). - * - * @since 1.8 public - * @param string $id - * @return string - */ - static public function findPropertyLabel( $id ) { - self::initPropertyRegistration(); - if ( array_key_exists( $id, self::$m_prop_labels ) ) { - return self::$m_prop_labels[$id]; - } else { // incomplete translation (language bug) or deliberately invisible property - return ''; - } - } - - /** - * Set up predefined properties, including their label, aliases, and - * typing information. - */ - static private function initPropertyRegistration() { - if ( is_array( self::$m_prop_types ) ) { - return; // init happened before - } - - /** - * @var SMWLanguage $smwgContLang - */ - global $smwgContLang, $smwgUseCategoryHierarchy; - - $datatypeLabels = $smwgContLang->getDatatypeLabels(); - - self::$m_prop_labels = $smwgContLang->getPropertyLabels() + $datatypeLabels; - self::$m_prop_aliases = $smwgContLang->getPropertyAliases() + $smwgContLang->getDatatypeAliases(); - - // Setup built-in predefined properties. - // NOTE: all ids must start with underscores. The translation - // for each ID, if any, is defined in the language files. - // Properties without translation cannot be entered by or - // displayed to users, whatever their "show" value below. - self::$m_prop_types = array( - self::TYPE_HAS_TYPE => array( '__typ', true ), // "has type" - '_URI' => array( '__spu', true ), // "equivalent URI" - self::TYPE_CATEGORY => array( '__sin', false ), // instance of a category - '_UNIT' => array( '__sps', true ), // "displays unit" - '_IMPO' => array( '__imp', true ), // "imported from" - self::TYPE_CONVERSION => array( '__sps', true ), // "corresponds to" - '_SERV' => array( '__sps', true ), // "provides service" - '_PVAL' => array( '__sps', true ), // "allows value" - '_REDI' => array( '__red', true ), // redirects to some page - '_SUBP' => array( '__sup', true ), // "subproperty of" - self::TYPE_SUBCATEGORY => array( '__suc', !$smwgUseCategoryHierarchy ), // "subcategory of" - '_CONC' => array( '__con', false ), // associated concept - self::TYPE_MODIFICATION_DATE => array( '_dat', false ), // "modification date" - self::TYPE_CREATION_DATE => array( '_dat', false ), // "creation date" - self::TYPE_NEW_PAGE => array( '_boo', false ), // "is a new page" - self::TYPE_LAST_EDITOR => array( '_wpg', false ), // "last editor is" - self::TYPE_ERROR => array( '_wpp', false ), // "has improper value for" - '_LIST' => array( '__pls', true ), // "has fields" - self::TYPE_SORTKEY => array( '__key', false ), // sort key of a page - '_SF_DF' => array( '__spf', true ), // Semantic Form's default form property - '_SF_AF' => array( '__spf', true ), // Semantic Form's alternate form property - self::TYPE_SUBOBJECT => array( '__sob', true ), // "has subobject" - self::TYPE_ASKQUERY => array( '__sob', false ), // "has query" - '_ASKST' => array( '_cod', true ), // "has query string" - '_ASKFO' => array( '_txt', true ), // "has query format" - '_ASKSI' => array( '_num', true ), // "has query size" - '_ASKDE' => array( '_num', true ), // "has query depth" - '_ASKDU' => array( '_num', true ), // "has query duration" - self::TYPE_MEDIA => array( '_txt', true ), // "has media type" - self::TYPE_MIME => array( '_txt', true ), // "has mime type" - ); - - foreach ( $datatypeLabels as $typeid => $label ) { - self::$m_prop_types[$typeid] = array( $typeid, true ); - } - - wfRunHooks( 'smwInitProperties' ); - } - - /** - * A method for registering/overwriting predefined properties for SMW. - * It should be called from within the hook 'smwInitProperties' only. - * IDs should start with three underscores "___" to avoid current and - * future confusion with SMW built-ins. - * - * @param $id string id - * @param $typeid SMW type id - * @param $label mixed string user label or false (internal property) - * @param $show boolean only used if label is given, see isShown() - * - * @note See self::isShown() for information about $show. - */ - static public function registerProperty( $id, $typeid, $label = false, $show = false ) { - self::$m_prop_types[$id] = array( $typeid, $show ); - - if ( $label != false ) { - self::$m_prop_labels[$id] = $label; - } - } - - /** - * Add a new alias label to an existing property ID. Note that every ID - * should have a primary label, either provided by SMW or registered - * with self::registerProperty(). This function should be - * called from within the hook 'smwInitDatatypes' only. - * - * @param $id string id of a property - * @param $label string alias label for the property - * - * @note Always use registerProperty() for the first label. No property - * that has used "false" for a label on registration should have an - * alias. - */ - static public function registerPropertyAlias( $id, $label ) { - self::$m_prop_aliases[$label] = $id; - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_PROPERTY ) { - return false; - } - - return $di->getKey() === $this->m_key; - } -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_String.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_String.php deleted file mode 100644 index 9b5deecd..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_String.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/** - * Unused class, kept for compatibilty. - * - * @deprecated Will be removed after SMW 1.9; do not use - */ -class SMWStringLengthException extends MWException { -} - -/** - * This class is an alias for SMWDIBlob, kept for compatibility. - * - * @since 1.6 - * @deprecated Will be removed after SMW 1.9; use SMWDIBlob instead - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWDIString extends SMWDIBlob { -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_Time.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_Time.php deleted file mode 100644 index 4cc668f2..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_Time.php +++ /dev/null @@ -1,469 +0,0 @@ -<?php - -use SMW\DataItemException; - -/** - * This class implements time data items. - * Such data items represent a unique point in time, given in either Julian or - * Gregorian notation (possibly proleptic), and a precision setting that states - * which of the components year, month, day, time were specified expicitly. - * Even when not specified, the data item always assumes default values for the - * missing parts, so the item really captures one point in time, no intervals. - * Times are always assumed to be in UTC. - * - * "Y0K issue": Neither the Gregorian nor the Julian calendar assume a year 0, - * i.e. the year 1 BC(E) was followed by 1 AD/CE. See - * http://en.wikipedia.org/wiki/Year_zero - * This implementation adheres to this convention and disallows year 0. The - * stored year numbers use positive numbers for CE and negative numbers for - * BCE. This is not just relevant for the question of how many years have - * (exactly) passed since a given date, but also for the location of leap - * years. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWDITime extends SMWDataItem { - - const CM_GREGORIAN = 1; - const CM_JULIAN = 2; - - const PREC_Y = 0; - const PREC_YM = 1; - const PREC_YMD = 2; - const PREC_YMDT = 3; - - /** - * Maximal number of days in a given month. - * @var array - */ - protected static $m_daysofmonths = array ( 1 => 31, 2 => 29, 3 => 31, 4 => 30, 5 => 31, 6 => 30, 7 => 31, 8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31 ); - - /** - * Precision SMWDITime::PREC_Y, SMWDITime::PREC_YM, - * SMWDITime::PREC_YMD, or SMWDITime::PREC_YMDT. - * @var integer - */ - protected $m_precision; - /** - * Calendar model: SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN. - * @var integer - */ - protected $m_model; - /** - * Number of year, possibly negative. - * @var integer - */ - protected $m_year; - /** - * Number of month. - * @var integer - */ - protected $m_month; - /** - * Number of day. - * @var integer - */ - protected $m_day; - /** - * Hours of the day. - * @var integer - */ - protected $m_hours; - /** - * Minutes of the hour. - * @var integer - */ - protected $m_minutes; - /** - * Seconds of the minute. - * @var integer - */ - protected $m_seconds; - - /** - * Create a time data item. All time components other than the year can - * be false to indicate that they are not specified. This will affect - * the internal precision setting. The missing values are initialised - * to minimal values (0 or 1) for internal calculations. - * - * @param $calendarmodel integer one of SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @param $year integer number of the year (possibly negative) - * @param $month mixed integer number or false - * @param $day mixed integer number or false - * @param $hour mixed integer number or false - * @param $minute mixed integer number or false - * @param $second mixed integer number or false - * - * @todo Implement more validation here. - */ - public function __construct( $calendarmodel, $year, $month = false, $day = false, - $hour = false, $minute = false, $second = false ) { - if ( ( $calendarmodel != self::CM_GREGORIAN ) && ( $calendarmodel != self::CM_JULIAN ) ) { - throw new DataItemException( "Unsupported calendar model constant \"$calendarmodel\"." ); - } - if ( $year == 0 ) { - throw new DataItemException( "There is no year 0 in Gregorian and Julian calendars." ); - } - $this->m_model = $calendarmodel; - $this->m_year = intval( $year ); - $this->m_month = $month != false ? intval( $month ) : 1; - $this->m_day = $day != false ? intval( $day ) : 1; - $this->m_hours = $hour !== false ? intval( $hour ) : 0; - $this->m_minutes = $minute !== false ? intval( $minute ) : 0; - $this->m_seconds = $second !== false ? intval( $second ) : 0; - if ( ( $this->m_hours < 0 ) || ( $this->m_hours > 23 ) || - ( $this->m_minutes < 0 ) || ( $this->m_minutes > 59 ) || - ( $this->m_seconds < 0 ) || ( $this->m_seconds > 59 ) || - ( $this->m_month < 1 ) || ( $this->m_month > 12 ) ) { - throw new DataItemException( "Part of the date is out of bounds." ); - } - if ( $this->m_day > self::getDayNumberForMonth( $this->m_month, $this->m_year, $this->m_model ) ) { - throw new DataItemException( "Month {$this->m_month} in year {$this->m_year} did not have {$this->m_day} days in this calendar model." ); - } - if ( $month === false ) { - $this->m_precision = self::PREC_Y; - } elseif ( $day === false ) { - $this->m_precision = self::PREC_YM; - } elseif ( $hour === false ) { - $this->m_precision = self::PREC_YMD; - } else { - $this->m_precision = self::PREC_YMDT; - } - } - - public function getDIType() { - return SMWDataItem::TYPE_TIME; - } - - public function getCalendarModel() { - return $this->m_model; - } - - public function getPrecision() { - return $this->m_precision; - } - - public function getYear() { - return $this->m_year; - } - - public function getMonth() { - return $this->m_month; - } - - public function getDay() { - return $this->m_day; - } - - public function getHour() { - return $this->m_hours; - } - - public function getMinute() { - return $this->m_minutes; - } - - public function getSecond() { - return $this->m_seconds; - } - - /** - * Creates and returns a new instance of SMWDITime from a MW timestamp. - * - * @since 1.8 - * - * @param string $timestamp must be in format - * - * @return SMWDITime|false - */ - public static function newFromTimestamp( $timestamp ) { - $timestamp = wfTimestamp( TS_MW, (string)$timestamp ); - - if ( $timestamp === false ) { - return false; - } - - return new self( - SMWDITime::CM_GREGORIAN, - substr( $timestamp, 0, 4 ), - substr( $timestamp, 4, 2 ), - substr( $timestamp, 6, 2 ), - substr( $timestamp, 8, 2 ), - substr( $timestamp, 10, 2 ), - substr( $timestamp, 12, 2 ) - ); - } - - /** - * Returns a MW timestamp representatation of the value. - * - * @since 1.6.2 - * - * @param $outputtype - * - * @return mixed - */ - public function getMwTimestamp( $outputtype = TS_UNIX ) { - return wfTimestamp( - $outputtype, - implode( '', array( - str_pad( $this->m_year, 4, '0', STR_PAD_LEFT ), - str_pad( $this->m_month, 2, '0', STR_PAD_LEFT ), - str_pad( $this->m_day, 2, '0', STR_PAD_LEFT ), - str_pad( $this->m_hours, 2, '0', STR_PAD_LEFT ), - str_pad( $this->m_minutes, 2, '0', STR_PAD_LEFT ), - str_pad( $this->m_seconds, 2, '0', STR_PAD_LEFT ), - ) ) - ); - } - - /** - * Get the data in the specified calendar model. This might require - * conversion. - * @note Conversion can be unreliable for very large absolute year - * numbers when the internal calculations hit floating point accuracy. - * Callers might want to avoid this (calendar models make little sense - * in such cases anyway). - * @param $calendarmodel integer one of SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @return SMWDITime - */ - public function getForCalendarModel( $calendarmodel ) { - if ( $calendarmodel == $this->m_model ) { - return $this; - } else { - return self::newFromJD( $this->getJD(), $calendarmodel, $this->m_precision ); - } - } - - /** - * Return a number that helps comparing time data items. For - * dates in the Julian Day era (roughly from 4713 BCE onwards), we use - * the Julian Day number. For earlier dates, the (negative) year number - * with a fraction for the date is used (times are ignored). This - * avoids calculation errors that would occur for very ancient dates - * if the JD number was used there. - * @return double sortkey - */ - public function getSortKey() { - $jd = ( $this->m_year >= -4713 ) ? $jd = $this->getJD() : -1; - if ( $jd > 0 ) { - return $jd; - } else { - return $this->m_year - 1 + ( $this->m_month - 1 ) / 12 + ( $this->m_day - 1 ) / 12 / 31; - } - } - - public function getJD() { - return self::date2JD( $this->m_year, $this->m_month, $this->m_day, $this->m_model ) + - self::time2JDoffset( $this->m_hours, $this->m_minutes, $this->m_seconds ); - } - - public function getSerialization() { - $result = strval( $this->m_model ) . '/' . strval( $this->m_year ); - if ( $this->m_precision >= self::PREC_YM ) { - $result .= '/' . strval( $this->m_month ); - } - if ( $this->m_precision >= self::PREC_YMD ) { - $result .= '/' . strval( $this->m_day ); - } - if ( $this->m_precision >= self::PREC_YMDT ) { - $result .= '/' . strval( $this->m_hours ) . '/' . strval( $this->m_minutes ) . '/' . strval( $this->m_seconds ); - } - return $result; - } - - /** - * Create a data item from the provided serialization string. - * - * @return SMWDITime - */ - public static function doUnserialize( $serialization ) { - $parts = explode( '/', $serialization, 7 ); - $values = array(); - - for ( $i = 0; $i < 7; $i += 1 ) { - if ( $i < count( $parts ) ) { - if ( is_numeric( $parts[$i] ) ) { - $values[$i] = intval( $parts[$i] ); - } else { - throw new DataItemException( "Unserialization failed: the string \"$serialization\" is no valid datetime specification." ); - } - } else { - $values[$i] = false; - } - } - - if ( count( $parts ) <= 1 ) { - throw new DataItemException( "Unserialization failed: the string \"$serialization\" is no valid URI." ); - } - - return new self( $values[0], $values[1], $values[2], $values[3], $values[4], $values[5], $values[6] ); - } - - /** - * Create a new time data item from the specified Julian Day number, - * calendar model, presicion, and type ID. - * @param $jdvalue double Julian Day number - * @param $calendarmodel integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @param $precision integer one of SMWDITime::PREC_Y, SMWDITime::PREC_YM, SMWDITime::PREC_YMD, SMWDITime::PREC_YMDT - * @return SMWDITime object - */ - public static function newFromJD( $jdvalue, $calendarmodel, $precision ) { - list( $year, $month, $day ) = self::JD2Date( $jdvalue, $calendarmodel ); - if ( $precision <= self::PREC_YM ) { - $day = false; - if ( $precision == self::PREC_Y ) { - $month = false; - } - } - if ( $precision == self::PREC_YMDT ) { - list( $hour, $minute, $second ) = self::JD2Time( $jdvalue ); - } else { - $hour = $minute = $second = false; - } - return new SMWDITime( $calendarmodel, $year, $month, $day, $hour, $minute, $second ); - } - - /** - * Compute the Julian Day number from a given date in the specified - * calendar model. This calculation assumes that neither calendar - * has a year 0. - * @param $year integer representing the year - * @param $month integer representing the month - * @param $day integer representing the day - * @param $calendarmodel integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @return float Julian Day number - */ - static public function date2JD( $year, $month, $day, $calendarmodel ) { - $astroyear = ( $year < 1 ) ? ( $year + 1 ) : $year; - if ( $calendarmodel == self::CM_GREGORIAN ) { - $a = intval( ( 14 - $month ) / 12 ); - $y = $astroyear + 4800 - $a; - $m = $month + 12 * $a - 3; - return $day + floor( ( 153 * $m + 2 ) / 5 ) + 365 * $y + floor( $y / 4 ) - floor( $y / 100 ) + floor( $y / 400 ) - 32045.5; - } else { - $y2 = ( $month <= 2 ) ? ( $astroyear - 1 ) : $astroyear; - $m2 = ( $month <= 2 ) ? ( $month + 12 ) : $month; - return floor( ( 365.25 * ( $y2 + 4716 ) ) ) + floor( ( 30.6001 * ( $m2 + 1 ) ) ) + $day - 1524.5; - } - } - - /** - * Compute the offset for the Julian Day number from a given time. - * This computation is the same for all calendar models. - * @param $hours integer representing the hour - * @param $minutes integer representing the minutes - * @param $seconds integer representing the seconds - * @return float offset for a Julian Day number to get this time - */ - static public function time2JDoffset( $hours, $minutes, $seconds ) { - return ( $hours / 24 ) + ( $minutes / ( 60 * 24 ) ) + ( $seconds / ( 3600 * 24 ) ); - } - - /** - * Convert a Julian Day number to a date in the given calendar model. - * This calculation assumes that neither calendar has a year 0. - * @note The algorithm may fail for some cases, in particular since the - * conversion to Gregorian needs positive JD. If this happens, wrong - * values will be returned. Avoid date conversions before 10000 BCE. - * @param $jdvalue float number of Julian Days - * @param $calendarmodel integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @return array( yearnumber, monthnumber, daynumber ) - */ - static public function JD2Date( $jdvalue, $calendarmodel ) { - if ( $calendarmodel == self::CM_GREGORIAN ) { - $jdvalue += 2921940; // add the days of 8000 years (this algorithm only works for positive JD) - $j = floor( $jdvalue + 0.5 ) + 32044; - $g = floor( $j / 146097 ); - $dg = $j % 146097; - $c = floor( ( ( floor( $dg / 36524 ) + 1 ) * 3 ) / 4 ); - $dc = $dg - $c * 36524; - $b = floor( $dc / 1461 ); - $db = $dc % 1461; - $a = floor( ( ( floor( $db / 365 ) + 1 ) * 3 ) / 4 ); - $da = $db - ( $a * 365 ); - $y = $g * 400 + $c * 100 + $b * 4 + $a; - $m = floor( ( $da * 5 + 308 ) / 153 ) - 2; - $d = $da - floor( ( ( $m + 4 ) * 153 ) / 5 ) + 122; - - $year = $y - 4800 + floor( ( $m + 2 ) / 12 ) - 8000; - $month = ( ( $m + 2 ) % 12 + 1 ); - $day = $d + 1; - } else { - $b = floor( $jdvalue + 0.5 ) + 1524; - $c = floor( ( $b - 122.1 ) / 365.25 ); - $d = floor( 365.25 * $c ); - $e = floor( ( $b - $d ) / 30.6001 ); - - $month = floor( ( $e < 14 ) ? ( $e - 1 ) : ( $e - 13 ) ); - $year = floor( ( $month > 2 ) ? ( $c - 4716 ) : ( $c - 4715 ) ); - $day = ( $b - $d - floor( 30.6001 * $e ) ); - } - $year = ( $year < 1 ) ? ( $year - 1 ) : $year; // correct "year 0" to -1 (= 1 BC(E)) - return array( $year, $month, $day ); - } - - /** - * Extract the time from a Julian Day number and return it as a string. - * This conversion is the same for all calendar models. - * @param $jdvalue float number of Julian Days - * @return array( hours, minutes, seconds ) - */ - static public function JD2Time( $jdvalue ) { - $wjd = $jdvalue + 0.5; - $fraction = $wjd - floor( $wjd ); - $time = round( $fraction * 3600 * 24 ); - $hours = floor( $time / 3600 ); - $time = $time - $hours * 3600; - $minutes = floor( $time / 60 ); - $seconds = floor( $time - $minutes * 60 ); - return array( $hours, $minutes, $seconds ); - } - - /** - * Find out whether the given year number is a leap year. - * This calculation assumes that neither calendar has a year 0. - * @param $year integer year number - * @param $calendarmodel integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @return boolean - */ - static public function isLeapYear( $year, $calendarmodel ) { - $astroyear = ( $year < 1 ) ? ( $year + 1 ) : $year; - if ( $calendarmodel == self::CM_JULIAN ) { - return ( $astroyear % 4 ) == 0; - } else { - return ( ( $astroyear % 400 ) == 0 ) || - ( ( ( $astroyear % 4 ) == 0 ) && ( ( $astroyear % 100 ) != 0 ) ); - } - } - - /** - * Find out how many days the given month had in the given year - * based on the specified calendar model. - * This calculation assumes that neither calendar has a year 0. - * @param $month integer month number - * @param $year integer year number - * @param $calendarmodel integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @return boolean - */ - static public function getDayNumberForMonth( $month, $year, $calendarmodel ) { - if ( $month !== 2 ) { - return self::$m_daysofmonths[$month]; - } elseif ( self::isLeapYear( $year, $calendarmodel ) ) { - return 29; - } else { - return 28; - } - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_TIME ) { - return false; - } - - return $di->getSortKey() === $this->getSortKey(); - } -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_URI.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_URI.php deleted file mode 100644 index df8ea214..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_URI.php +++ /dev/null @@ -1,141 +0,0 @@ -<?php - -use SMW\DataItemException; - -/** - * This class implements URI data items. - * - * @since 1.6 - * - * @author Markus Krötzsch - * @ingroup SMWDataItems - */ -class SMWDIUri extends SMWDataItem { - - /** - * URI scheme such as "html" or "mailto". - * @var string - */ - protected $m_scheme; - /** - * "Hierpart" of the URI (usually some authority and path). - * @var string - */ - protected $m_hierpart; - /** - * Query part of the URI. - * @var string - */ - protected $m_query; - /** - * Fragment part of the URI. - * @var string - */ - protected $m_fragment; - - /** - * Initialise a URI by providing its scheme (e.g. "html"), 'hierpart' - * following "scheme:" (e.g. "//username@example.org/path), query (e.g. - * "q=Search+term", and fragment (e.g. "section-one"). The complete URI - * with these examples would be - * http://username@example.org/path?q=Search+term#section-one - * @param $scheme string for the scheme - * @param $hierpart string for the "hierpart" - * @param $query string for the query - * @param $fragment string for the fragment - * - * @todo Implement more validation here. - */ - public function __construct( $scheme, $hierpart, $query, $fragment ) { - if ( ( $scheme === '' ) || ( preg_match( '/[^a-zA-Z]/u', $scheme ) ) ) { - throw new DataItemException( "Illegal URI scheme \"$scheme\"." ); - } - if ( $hierpart === '' ) { - throw new DataItemException( "Illegal URI hierpart \"$hierpart\"." ); - } - $this->m_scheme = $scheme; - $this->m_hierpart = $hierpart; - $this->m_query = $query; - $this->m_fragment = $fragment; - } - - public function getDIType() { - return SMWDataItem::TYPE_URI; - } - - /// @todo This should be changed to the spelling getUri(). - public function getURI() { - $schemesWithDoubleslesh = array( - 'http', 'https', 'ftp' - ); - - $uri = $this->m_scheme . ':' - . ( in_array( $this->m_scheme, $schemesWithDoubleslesh ) ? '//' : '' ) - . $this->m_hierpart - . ( $this->m_query ? '?' . $this->m_query : '' ) - . ( $this->m_fragment ? '#' . $this->m_fragment : '' ); - - return $uri; - } - - public function getScheme() { - return $this->m_scheme; - } - - public function getHierpart() { - return $this->m_hierpart; - } - - public function getQuery() { - return $this->m_query; - } - - public function getFragment() { - return $this->m_fragment; - } - - public function getSortKey() { - return $this->getURI(); - } - - public function getSerialization() { - return $this->getURI(); - } - - /** - * Create a data item from the provided serialization string and type - * ID. - * @return SMWDIUri - */ - public static function doUnserialize( $serialization ) { - $parts = explode( ':', $serialization, 2 ); // try to split "schema:rest" - if ( count( $parts ) <= 1 ) { - throw new DataItemException( "Unserialization failed: the string \"$serialization\" is no valid URI." ); - } - $scheme = $parts[0]; - $parts = explode( '?', $parts[1], 2 ); // try to split "hier-part?queryfrag" - if ( count( $parts ) == 2 ) { - $hierpart = $parts[0]; - $parts = explode( '#', $parts[1], 2 ); // try to split "query#frag" - $query = $parts[0]; - $fragment = ( count( $parts ) == 2 ) ? $parts[1] : ''; - } else { - $query = ''; - $parts = explode( '#', $parts[0], 2 ); // try to split "hier-part#frag" - $hierpart = $parts[0]; - $fragment = ( count( $parts ) == 2 ) ? $parts[1] : ''; - } - - $hierpart = ltrim( $hierpart, '/' ); - - return new SMWDIUri( $scheme, $hierpart, $query, $fragment ); - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_URI ) { - return false; - } - - return $di->getURI() === $this->getURI(); - } -} diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DI_WikiPage.php b/SemanticMediaWiki/includes/dataitems/SMW_DI_WikiPage.php deleted file mode 100644 index c49603e5..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DI_WikiPage.php +++ /dev/null @@ -1,170 +0,0 @@ -<?php - -namespace SMW; - -use SMW\DataItemException; -use SMWDataItem; -use SMWWikiPageValue; -use Title; - -/** - * This class implements wiki page data items. - * - * @since 1.6 - * @ingroup SMWDataItems - * - * @author Markus Krötzsch - */ -class DIWikiPage extends SMWDataItem { - - /** - * MediaWiki DB key string - * @var string - */ - protected $m_dbkey; - /** - * MediaWiki namespace integer. - * @var integer - */ - protected $m_namespace; - /** - * MediaWiki interwiki prefix. - * @var string - */ - protected $m_interwiki; - /** - * Name for subobjects of pages, or empty string if the given object is - * the page itself (not a subobject). - * @var string - */ - protected $m_subobjectname; - - /** - * Contructor. We do not bother with too much detailed validation here, - * regarding the known namespaces, canonicity of the dbkey (namespace - * exrtacted?), validity of interwiki prefix (known?), and general use - * of allowed characters (may depend on MW configuration). All of this - * would be more work than it is worth, since callers will usually be - * careful and since errors here do not have major consequences. - * - * @param string $dbkey - * @param integer $namespace - * @param string $interwiki - * @param string $subobjectname - */ - public function __construct( $dbkey, $namespace, $interwiki = '', $subobjectname = '' ) { - // Check if the provided value holds an integer - // (it can be of type string or float as well, as long as the value is an int) - if ( !ctype_digit( ltrim( (string)$namespace, '-' ) ) ) { - throw new DataItemException( "Given namespace '$namespace' is not an integer." ); - } - - $this->m_dbkey = $dbkey; - $this->m_namespace = (int)$namespace; // really make this an integer - $this->m_interwiki = $interwiki; - $this->m_subobjectname = $subobjectname; - } - - public function getDIType() { - return SMWDataItem::TYPE_WIKIPAGE; - } - - public function getDBkey() { - return $this->m_dbkey; - } - - public function getNamespace() { - return $this->m_namespace; - } - - public function getInterwiki() { - return $this->m_interwiki; - } - - public function getSubobjectName() { - return $this->m_subobjectname; - } - - /** - * Get the sortkey of the wiki page data item. Note that this is not - * the sortkey that might have been set for the corresponding wiki - * page. To obtain the latter, query for the values of the property - * "new SMWDIProperty( '_SKEY' )". - */ - public function getSortKey() { - return $this->m_dbkey; - } - - /** - * Create a MediaWiki Title object for this DIWikiPage. The result - * can be null if an error occurred. - * - * @return Title|null - */ - public function getTitle() { - return Title::makeTitleSafe( - $this->m_namespace, - $this->m_dbkey, - $this->m_subobjectname, - $this->m_interwiki - ); - } - - public function getSerialization() { - $segments = array( - $this->m_dbkey, - $this->m_namespace, - $this->m_interwiki - ); - - if ( $this->m_subobjectname !== '' ) { - $segments[] = $this->m_subobjectname; - } - - return implode( '#', $segments ); - } - - /** - * Create a data item from the provided serialization string and type ID. - * - * @param string $serialization - * - * @return DIWikiPage - * @throws DataItemException - */ - public static function doUnserialize( $serialization ) { - $parts = explode( '#', $serialization, 4 ); - - if ( count( $parts ) == 3 ) { - return new self( $parts[0], intval( $parts[1] ), $parts[2] ); - } elseif ( count( $parts ) == 4 ) { - return new self( $parts[0], intval( $parts[1] ), $parts[2], $parts[3] ); - } else { - throw new DataItemException( "Unserialization failed: the string \"$serialization\" was not understood." ); - } - } - - /** - * Create a data item from a MediaWiki Title. - * - * @param $title Title - * @return DIWikiPage - */ - public static function newFromTitle( Title $title ) { - return new self( - $title->getDBkey(), - $title->getNamespace(), - $title->getInterwiki(), - str_replace( ' ', '_', $title->getFragment() ) - ); - } - - public function equals( SMWDataItem $di ) { - if ( $di->getDIType() !== SMWDataItem::TYPE_WIKIPAGE ) { - return false; - } - - return $di->getSerialization() === $this->getSerialization(); - } -} - diff --git a/SemanticMediaWiki/includes/dataitems/SMW_DataItem.php b/SemanticMediaWiki/includes/dataitems/SMW_DataItem.php deleted file mode 100644 index 4154c0d8..00000000 --- a/SemanticMediaWiki/includes/dataitems/SMW_DataItem.php +++ /dev/null @@ -1,186 +0,0 @@ -<?php -/** - * File holding abstract class SMWDataItem, the base for all dataitems in SMW. - * - * @author Markus Krötzsch - * - * @file - * @ingroup SMWDataItems - */ - -/** - * This group contains all parts of SMW that relate to the processing of dataitems - * of various types. - * - * @defgroup SMWDataItems SMWDataItems - * @ingroup SMW - */ - -/** - * Objects of this type represent all that is known about a certain piece of - * data that could act as the value of some property. Data items only represent - * the stored data, and are thus at the core of SMW's data model. Data items - * are always immutable, i.e. they must not be changed after creation (and this - * is mostly enforced by the API with some minor exceptions). - * - * The set of available data items is fixed and cannot be extended. These are - * the kinds of information that SMW can process. Their concrete use and - * handling might depend on the context in which they are used. In particular, - * property values may be influences by settings made for their property. This - * aspect, however, is not part of the data item API. - * - * @since 1.6 - * - * @ingroup SMWDataItems - */ -abstract class SMWDataItem { - - /// Data item ID that can be used to indicate that no data item class is appropriate - const TYPE_NOTYPE = 0; - /// Data item ID for SMWDINumber - const TYPE_NUMBER = 1; - /** - * Data item ID for SMWDIString. - * @deprecated Will vanish after SMW 1.9; use TYPE_BLOB instead. - */ - const TYPE_STRING = 2; - /// Data item ID for SMWDIBlob - const TYPE_BLOB = 2; - /// Data item ID for SMWDIBoolean - const TYPE_BOOLEAN = 4; - /// Data item ID for SMWDIUri - const TYPE_URI = 5; - /// Data item ID for SMWDITimePoint - const TYPE_TIME = 6; - /// Data item ID for SMWDIGeoCoord - const TYPE_GEO = 7; - /// Data item ID for SMWDIContainer - const TYPE_CONTAINER = 8; - /// Data item ID for SMWDIWikiPage - const TYPE_WIKIPAGE = 9; - /// Data item ID for SMWDIConcept - const TYPE_CONCEPT = 10; - /// Data item ID for SMWDIProperty - const TYPE_PROPERTY = 11; - /// Data item ID for SMWDIError - const TYPE_ERROR = 12; - - /** - * Convenience method that returns a constant that defines the concrete - * class that implements this data item. Used to switch when processing - * data items. - * @return integer that specifies the basic type of data item - */ - abstract public function getDIType(); - - /** - * Return a value that can be used for sorting data of this type. - * If the data is of a numerical type, the sorting must be done in - * numerical order. If the data is a string, the data must be sorted - * alphabetically. - * - * @note Every data item returns a sort key, even if there is no - * natural linear order for the type. SMW must order listed data - * in some way in any case. If there is a natural order (e.g. for - * Booleans where false < true), then the sortkey must agree with - * this order (e.g. for Booleans where false maps to 0, and true - * maps to 1). - * - * @note Wiki pages are a special case in SMW. They are ordered by a - * sortkey that is assigned to them as a property value. When pages are - * sorted, this data should be used if possible. - * - * @return float or string - */ - abstract public function getSortKey(); - - /** - * Method to compare two SMWDataItems - * This should result true only if they are of the same DI type - * and have the same internal value - * - * @since 1.8 - * - * @param SMWDataItem $di - * @return boolean - */ - abstract public function equals( SMWDataItem $di ); - - /** - * Create a data item that represents the sortkey, i.e. either an - * SMWDIBlob or an SMWDINumber. For efficiency, these subclasses - * overwrite this method to return themselves. - * - * @return SMWDataItem - */ - public function getSortKeyDataItem() { - $sortkey = $this->getSortKey(); - if ( is_numeric( $sortkey ) ) { - return new SMWDINumber( $sortkey ); - } else { - return new SMWDIBlob( $sortkey ); - } - } - - /** - * Get a UTF-8 encoded string serialization of this data item. - * The serialisation should be concise and need not be pretty, but it - * must allow unserialization. Each subclass of SMWDataItem implements - * a static method doUnserialize() for this purpose. - * @return string - */ - abstract public function getSerialization(); - - /** - * Get a hash string for this data item. Might be overwritten in - * subclasses to obtain shorter or more efficient hashes. - * - * @return string - */ - public function getHash() { - return $this->getSerialization(); - } - - /** - * Create a data item of the given dataitem ID based on the the - * provided serialization string and (optional) typeid. - * - * @param $diType integer dataitem ID - * @param $serialization string - * @param $typeid string SMW type ID (optional) - * - * @return SMWDataItem - */ - public static function newFromSerialization( $diType, $serialization ) { - $diClass = self::getDataItemClassNameForId( $diType ); - return call_user_func( array( $diClass, 'doUnserialize' ), $serialization ); - } - - /** - * Gets the class name of the data item that has the provided type id. - * - * @param integer $diType Element of the SMWDataItem::TYPE_ enum - * - * @throws InvalidArgumentException - * - * @return string - */ - public static function getDataItemClassNameForId( $diType ) { - switch ( $diType ) { - case self::TYPE_NUMBER: return 'SMWDINumber'; - case self::TYPE_BLOB: return 'SMWDIBlob'; - case self::TYPE_BOOLEAN: return 'SMWDIBoolean'; - case self::TYPE_URI: return 'SMWDIUri'; - case self::TYPE_TIME: return 'SMWDITime'; - case self::TYPE_GEO: return 'SMWDIGeoCoord'; - case self::TYPE_CONTAINER: return 'SMWDIContainer'; - case self::TYPE_WIKIPAGE: return 'SMWDIWikiPage'; - case self::TYPE_CONCEPT: return 'SMWDIConcept'; - case self::TYPE_PROPERTY: return 'SMWDIProperty'; - case self::TYPE_ERROR: return 'SMWDIError'; - case self::TYPE_NOTYPE: default: - throw new InvalidArgumentException( "The value \"$diType\" is not a valid dataitem ID." ); - } - } - -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Bool.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Bool.php deleted file mode 100644 index 8c538346..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Bool.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements Boolean datavalues. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWBoolValue extends SMWDataValue { - - /** - * The text to write for "true" if a custom output format was set. - * @var string - */ - protected $m_truecaption; - - /** - * The text to write for "false" if a custom output format was set. - * @var string - */ - protected $m_falsecaption; - - protected function parseUserValue( $value ) { - $value = trim( $value ); - if ( $this->m_caption === false ) { - $this->m_caption = $value; - } - - $lcv = strtolower( $value ); - $boolvalue = false; - if ( $lcv === '1' ) { - $boolvalue = true; - } elseif ( $lcv === '0' ) { - $boolvalue = false; - } elseif ( in_array( $lcv, explode( ',', wfMessage( 'smw_true_words' )->inContentLanguage()->text() ), true ) ) { - $boolvalue = true; - } elseif ( in_array( $lcv, explode( ',', wfMessage( 'smw_false_words' )->inContentLanguage()->text() ), true ) ) { - $boolvalue = false; - } else { - $this->addError( wfMessage( 'smw_noboolean', $value )->inContentLanguage()->text() ); - } - $this->m_dataitem = new SMWDIBoolean( $boolvalue, $this->m_typeid ); - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_BOOLEAN ) { - $this->m_dataitem = $dataItem; - $this->m_caption = $this->getStandardCaption( true ); // use default for this language - return true; - } else { - return false; - } - } - - public function setOutputFormat( $formatstring ) { - if ( $formatstring == $this->m_outformat ) return; - unset( $this->m_truecaption ); - unset( $this->m_falsecaption ); - if ( $formatstring === '' ) { // no format - // (unsetting the captions is exactly the right thing here) - } elseif ( strtolower( $formatstring ) == '-' ) { // "plain" format - $this->m_truecaption = 'true'; - $this->m_falsecaption = 'false'; - } elseif ( strtolower( $formatstring ) == 'x' ) { // X format - $this->m_truecaption = '<span style="font-family: sans-serif; ">X</span>'; - $this->m_falsecaption = ''; - } else { // format "truelabel, falselabel" (hopefully) - $captions = explode( ',', $formatstring, 2 ); - if ( count( $captions ) == 2 ) { // note: escaping needed to be safe; MW-sanitising would be an alternative - $this->m_truecaption = htmlspecialchars( trim( $captions[0] ) ); - $this->m_falsecaption = htmlspecialchars( trim( $captions[1] ) ); - } // else: no format that is recognised, ignore - } - $this->m_caption = $this->getStandardCaption( true ); - $this->m_outformat = $formatstring; - } - - public function getShortWikiText( $linked = null ) { - return $this->m_caption; - } - - public function getShortHTMLText( $linker = null ) { - return $this->m_caption; - } - - public function getLongWikiText( $linked = null ) { - return $this->isValid() ? $this->getStandardCaption( true ) : $this->getErrorText(); - } - - public function getLongHTMLText( $linker = null ) { - return $this->isValid() ? $this->getStandardCaption( true ) : $this->getErrorText(); - } - - public function getWikiValue() { - return $this->getStandardCaption( false ); - } - - public function getBoolean() { - return $this->m_dataitem->getBoolean(); - } - - /** - * Get text for displaying the value of this property, or false if not - * valid. - * @param $useformat bool, true if the output format should be used, false if the returned text should be parsable - * @return string - */ - protected function getStandardCaption( $useformat ) { - if ( !$this->isValid() ) return false; - if ( $useformat && ( isset( $this->m_truecaption ) ) ) { - return $this->m_dataitem->getBoolean() ? $this->m_truecaption : $this->m_falsecaption; - } else { - $vals = explode( - ',', - wfMessage( - $this->m_dataitem->getBoolean() ? 'smw_true_words' : 'smw_false_words' - )->inContentLanguage()->text() - ); - return reset( $vals ); - } - } -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Concept.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Concept.php deleted file mode 100644 index fdccf5b1..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Concept.php +++ /dev/null @@ -1,190 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue is used as a container for concept descriptions as used - * on Concept pages with the #concept parserfunction. It has a somewhat - * non-standard interface as compared to other datavalues, but this is not - * an issue. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWConceptValue extends SMWDataValue { - - protected function parseUserValue( $value ) { - throw new Exception( 'Concepts cannot be initialized from user-provided strings. This should not happen.' ); - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_CONCEPT ) { - $this->m_dataitem = $dataItem; - $this->m_caption = $dataItem->getConceptQuery(); // probably useless - return true; - } else { - return false; - } - } - - protected function clear() { - $this->m_dataitem = new \SMW\DIConcept( '', '', 0, -1, -1, $this->m_typeid ); - } - - public function getShortWikiText( $linked = null ) { - return $this->m_caption; - } - - public function getShortHTMLText( $linker = null ) { - return $this->getShortWikiText( $linker ); // should be save (based on xsdvalue) - } - - public function getLongWikiText( $linked = null ) { - if ( !$this->isValid() ) { - return $this->getErrorText(); - } else { - return $this->m_caption; - } - } - - public function getLongHTMLText( $linker = null ) { - if ( !$this->isValid() ) { - return $this->getErrorText(); - } else { - return $this->m_caption; // should be save (based on xsdvalue) - } - } - - public function getWikiValue() { - /// This should not be used for anything. This class does not support wiki values. - return str_replace( array( '<', '>', '&' ), array( '<', '>', '&' ), $this->m_dataitem->getConceptQuery() ); - } - - /** - * Function not called anywhere but code kept for reference before - * migrating it to SMWExporter. - */ - private function getExportData() { - if ( $this->isValid() ) { - $qp = new SMWQueryParser(); - $desc = $qp->getQueryDescription( str_replace( array( '<', '>', '&' ), array( '<', '>', '&' ), $this->m_dataitem->getConceptQuery() ) ); - $exact = true; - $owldesc = $this->descriptionToExpData( $desc, $exact ); - if ( !$exact ) { - $result = new SMWExpData( new SMWExpResource( '' ) ); - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdf', 'type' ), - new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Class' ) ) ); - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdfs', 'subClassOf' ), $owldesc ); - return $result; - } else { - return $owldesc; - } - } else { - return null; - } - } - - public function descriptionToExpData( $desc, &$exact ) { - if ( ( $desc instanceof SMWConjunction ) || ( $desc instanceof SMWDisjunction ) ) { - $result = new SMWExpData( new SMWExpResource( '' ) ); - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdf', 'type' ), - new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Class' ) ) ); - $elements = array(); - foreach ( $desc->getDescriptions() as $subdesc ) { - $element = $this->descriptionToExpData( $subdesc, $exact ); - if ( $element === false ) { - $element = new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Thing' ) ); - } - $elements[] = $element; - } - $prop = ( $desc instanceof SMWConjunction ) ? 'intersectionOf':'unionOf'; - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'owl', $prop ), - SMWExpData::makeCollection( $elements ) ); - } elseif ( $desc instanceof SMWClassDescription ) { - if ( count( $desc->getCategories() ) == 1 ) { // single category - $result = new SMWExpData( SMWExporter::getResourceElement( end( $desc->getCategories() ) ) ); - } else { // disjunction of categories - $result = new SMWExpData( new SMWExpResource( '' ) ); - $elements = array(); - foreach ( $desc->getCategories() as $cat ) { - $elements[] = new SMWExpData( SMWExporter::getResourceElement( $cat ) ); ; - } - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'owl', 'unionOf' ), - SMWExpData::makeCollection( $elements ) ); - } - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdf', 'type' ), - new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Class' ) ) ); - } elseif ( $desc instanceof SMWConceptDescription ) { - $result = new SMWExpData( SMWExporter::getResourceElement( $desc->getConcept() ) ); - } elseif ( $desc instanceof SMWSomeProperty ) { - $result = new SMWExpData( new SMWExpResource( '' ) ); - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdf', 'type' ), - new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Restriction' ) ) ); - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'owl', 'onProperty' ), - new SMWExpData( SMWExporter::getResourceElement( $desc->getProperty() ) ) ); - $subdata = $this->descriptionToExpData( $desc->getDescription(), $exact ); - if ( ( $desc->getDescription() instanceof SMWValueDescription ) && - ( $desc->getDescription()->getComparator() == SMW_CMP_EQ ) ) { - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'owl', 'hasValue' ), $subdata ); - } else { - if ( $subdata === false ) { - $owltype = SMWExporter::getOWLPropertyType( $desc->getProperty()->getPropertyTypeID() ); - if ( $owltype == 'ObjectProperty' ) { - $subdata = new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Thing' ) ); - } elseif ( $owltype == 'DatatypeProperty' ) { - $subdata = new SMWExpData( SMWExporter::getSpecialNsResource( 'rdfs', 'Literal' ) ); - } else { // no restrictions at all with annotation properties ... - return new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Thing' ) ); - } - } - $result->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'owl', 'someValuesFrom' ), $subdata ); - } - } elseif ( $desc instanceof SMWValueDescription ) { - if ( $desc->getComparator() == SMW_CMP_EQ ) { - $result = SMWExporter::getDataItemExpElement( $desc->getDataItem() ); - } else { // alas, OWL cannot represent <= and >= ... - $exact = false; - $result = false; - } - } elseif ( $desc instanceof SMWThingDescription ) { - $result = false; - } else { - $result = false; - $exact = false; - } - return $result; - } - - /// Return the concept's defining text (in SMW query syntax) - public function getConceptText() { - return $this->m_dataitem->getConceptQuery(); - } - - /// Return the optional concept documentation. - public function getDocu() { - return $this->m_dataitem->getDocumentation(); - } - - /// Return the concept's size (a metric used to estimate computation complexity). - public function getSize() { - return $this->m_dataitem->getSize(); - } - - /// Return the concept's depth (a metric used to estimate computation complexity). - public function getDepth() { - return $this->m_dataitem->getDepth(); - } - - /// Return the concept's query feature bit field (a metric used to estimate computation complexity). - public function getQueryFeatures() { - return $this->m_dataitem->getQueryFeatures(); - } - -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Error.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Error.php deleted file mode 100644 index 216d0de7..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Error.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements error datavalues, a kind of pseudo data value that - * is used in places where a data value is expected but no more meaningful - * value could be created. It is always invalid and never gets stored or - * exported, but it can help to transport an error message. - * - * @note SMWDataValue will return a data item of type SMWDIError for invalid - * data values. Hence this is the DI type of this DV, even if not mentioned in - * this file. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWErrorValue extends SMWDataValue { - - public function __construct( $typeid, $errormsg = '', $uservalue = '', $caption = false ) { - parent::__construct( $typeid ); - $this->m_caption = ( $caption !== false ) ? $caption : $uservalue; - if ( $errormsg !== '' ) { - $this->addError( $errormsg ); - } - } - - protected function parseUserValue( $value ) { - if ( $this->m_caption === false ) { - $this->m_caption = $value; - } - $this->addError( wfMessage( 'smw_parseerror' )->inContentLanguage()->text() ); - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_ERROR ) { - $this->addError( $dataItem->getErrors() ); - $this->m_caption = $this->getErrorText(); - return true; - } else { - return false; - } - } - - public function getShortWikiText( $linked = null ) { - return $this->m_caption; - } - - public function getShortHTMLText( $linker = null ) { - return htmlspecialchars( $this->getShortWikiText( $linker ) ); - } - - public function getLongWikiText( $linked = null ) { - return $this->getErrorText(); - } - - public function getLongHTMLText( $linker = null ) { - return $this->getErrorText(); - } - - public function getWikiValue() { - return $this->m_dataitem->getString(); - } - - public function isValid() { - return false; - } - -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Import.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Import.php deleted file mode 100644 index d8ff473e..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Import.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements datavalues used by special property '_IMPO' used - * for assigning imported vocabulary to some page of the wiki. It looks up a - * MediaWiki message to find out whether a user-supplied vocabulary name can be - * imported in the wiki, and whether its declaration is correct (to the extent - * that this can be checked). - * - * @author Fabian Howahl - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWImportValue extends SMWDataValue { - - protected $m_qname = ''; // string provided by user which is used to look up data on Mediawiki:*-Page - protected $m_uri = ''; // URI of namespace (without local name) - protected $m_namespace = ''; // namespace id (e.g. "foaf") - protected $m_section = ''; // local name (e.g. "knows") - protected $m_name = ''; // wiki name of the vocab (e.g. "Friend of a Friend")l might contain wiki markup - - protected function parseUserValue( $value ) { - global $wgContLang; - - $this->m_qname = $value; - - list( $onto_ns, $onto_section ) = explode( ':', $this->m_qname, 2 ); - $msglines = preg_split( "([\n][\s]?)", wfMessage( "smw_import_$onto_ns" )->inContentLanguage()->text() ); // get the definition for "$namespace:$section" - - if ( count( $msglines ) < 2 ) { // error: no elements for this namespace - $this->addError( wfMessage( 'smw_unknown_importns', $onto_ns )->inContentLanguage()->text() ); - $this->m_dataitem = new SMWDIBlob( 'ERROR' ); - return; - } - - // browse list in smw_import_* for section - list( $onto_uri, $onto_name ) = explode( '|', array_shift( $msglines ), 2 ); - if ( $onto_uri[0] == ' ' ) $onto_uri = mb_substr( $onto_uri, 1 ); // tolerate initial space - - $this->m_uri = $onto_uri; - $this->m_namespace = $onto_ns; - $this->m_section = $onto_section; - $this->m_name = $onto_name; - - foreach ( $msglines as $msgline ) { - list( $secname, $typestring ) = explode( '|', $msgline, 2 ); - if ( $secname === $onto_section ) { - list( $namespace, ) = explode( ':', $typestring, 2 ); - // check whether type matches - switch ( $namespace ) { - case $wgContLang->getNsText( SMW_NS_TYPE ): - $elemtype = SMW_NS_PROPERTY; - break; - case $wgContLang->getNsText( SMW_NS_PROPERTY ): - $elemtype = SMW_NS_PROPERTY; - break; - case $wgContLang->getNsText( NS_CATEGORY ): - $elemtype = NS_CATEGORY; - break; - case $wgContLang->getNsText( SMW_NS_CONCEPT ): - $elemtype = NS_CATEGORY; - break; - default: // match all other namespaces - $elemtype = NS_MAIN; - } - break; - } - } - - $this->m_dataitem = new SMWDIBlob( $this->m_namespace . ' ' . $this->m_section . ' ' . $this->m_uri ); - - // check whether caption is set, otherwise assign link statement to caption - if ( $this->m_caption === false ) { - $this->m_caption = "[" . $this->m_uri . " " . $this->m_qname . "] (" . $this->m_name . ")"; - } - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem instanceof SMWDIBlob ) { - $this->m_dataitem = $dataItem; - $parts = explode( ' ', $dataItem->getString(), 3 ); - if ( count( $parts ) != 3 ) { - $this->addError( wfMessage( 'smw_parseerror' )->inContentLanguage()->text() ); - } else { - $this->m_namespace = $parts[0]; - $this->m_section = $parts[1]; - $this->m_uri = $parts[2]; - $this->m_qname = $this->m_namespace . ':' . $this->m_section; - $this->m_caption = "[" . $this->m_uri . " " . $this->m_qname . "] (" . $this->m_name . ")"; - } - return true; - } else { - return false; - } - } - - public function getShortWikiText( $linked = null ) { - return $this->m_caption; - } - - public function getShortHTMLText( $linker = null ) { - return htmlspecialchars( $this->m_qname ); - } - - public function getLongWikiText( $linked = null ) { - if ( !$this->isValid() ) { - return $this->getErrorText(); - } else { - return "[" . $this->m_uri . " " . $this->m_qname . "] (" . $this->m_name . ")"; - } - } - - public function getLongHTMLText( $linker = null ) { - if ( !$this->isValid() ) { - return $this->getErrorText(); - } else { - return htmlspecialchars( $this->m_qname ); - } - } - - public function getWikiValue() { - return $this->m_qname; - } - - public function getNS() { - return $this->m_uri; - } - - public function getNSID() { - return $this->m_namespace; - } - - public function getLocalName() { - return $this->m_section; - } -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Number.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Number.php deleted file mode 100644 index 089302f8..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Number.php +++ /dev/null @@ -1,332 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements numerical datavalues, and supports optional - * unit conversions. It parses and manages unit strings, since even plain - * numbers may have (not further specified) units that are stored. However, - * only subclasses implement full unit conversion by extending the methods - * convertToMainUnit() and makeConversionValues(). - * - * Units work as follows: a unit is a string, but many such strings might - * refer to the same unit of measurement. There is always one string, that - * canonically represents the unit, and we will call this version of writing - * the unit the /unit id/. IDs for units are needed for tasks like duplicate - * avoidance. If no conversion information is given, any unit is its own ID. - * In any case, units are /normalised/, i.e. given a more standardised meaning - * before being processed. All units, IDs or otherwise, should be suitable for - * printout in wikitext, and main IDs should moreover be suitable for printout - * in HTML. - * - * Subclasses that support unit conversion may interpret the output format set - * via setOutputFormat() to allow a unit to be selected for display. Note that - * this setting does not affect the internal representation of the value - * though. So chosing a specific output format will change the behavior of - * output functions like getLongWikiText(), but not of functions that access - * the value itself, such as getUnit() or getDBKeys(). - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - * - * @todo Wiki-HTML-conversion for unit strings must be revisited, as the current - * solution might be unsafe. - */ -class SMWNumberValue extends SMWDataValue { - - /** - * Array with entries unit=>value, mapping a normalized unit to the - * converted value. Used for conversion tooltips. - * @var array - */ - protected $m_unitvalues; - - /** - * Canonical identifier for the unit that the user gave as input. Used - * to avoid printing this in conversion tooltips again. If the - * outputformat was set to show another unit, then the values of - * $m_caption and $m_unitin will be updated as if the formatted string - * had been the original user input, i.e. the two values reflect what - * is currently printed. - * @var string - */ - protected $m_unitin; - - /** - * Parse a string of the form "number unit" where unit is optional. The - * results are stored in the $number and $unit parameters. Returns an - * error code. - * @param $value string to parse - * @param $number call-by-ref parameter that will be set to the numerical value - * @param $unit call-by-ref parameter that will be set to the "unit" string (after the number) - * @return integer 0 (no errors), 1 (no number found at all), 2 (number - * too large for this platform) - */ - static protected function parseNumberValue( $value, &$number, &$unit ) { - // Parse to find $number and (possibly) $unit - $decseparator = wfMessage( 'smw_decseparator' )->inContentLanguage()->text(); - $kiloseparator = wfMessage( 'smw_kiloseparator' )->inContentLanguage()->text(); - - $parts = preg_split( '/([-+]?\s*\d+(?:\\' . $kiloseparator . '\d\d\d)*' . - '(?:\\' . $decseparator . '\d+)?\s*(?:[eE][-+]?\d+)?)/u', - trim( str_replace( array( ' ', ' ', ' ', ' ' ), '', $value ) ), - 2, PREG_SPLIT_DELIM_CAPTURE ); - - if ( count( $parts ) >= 2 ) { - $numstring = str_replace( $kiloseparator, '', preg_replace( '/\s*/u', '', $parts[1] ) ); // simplify - if ( $decseparator != '.' ) { - $numstring = str_replace( $decseparator, '.', $numstring ); - } - list( $number ) = sscanf( $numstring, "%f" ); - if ( count( $parts ) >= 3 ) { - $unit = self::normalizeUnit( $parts[2] ); - } - } - - if ( ( count( $parts ) == 1 ) || ( $numstring === '' ) ) { // no number found - return 1; - } elseif ( is_infinite( $number ) ) { // number is too large for this platform - return 2; - } else { - return 0; - } - } - - protected function parseUserValue( $value ) { - // Set caption - if ( $this->m_caption === false ) { - $this->m_caption = $value; - } - $this->m_unitin = false; - $this->m_unitvalues = false; - $number = $unit = ''; - $error = self::parseNumberValue( $value, $number, $unit ); - if ( $error == 1 ) { // no number found - $this->addError( wfMessage( 'smw_nofloat', $value )->inContentLanguage()->text() ); - } elseif ( $error == 2 ) { // number is too large for this platform - $this->addError( wfMessage( 'smw_infinite', $value )->inContentLanguage()->text() ); - } elseif ( $this->convertToMainUnit( $number, $unit ) === false ) { // so far so good: now convert unit and check if it is allowed - $this->addError( wfMessage( 'smw_unitnotallowed', $unit )->inContentLanguage()->text() ); - } // note that convertToMainUnit() also sets m_dataitem if valid - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_NUMBER ) { - $this->m_dataitem = $dataItem; - $this->m_caption = false; - $this->m_unitin = false; - $this->makeUserValue(); - $this->m_unitvalues = false; - return true; - } else { - return false; - } - } - - public function setOutputFormat( $formatstring ) { - if ( $formatstring != $this->m_outformat ) { - $this->m_outformat = $formatstring; - if ( $this->isValid() ) { // update caption/unitin for this format - $this->m_caption = false; - $this->m_unitin = false; - $this->makeUserValue(); - } - } - } - - public function getShortWikiText( $linked = null ) { - if ( is_null( $linked ) || ( $linked === false ) || ( $this->m_outformat == '-' ) - || ( $this->m_outformat == '-u' ) || ( $this->m_outformat == '-n' ) || ( !$this->isValid() ) ) { - return $this->m_caption; - } else { - $this->makeConversionValues(); - $tooltip = ''; - $i = 0; - $sep = ''; - foreach ( $this->m_unitvalues as $unit => $value ) { - if ( $unit != $this->m_unitin ) { - $tooltip .= $sep . smwfNumberFormat( $value ); - if ( $unit !== '' ) { - $tooltip .= ' ' . $unit; - } - $sep = ' <br />'; - $i++; - if ( $i >= 5 ) { // limit number of printouts in tooltip - break; - } - } - } - if ( $tooltip !== '' ) { - $highlighter = SMW\Highlighter::factory( SMW\Highlighter::TYPE_QUANTITY ); - $highlighter->setContent( array ( - 'caption' => $this->m_caption, - 'content' => $tooltip - ) ); - - return $highlighter->getHtml(); - } else { - return $this->m_caption; - } - } - } - - public function getShortHTMLText( $linker = null ) { - return $this->getShortWikiText( $linker ); - } - - public function getLongWikiText( $linked = null ) { - if ( !$this->isValid() ) { - return $this->getErrorText(); - } else { - $this->makeConversionValues(); - $result = ''; - $i = 0; - foreach ( $this->m_unitvalues as $unit => $value ) { - if ( $i == 1 ) { - $result .= ' ('; - } elseif ( $i > 1 ) { - $result .= ', '; - } - $result .= ( $this->m_outformat != '-' ? smwfNumberFormat( $value ) : $value ); - if ( $unit !== '' ) { - $result .= ' ' . $unit; - } - $i++; - if ( $this->m_outformat == '-' ) { // no further conversions for plain output format - break; - } - } - if ( $i > 1 ) { - $result .= ')'; - } - return $result; - } - } - - public function getLongHTMLText( $linker = null ) { - return $this->getLongWikiText( $linker ); - } - - public function getNumber() { - return $this->isValid() ? $this->m_dataitem->getNumber() : 32202; - } - - public function getWikiValue() { - if ( $this->isValid() ) { - $unit = $this->getUnit(); - return smwfNumberFormat( $this->m_dataitem->getSerialization() ) . ( $unit !== '' ? ' ' . $unit : '' ); - } else { - return 'error'; - } - } - - /** - * Return the unit in which the returned value is to be interpreted. - * This string is a plain UTF-8 string without wiki or html markup. - * The returned value is a canonical ID for the main unit. - * Returns the empty string if no unit is given for the value. - * Overwritten by subclasses that support units. - */ - public function getUnit() { - return ''; - } - - /** - * Create links to mapping services based on a wiki-editable message. - * The parameters available to the message are: - * $1: string of numerical value in English punctuation - * $2: string of integer version of value, in English punctuation - * - * @return array - */ - protected function getServiceLinkParams() { - if ( $this->isValid() ) { - return array( strval( $this->m_dataitem->getNumber() ), strval( round( $this->m_dataitem->getNumber() ) ) ); - } else { - return array(); - } - } - - /** - * Transform a (typically unit-) string into a normalised form, - * so that, e.g., "km²" and "km<sup>2</sup>" do not need to be - * distinguished. - */ - static protected function normalizeUnit( $unit ) { - $unit = str_replace( array( '[[', ']]' ), '', trim( $unit ) ); // allow simple links to be used inside annotations - $unit = str_replace( array( '²', '<sup>2</sup>' ), '²', $unit ); - $unit = str_replace( array( '³', '<sup>3</sup>' ), '³', $unit ); - return smwfXMLContentEncode( $unit ); - } - - /** - * Compute the value based on the given input number and unit string. - * If the unit is not supported, return false, otherwise return true. - * This is called when parsing user input, where the given unit value - * has already been normalized. - * - * This class does not support any (non-empty) units, but subclasses - * may overwrite this behavior. - * @param $number float value obtained by parsing user input - * @param $unit string after the numericla user input - * @return boolean specifying if the unit string is allowed - */ - protected function convertToMainUnit( $number, $unit ) { - $this->m_dataitem = new SMWDINumber( $number ); - $this->m_unitin = ''; - return ( $unit === '' ); - } - - /** - * This method creates an array of unit-value-pairs that should be - * printed. Units are the keys and should be canonical unit IDs. - * The result is stored in $this->m_unitvalues. Again, any class that - * requires effort for doing this should first check whether the array - * is already set (i.e. not false) before doing any work. - * Note that the values should be plain numbers. Output formatting is done - * later when needed. Also, it should be checked if the value is valid - * before trying to calculate with its contents. - * This method also must call or implement convertToMainUnit(). - * - * Overwritten by subclasses that support units. - */ - protected function makeConversionValues() { - $this->m_unitvalues = array( '' => $this->m_dataitem->getNumber() ); - } - - /** - * This method is used when no user input was given to find the best - * values for m_unitin and m_caption. After conversion, - * these fields will look as if they were generated from user input, - * and convertToMainUnit() will have been called (if not, it would be - * blocked by the presence of m_unitin). - * - * Overwritten by subclasses that support units. - */ - protected function makeUserValue() { - $this->m_caption = ''; - if ( $this->m_outformat != '-u' ) { // -u is the format for displaying the unit only - $this->m_caption .= ( ( $this->m_outformat != '-' ) && ( $this->m_outformat != '-n' ) ? smwfNumberFormat( $this->m_dataitem->getNumber() ) : $this->m_dataitem->getNumber() ); - } - // no unit ever, so nothing to do about this - $this->m_unitin = ''; - } - - /** - * Return an array of major unit strings (ids only recommended) supported by - * this datavalue. - * - * Overwritten by subclasses that support units. - */ - public function getUnitList() { - return array( '' ); - } - -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Property.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Property.php deleted file mode 100644 index b67f08fe..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Property.php +++ /dev/null @@ -1,352 +0,0 @@ -<?php -/** - * File holding class SMWPropertyValue. - * - * @author Markus Krötzsch - * - * @file - * @ingroup SMWDataValues - */ - -/** - * Objects of this class represent properties in SMW. - * - * This class represents both normal (user-defined) properties and - * predefined ("special") properties. Predefined properties may still - * have a standard label (and associated wiki article) and they will - * behave just like user-defined properties in most cases (e.g. when - * asking for a printout text, a link to the according page is produced). - * It is possible that predefined properties have no visible label at all, - * if they are used only internally and never specified by or shown to - * the user. Those will use their internal ID as DB key, and - * empty texts for most printouts. All other proeprties use their - * canonical DB key (even if they are predefined and have an id). - * Functions are provided to check whether a property is visible or - * user-defined, and to get the internal ID, if any. - * - * @note This datavalue is used only for representing properties and, - * possibly objects/values, but never for subjects (pages as such). Hence - * it does not provide a complete Title-like interface, or support for - * things like sortkey. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWPropertyValue extends SMWDataValue { - - /** - * Cache for wiki page value object associated to this property, or - * null if no such page exists. Use getWikiPageValue() to get the data. - * @var SMWWikiPageValue - */ - protected $m_wikipage = null; - - /** - * Cache for type value of this property, or null if not calculated yet. - * @var SMWTypesValue - */ - private $mPropTypeValue; - - /** - * Static function for creating a new property object from a - * propertyname (string) as a user might enter it. - * @note The resulting property object might be invalid if - * the provided name is not allowed. An object is returned - * in any case. - * - * @param string $propertyName - * - * @return SMWPropertyValue - */ - static public function makeUserProperty( $propertyName ) { - $property = new SMWPropertyValue( '__pro' ); - $property->setUserValue( $propertyName ); - return $property; - } - - /** - * Static function for creating a new property object from a property - * identifier (string) as it might be used internally. This might be - * the DB key version of some property title text or the id of a - * predefined property (such as '_TYPE'). - * @note This function strictly requires an internal identifier, i.e. - * predefined properties must be referred to by their ID, and '-' is - * not supported for indicating inverses. - * @note The resulting property object might be invalid if - * the provided name is not allowed. An object is returned - * in any case. - */ - static public function makeProperty( $propertyid ) { - $diProperty = new SMWDIProperty( $propertyid ); - $dvProperty = new SMWPropertyValue( '__pro' ); - $dvProperty->setDataItem( $diProperty ); - return $dvProperty; - } - - /** - * We use the internal wikipage object to store some of this objects data. - * Clone it to make sure that data can be modified independently from the - * original object's content. - */ - public function __clone() { - if ( !is_null( $this->m_wikipage ) ) $this->m_wikipage = clone $this->m_wikipage; - } - - /** - * Extended parsing function to first check whether value refers to pre-defined - * property, resolve aliases, and set internal property id accordingly. - * @todo Accept/enforce property namespace. - */ - protected function parseUserValue( $value ) { - $this->mPropTypeValue = null; - $this->m_wikipage = null; - - if ( $this->m_caption === false ) { // always use this as caption - $this->m_caption = $value; - } - $propertyName = smwfNormalTitleText( ltrim( rtrim( $value, ' ]' ), ' [' ) ); // slightly normalise label - $inverse = false; - if ( ( $propertyName !== '' ) && ( $propertyName { 0 } == '-' ) ) { // property refers to an inverse - $propertyName = smwfNormalTitleText( (string)substr( $value, 1 ) ); - /// NOTE The cast is necessary at least in PHP 5.3.3 to get string '' instead of boolean false. - /// NOTE It is necessary to normalize again here, since normalization may uppercase the first letter. - $inverse = true; - } - - try { - $this->m_dataitem = SMWDIProperty::newFromUserLabel( $propertyName, $inverse, $this->m_typeid ); - } catch ( SMWDataItemException $e ) { // happens, e.g., when trying to sort queries by property "-" - $this->addError( wfMessage( 'smw_noproperty', $value )->inContentLanguage()->text() ); - $this->m_dataitem = new SMWDIProperty( 'ERROR', false ); // just to have something - } - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_PROPERTY ) { - $this->m_dataitem = $dataItem; - $this->mPropTypeValue = null; - unset( $this->m_wikipage ); - $this->m_caption = false; - return true; - } else { - return false; - } - } - - public function setCaption( $caption ) { - parent::setCaption( $caption ); - if ( $this->getWikiPageValue() instanceof SMWDataValue ) { // pass caption to embedded datavalue (used for printout) - $this->m_wikipage->setCaption( $caption ); - } - } - - public function setOutputFormat( $formatstring ) { - $this->m_outformat = $formatstring; - if ( $this->m_wikipage instanceof SMWDataValue ) { - $this->m_wikipage->setOutputFormat( $formatstring ); - } - } - - public function setInverse( $isinverse ) { - return $this->m_dataitem = new SMWDIProperty( $this->m_dataitem->getKey(), ( $isinverse == true ) ); - } - - /** - * Return a wiki page value that can be used for displaying this - * property, or null if no such wiki page exists (for predefined - * properties without any label). - * @return SMWWikiPageValue or null - */ - public function getWikiPageValue() { - if ( !isset( $this->m_wikipage ) ) { - $diWikiPage = $this->m_dataitem->getDiWikiPage(); - if ( !is_null( $diWikiPage ) ) { - $this->m_wikipage = \SMW\DataValueFactory::getInstance()->newDataItemValue( $diWikiPage, null, $this->m_caption ); - $this->m_wikipage->setOutputFormat( $this->m_outformat ); - $this->addError( $this->m_wikipage->getErrors() ); - } else { // should rarely happen ($value is only changed if the input $value really was a label for a predefined prop) - $this->m_wikipage = null; - } - } - return $this->m_wikipage; - } - - /** - * Return TRUE if this is a property that can be displayed, and not a pre-defined - * property that is used only internally and does not even have a user-readable name. - * @note Every user defined property is necessarily visible. - */ - public function isVisible() { - return $this->isValid() && ( $this->m_dataitem->isUserDefined() || $this->m_dataitem->getLabel() !== '' ); - } - - public function getShortWikiText( $linked = null ) { - if ( $this->isVisible() ) { - $wikiPageValue = $this->getWikiPageValue(); - return is_null( $wikiPageValue ) ? '' : $this->highlightText( $wikiPageValue->getShortWikiText( $linked ) ); - } else { - return ''; - } - } - - public function getShortHTMLText( $linked = null ) { - if ( $this->isVisible() ) { - $wikiPageValue = $this->getWikiPageValue(); - return is_null( $wikiPageValue ) ? '' : $this->highlightText( $wikiPageValue->getShortHTMLText( $linked ) ); - } else { - return ''; - } - } - - public function getLongWikiText( $linked = null ) { - if ( $this->isVisible() ) { - $wikiPageValue = $this->getWikiPageValue(); - return is_null( $wikiPageValue ) ? '' : $this->highlightText( $wikiPageValue->getLongWikiText( $linked ) ); - } else { - return ''; - } - } - - public function getLongHTMLText( $linked = null ) { - if ( $this->isVisible() ) { - $wikiPageValue = $this->getWikiPageValue(); - return is_null( $wikiPageValue ) ? '' : $this->highlightText( $wikiPageValue->getLongHTMLText( $linked ) ); - } else { - return ''; - } - } - - public function getWikiValue() { - return $this->isVisible() ? $this->m_dataitem->getLabel() : ''; - } - - /** - * If this property was not user defined, return the internal ID string referring to - * that property. Otherwise return FALSE; - */ - public function getPropertyID() { - return $this->m_dataitem->isUserDefined() ? false : $this->m_dataitem->getKey(); - } - - /** - * Return an SMWTypesValue object representing the datatype of this - * property. - * @deprecated Types values are not a good way to exchange SMW type information. They are for input only. Use getPropertyTypeID() if you want the type id. This method will vanish in SMW 1.7. - */ - public function getTypesValue() { - $result = SMWTypesValue::newFromTypeId( $this->getPropertyTypeID() ); - if ( !$this->isValid() ) { - $result->addError( $this->getErrors() ); - } - return $result; - } - - /** - * Convenience method to find the type id of this property. Most callers - * should rather use SMWDIProperty::findPropertyTypeId() directly. Note - * that this is not the same as getTypeID(), which returns the id of - * this property datavalue. - * - * @return string - */ - public function getPropertyTypeID() { - if ( $this->isValid() ) { - return $this->m_dataitem->findPropertyTypeId(); - } else { - return '__err'; - } - } - - /** - * Create special highlighting for hinting at special properties. - */ - protected function highlightText( $text ) { - if ( $this->m_dataitem->isUserDefined() ) { - return $text; - } else { - $highlighter = SMW\Highlighter::factory( SMW\Highlighter::TYPE_PROPERTY ); - $highlighter->setContent( array ( - 'caption' => $text, - 'content' => wfMessage( 'smw_isspecprop' )->text() - ) ); - - return $highlighter->getHtml(); - } - } - - /** - * A function for registering/overwriting predefined properties for SMW. Should be called from - * within the hook 'smwInitProperties'. Ids should start with three underscores "___" to avoid - * current and future confusion with SMW built-ins. - * - * @deprecated Use SMWDIProperty::registerProperty(). Will vanish before SMW 1.7. - */ - static public function registerProperty( $id, $typeid, $label = false, $show = false ) { - SMWDIProperty::registerProperty( $id, $typeid, $label, $show ); - } - - /** - * Add a new alias label to an existing datatype id. Note that every ID should have a primary - * label, either provided by SMW or registered with registerDatatype. This function should be - * called from within the hook 'smwInitDatatypes'. - * - * @deprecated Use SMWDIProperty::registerPropertyAlias(). Will vanish before SMW 1.7. - */ - static public function registerPropertyAlias( $id, $label ) { - SMWDIProperty::registerPropertyAlias( $id, $label ); - } - - /** - * @see SMWDIProperty::isUserDefined() - * - * @deprecated since 1.6 - */ - public function isUserDefined() { - return $this->m_dataitem->isUserDefined(); - } - - /** - * @see SMWDIProperty::isShown() - * - * @deprecated since 1.6 - */ - public function isShown() { - return $this->m_dataitem->isShown(); - } - - /** - * @see SMWDIProperty::isInverse() - * - * @deprecated since 1.6 - */ - public function isInverse() { - return $this->m_dataitem->isInverse(); - } - - /** - * Return a DB-key-like string: for visible properties, it is the actual DB key, - * for internal (invisible) properties, it is the property ID. The value agrees - * with the first component of getDBkeys() and it can be used in its place. - * @see SMWDIProperty::getKey() - * - * @deprecated since 1.6 - */ - public function getDBkey() { - return $this->m_dataitem->getKey(); - } - - /** - * @see SMWDIProperty::getLabel() - * - * @deprecated since 1.6 - */ - public function getText() { - return $this->m_dataitem->getLabel(); - } - -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_PropertyList.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_PropertyList.php deleted file mode 100644 index afc03ab6..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_PropertyList.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements special processing suitable for defining the list - * of properties that is required for SMWRecordValue objects. The input is a - * plain semicolon-separated list of property names, optionally with the - * namespace prefix. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWPropertyListValue extends SMWDataValue { - /** - * List of properte data items that are stored. - * @var array of SMWDIProperty - */ - protected $m_diProperties; - - protected function parseUserValue( $value ) { - global $wgContLang; - - $this->m_diProperties = array(); - $stringValue = ''; - $valueList = preg_split( '/[\s]*;[\s]*/u', trim( $value ) ); - foreach ( $valueList as $propertyName ) { - $propertyNameParts = explode( ':', $propertyName, 2 ); - if ( count( $propertyNameParts ) > 1 ) { - $namespace = smwfNormalTitleText( $propertyNameParts[0] ); - $propertyName = $propertyNameParts[1]; - $propertyNamespace = $wgContLang->getNsText( SMW_NS_PROPERTY ); - if ( $namespace != $propertyNamespace ) { - $this->addError( wfMessage( 'smw_wrong_namespace', $propertyNamespace )->inContentLanguage()->text() ); - } - } - - $propertyName = smwfNormalTitleText( $propertyName ); - - try { - $diProperty = SMWDIProperty::newFromUserLabel( $propertyName ); - } catch ( SMWDataItemException $e ) { - $diProperty = new SMWDIProperty( 'Error' ); - $this->addError( wfMessage( 'smw_noproperty', $propertyName )->inContentLanguage()->text() ); - } - - $this->m_diProperties[] = $diProperty; - $stringValue .= ( $stringValue ? ';' : '' ) . $diProperty->getKey(); - } - - $this->m_dataitem = new SMWDIBlob( $stringValue ); - } - - /** - * @see SMWDataValue::loadDataItem() - * - * @param $dataitem SMWDataItem - * - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem instanceof SMWDIBlob ) { - $this->m_dataitem = $dataItem; - $this->m_diProperties = array(); - - foreach ( explode( ';', $dataItem->getString() ) as $propertyKey ) { - try { - $this->m_diProperties[] = new SMWDIProperty( $propertyKey ); - } catch ( SMWDataItemException $e ) { - $this->m_diProperties[] = new SMWDIProperty( 'Error' ); - $this->addError( wfMessage( 'smw_parseerror' )->inContentLanguage()->text() ); - } - } - - $this->m_caption = false; - - return true; - } else { - return false; - } - } - - public function getShortWikiText( $linked = null ) { - return ( $this->m_caption !== false ) ? $this->m_caption : $this->makeOutputText( 2, $linked ); - } - - public function getShortHTMLText( $linker = null ) { - return ( $this->m_caption !== false ) ? $this->m_caption : $this->makeOutputText( 3, $linker ); - } - - public function getLongWikiText( $linked = null ) { - return $this->makeOutputText( 2, $linked ); - } - - public function getLongHTMLText( $linker = null ) { - return $this->makeOutputText( 3, $linker ); - } - - public function getWikiValue() { - return $this->makeOutputText( 4 ); - } - - public function getPropertyDataItems() { - return $this->m_diProperties; - } - -////// Internal helper functions - - protected function makeOutputText( $type, $linker = null ) { - if ( !$this->isValid() ) { - return ( ( $type == 0 ) || ( $type == 1 ) ) ? '' : $this->getErrorText(); - } - $result = ''; - $sep = ( $type == 4 ) ? '; ' : ', '; - foreach ( $this->m_diProperties as $diProperty ) { - if ( $result !== '' ) $result .= $sep; - $propertyValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $diProperty, null ); - $result .= $this->makeValueOutputText( $type, $propertyValue, $linker ); - } - return $result; - } - - protected function makeValueOutputText( $type, $propertyValue, $linker ) { - switch ( $type ) { - case 0: return $propertyValue->getShortWikiText( $linker ); - case 1: return $propertyValue->getShortHTMLText( $linker ); - case 2: return $propertyValue->getLongWikiText( $linker ); - case 3: return $propertyValue->getLongHTMLText( $linker ); - case 4: return $propertyValue->getWikiValue(); - } - } -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Quantity.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Quantity.php deleted file mode 100644 index 2f5e9f20..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Quantity.php +++ /dev/null @@ -1,231 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements unit support custom units, for which users have - * provided linear conversion factors within the wiki. Those user settings - * are retrieved from a property page associated with this object. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWQuantityValue extends SMWNumberValue { - - /** - * Array with format (canonical unit ID string) => (conversion factor) - * @var float[]|bool - */ - protected $m_unitfactors = false; - - /** - * Array with format (normalised unit string) => (canonical unit ID string) - * @var string[]|bool - */ - protected $m_unitids = false; - - /** - * Ordered array of (normalized) units that should be displayed in tooltips, etc. - * @var string[]|bool - */ - protected $m_displayunits = false; - - /** - * Main unit in canonical form (recognised by the conversion factor 1) - * @var string|bool - */ - protected $m_mainunit = false; - - protected function convertToMainUnit( $number, $unit ) { - $this->initConversionData(); - - if ( array_key_exists( $unit, $this->m_unitids ) ) { - $this->m_unitin = $this->m_unitids[$unit]; - assert( '$this->m_unitfactors[$this->m_unitin] != 0 /* Should be filtered by initConversionData() */' ); - $this->m_dataitem = new SMWDINumber( $number / $this->m_unitfactors[$this->m_unitin], $this->m_typeid ); - return true; - } else { // unsupported unit - return false; - } - } - - protected function makeConversionValues() { - if ( $this->m_unitvalues !== false ) { - return; // do this only once - } - - $this->m_unitvalues = array(); - - if ( !$this->isValid() ) { - return; - } - - $this->initDisplayData(); - - if ( count( $this->m_displayunits ) == 0 ) { // no display units, just show all - foreach ( $this->m_unitfactors as $unit => $factor ) { - if ( $unit !== '' ) { // filter out the empty fallback unit that is always there - $this->m_unitvalues[$unit] = $this->m_dataitem->getNumber() * $factor; - } - } - } else { - foreach ( $this->m_displayunits as $unit ) { - /// NOTE We keep non-ID units unless the input unit is used, so display units can be used to pick - /// the preferred form of a unit. Doing this requires us to recompute the conversion values whenever - /// the m_unitin changes. - $unitkey = ( $this->m_unitids[$unit] == $this->m_unitin ) ? $this->m_unitids[$unit] : $unit; - $this->m_unitvalues[$unitkey] = $this->m_dataitem->getNumber() * $this->m_unitfactors[$this->m_unitids[$unit]]; - } - } - } - - protected function makeUserValue() { - $printunit = false; // the normalised string of a known unit to use for printouts - - // Check if a known unit is given as outputformat: - if ( ( $this->m_outformat ) && ( $this->m_outformat != '-' ) && - ( $this->m_outformat != '-n' ) && ( $this->m_outformat != '-u' ) ) { // first try given output unit - $wantedunit = SMWNumberValue::normalizeUnit( $this->m_outformat ); - if ( array_key_exists( $wantedunit, $this->m_unitids ) ) { - $printunit = $wantedunit; - } - } - - // Alternatively, try to use the main display unit as a default: - if ( $printunit === false ) { - $this->initDisplayData(); - if ( count( $this->m_displayunits ) > 0 ) { - $printunit = reset( $this->m_displayunits ); - } - } - // Finally, fall back to main unit: - if ( $printunit === false ) { - $printunit = $this->getUnit(); - } - - $this->m_unitin = $this->m_unitids[$printunit]; - $this->m_unitvalues = false; // this array depends on m_unitin if displayunits were used, better invalidate it here - $value = $this->m_dataitem->getNumber() * $this->m_unitfactors[$this->m_unitin]; - - $this->m_caption = ''; - if ( $this->m_outformat != '-u' ) { // -u is the format for displaying the unit only - $this->m_caption .= ( ( $this->m_outformat != '-' ) && ( $this->m_outformat != '-n' ) ? smwfNumberFormat( $value ) : $value ); - } - - if ( ( $printunit !== '' ) && ( $this->m_outformat != '-n' ) ) { // -n is the format for displaying the number only - if ( $this->m_outformat != '-u' ) { - $this->m_caption .= ( $this->m_outformat != '-' ? ' ' : ' ' ); - } - $this->m_caption .= $printunit; - } - } - - public function getUnitList() { - $this->initConversionData(); - return array_keys( $this->m_unitfactors ); - } - - public function getUnit() { - $this->initConversionData(); - return $this->m_mainunit; - } - -/// The remaining functions are relatively "private" but are kept protected since -/// subclasses might exploit this to, e.g., "fake" conversion factors instead of -/// getting them from the database. A cheap way of making built-in types. - - /** - * This method initializes $m_unitfactors, $m_unitids, and $m_mainunit. - */ - protected function initConversionData() { - if ( $this->m_unitids !== false ) { - return; // do the below only once - } - - $this->m_unitids = array(); - $this->m_unitfactors = array(); - $this->m_mainunit = false; - - if ( !is_null( $this->m_property ) ) { - $propertyDiWikiPage = $this->m_property->getDiWikiPage(); - } - - if ( is_null( $this->m_property ) || is_null( $propertyDiWikiPage ) ) { - return; // we cannot find conversion factors without the property - } - - $factors = \SMW\StoreFactory::getStore()->getPropertyValues( $propertyDiWikiPage, new SMWDIProperty( '_CONV' ) ); - if ( count( $factors ) == 0 ) { // no custom type - $this->addError( wfMessage( 'smw_nounitsdeclared' )->inContentLanguage()->text() ); - return; - } - - $number = $unit = ''; - - foreach ( $factors as $di ) { - if ( !( $di instanceof SMWDIBlob ) || - ( SMWNumberValue::parseNumberValue( $di->getString(), $number, $unit ) != 0 ) || - ( $number == 0 ) ) { - continue; // ignore corrupted data and bogus inputs - } - $unit_aliases = preg_split( '/\s*,\s*/u', $unit ); - $first = true; - foreach ( $unit_aliases as $unit ) { - $unit = SMWNumberValue::normalizeUnit( $unit ); - if ( $first ) { - $unitid = $unit; - if ( $number == 1 ) { // add main unit to front of array (displayed first) - $this->m_mainunit = $unit; - $this->m_unitfactors = array( $unit => 1 ) + $this->m_unitfactors; - } else { // non-main units are not ordered (can be modified via display units) - $this->m_unitfactors[$unit] = $number; - } - $first = false; - } - // add all known units to m_unitids to simplify checking for them - $this->m_unitids[$unit] = $unitid; - } - } - - if ( $this->m_mainunit === false ) { // No unit with factor 1? Make empty string the main unit. - $this->m_mainunit = ''; - } - - // always add an extra empty unit; not as a synonym for the main unit but as a new unit with ID '' - // so if users do not give any unit, the conversion tooltip will still display the main unit for clarity - // (the empty unit is never displayed; we filter it when making conversion values) - $this->m_unitfactors = array( '' => 1 ) + $this->m_unitfactors; - $this->m_unitids[''] = ''; - } - - /** - * This method initializes $m_displayunits. - */ - protected function initDisplayData() { - if ( $this->m_displayunits !== false ) return; // do the below only once - $this->initConversionData(); // needed to normalise unit strings - $this->m_displayunits = array(); - - if ( is_null( $this->m_property ) || is_null( $this->m_property->getDIWikiPage() ) ) { - return; - } - - $dataItems = \SMW\StoreFactory::getStore()->getPropertyValues( $this->m_property->getDIWikiPage(), new SMWDIProperty( '_UNIT' ) ); - $units = array(); - - foreach ( $dataItems as $di ) { // Join all if many annotations exist. Discouraged (random order) but possible. - if ( $di instanceof SMWDIBlob ) { - $units = $units + preg_split( '/\s*,\s*/u', $di->getString() ); - } - } - - foreach ( $units as $unit ) { - $unit = SMWNumberValue::normalizeUnit( $unit ); - if ( array_key_exists( $unit, $this->m_unitids ) ) { - $this->m_displayunits[] = $unit; // do not avoid duplicates, users can handle this - } // note: we ignore unsuppported units -- no way to display them - } - } -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php deleted file mode 100644 index 1fd32ceb..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php +++ /dev/null @@ -1,328 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * SMWDataValue implements the handling of small sets of property-value pairs. - * The declaration of Records in SMW uses the order of values to encode the - * property that should be used, so the user only needs to enter a list of - * values. Internally, however, the property-value assignments are not stored - * with a particular order; they will only be ordered for display, following - * the declaration. This is why it is not supported to have Records using the - * same property for more than one value. - * - * The class uses SMWDIContainer objects to return its inner state. See the - * documentation for SMWDIContainer for details on how this "pseudo" data - * encapsulated many property assignments. Such data is stored internally - * like a page with various property-value assignments. Indeed, record values - * can be created from SMWDIWikiPage objects (the missing information will - * be fetched from the store). - * - * @todo Enforce limitation of maximal number of values. - * @todo Enforce uniqueness of properties in declaration. - * @todo Complete internationalisation. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWRecordValue extends SMWDataValue { - - /// cache for properties for the fields of this data value - protected $m_diProperties = null; - - protected function parseUserValue( $value ) { - $this->parseUserValueOrQuery( $value, false ); - } - - protected function parseUserValueOrQuery( $value, $queryMode ) { - if ( $value === '' ) { - $this->addError( wfMessage( 'smw_novalues' )->text() ); - - if ( $queryMode ) { - return new SMWThingDescription(); - } else { - return; - } - } - - if ( $queryMode ) { - $subdescriptions = array(); - } elseif ( is_null( $this->m_contextPage ) ) { - $semanticData = SMWContainerSemanticData::makeAnonymousContainer(); - } else { - $subobjectName = '_' . hash( 'md4', $value, false ); // md4 is probably fastest of PHP's hashes - $subject = new SMWDIWikiPage( $this->m_contextPage->getDBkey(), - $this->m_contextPage->getNamespace(), $this->m_contextPage->getInterwiki(), - $subobjectName ); - $semanticData = new SMWContainerSemanticData( $subject ); - } - - $values = preg_split( '/[\s]*;[\s]*/u', trim( $value ) ); - $valueIndex = 0; // index in value array - $propertyIndex = 0; // index in property list - $empty = true; - - foreach ( $this->getPropertyDataItems() as $diProperty ) { - if ( !array_key_exists( $valueIndex, $values ) ) { - break; // stop if there are no values left - } - - if ( $queryMode ) { // special handling for supporting query parsing - $comparator = SMW_CMP_EQ; - SMWDataValue::prepareValue( $values[$valueIndex], $comparator ); - } - - // generating the DVs: - if ( ( $values[$valueIndex] === '' ) || ( $values[$valueIndex] == '?' ) ) { // explicit omission - $valueIndex++; - } else { - $dataValue = \SMW\DataValueFactory::getInstance()->newPropertyObjectValue( $diProperty, $values[$valueIndex] ); - - if ( $dataValue->isValid() ) { // valid DV: keep - if ( $queryMode ) { - $subdescriptions[] = new SMWSomeProperty( - $diProperty, - new SMWValueDescription( - $dataValue->getDataItem(), - $dataValue->getProperty(), - $comparator - ) - ); - } else { - $semanticData->addPropertyObjectValue( $diProperty, $dataValue->getDataItem() ); - } - - $valueIndex++; - $empty = false; - } elseif ( ( count( $values ) - $valueIndex ) == ( count( $this->m_diProperties ) - $propertyIndex ) ) { - // too many errors: keep this one to have enough slots left - if ( !$queryMode ) { - $semanticData->addPropertyObjectValue( $diProperty, $dataValue->getDataItem() ); - } - - $this->addError( $dataValue->getErrors() ); - ++$valueIndex; - } - } - ++$propertyIndex; - } - - if ( $empty ) { - $this->addError( wfMessage( 'smw_novalues' )->text() ); - } - - if ( $queryMode ) { - switch ( count( $subdescriptions ) ) { - case 0: return new SMWThingDescription(); - case 1: return reset( $subdescriptions ); - default: return new SMWConjunction( $subdescriptions ); - } - } else { - $this->m_dataitem = new SMWDIContainer( $semanticData ); - } - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_CONTAINER ) { - $this->m_dataitem = $dataItem; - return true; - } elseif ( $dataItem->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) { - $semanticData = new SMWContainerSemanticData( $dataItem ); - $semanticData->copyDataFrom( \SMW\StoreFactory::getStore()->getSemanticData( $dataItem ) ); - $this->m_dataitem = new SMWDIContainer( $semanticData ); - return true; - } else { - return false; - } - } - - /** - * Overwrite SMWDataValue::getQueryDescription() to be able to process - * comparators between all values. - */ - public function getQueryDescription( $value ) { - return $this->parseUserValueOrQuery( $value, true ); - } - - public function getShortWikiText( $linked = null ) { - if ( $this->m_caption !== false ) { - return $this->m_caption; - } - return $this->makeOutputText( 0, $linked ); - } - - public function getShortHTMLText( $linker = null ) { - if ( $this->m_caption !== false ) { - return $this->m_caption; - } - return $this->makeOutputText( 1, $linker ); - } - - public function getLongWikiText( $linked = null ) { - return $this->makeOutputText( 2, $linked ); - } - - public function getLongHTMLText( $linker = null ) { - return $this->makeOutputText( 3, $linker ); - } - - public function getWikiValue() { - return $this->makeOutputText( 4 ); - } - - /// @todo Allowed values for multi-valued properties are not supported yet. - protected function checkAllowedValues() { } - - /** - * Make sure that the content is reset in this case. - * @todo This is not a full reset yet (the case that property is changed after a value - * was set does not occur in the normal flow of things, hence this has low priority). - */ - public function setProperty( SMWDIProperty $property ) { - parent::setProperty( $property ); - $this->m_diProperties = null; - } - -////// Additional API for value lists - - /** - * @deprecated as of 1.6, use getDataItems instead - * - * @return array of SMWDataItem - */ - public function getDVs() { - return $this->getDataItems(); - } - - /** - * Create a list (array with numeric keys) containing the datavalue - * objects that this SMWRecordValue object holds. Values that are not - * present are set to null. Note that the first index in the array is - * 0, not 1. - * - * @since 1.6 - * - * @return array of SMWDataItem - */ - public function getDataItems() { - if ( $this->isValid() ) { - $result = array(); - $index = 0; - foreach ( $this->getPropertyDataItems() as $diProperty ) { - $values = $this->getDataItem()->getSemanticData()->getPropertyValues( $diProperty ); - if ( count( $values ) > 0 ) { - $result[$index] = reset( $values ); - } else { - $result[$index] = null; - } - $index += 1; - } - return $result; - } else { - return array(); - } - } - - /** - * Return the array (list) of properties that the individual entries of - * this datatype consist of. - * - * @since 1.6 - * - * @todo I18N for error message. - * - * @return array of SMWDIProperty - */ - public function getPropertyDataItems() { - if ( is_null( $this->m_diProperties ) ) { - $this->m_diProperties = self::findPropertyDataItems( $this->m_property ); - - if ( count( $this->m_diProperties ) == 0 ) { // TODO internalionalize - $this->addError( 'The list of properties to be used for the data fields has not been specified properly.' ); - } - } - - return $this->m_diProperties; - } - - /** - * Return the array (list) of properties that the individual entries of - * this datatype consist of. - * - * @since 1.6 - * - * @param $diProperty mixed null or SMWDIProperty object for which to retrieve the types - * - * @return array of SMWDIProperty - */ - public static function findPropertyDataItems( $diProperty ) { - if ( !is_null( $diProperty ) ) { - $propertyDiWikiPage = $diProperty->getDiWikiPage(); - - if ( !is_null( $propertyDiWikiPage ) ) { - $listDiProperty = new SMWDIProperty( '_LIST' ); - $dataItems = \SMW\StoreFactory::getStore()->getPropertyValues( $propertyDiWikiPage, $listDiProperty ); - - if ( count( $dataItems ) == 1 ) { - $propertyListValue = new SMWPropertyListValue( '__pls' ); - $propertyListValue->setDataItem( reset( $dataItems ) ); - - if ( $propertyListValue->isValid() ) { - return $propertyListValue->getPropertyDataItems(); - } - } - } - } - - return array(); - } - -////// Internal helper functions - - protected function makeOutputText( $type = 0, $linker = null ) { - if ( !$this->isValid() ) { - return ( ( $type == 0 ) || ( $type == 1 ) ) ? '' : $this->getErrorText(); - } - - $result = ''; - $i = 0; - foreach ( $this->getPropertyDataItems() as $propertyDataItem ) { - if ( $i == 1 ) { - $result .= ( $type == 4 ) ? '; ' : ' ('; - } elseif ( $i > 1 ) { - $result .= ( $type == 4 ) ? '; ' : ', '; - } - ++$i; - $propertyValues = $this->m_dataitem->getSemanticData()->getPropertyValues( $propertyDataItem ); // combining this with next line violates PHP strict standards - $dataItem = reset( $propertyValues ); - if ( $dataItem !== false ) { - $dataValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $dataItem, $propertyDataItem ); - $result .= $this->makeValueOutputText( $type, $dataValue, $linker ); - } else { - $result .= '?'; - } - } - if ( ( $i > 1 ) && ( $type != 4 ) ) $result .= ')'; - - return $result; - } - - protected function makeValueOutputText( $type, $dataValue, $linker ) { - switch ( $type ) { - case 0: return $dataValue->getShortWikiText( $linker ); - case 1: return $dataValue->getShortHTMLText( $linker ); - case 2: return $dataValue->getShortWikiText( $linker ); - case 3: return $dataValue->getShortHTMLText( $linker ); - case 4: return $dataValue->getWikiValue(); - } - } - -} - diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_String.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_String.php deleted file mode 100644 index 6151c381..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_String.php +++ /dev/null @@ -1,194 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements String-Datavalues suitable for defining - * String-types of properties. - * - * @author Nikolas Iwan - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWStringValue extends SMWDataValue { - - protected function parseUserValue( $value ) { - if ( $value === '' ) { - $this->addError( wfMessage( 'smw_emptystring' )->inContentLanguage()->text() ); - } - - $this->m_dataitem = new SMWDIBlob( $value, $this->m_typeid ); - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem instanceof SMWDIBlob ) { - $this->m_caption = false; - $this->m_dataitem = $dataItem; - return true; - } else { - return false; - } - } - - public function getShortWikiText( $linked = null ) { - if ( $this->m_caption !== false ) { - return $this->m_caption; - } else { - return $this->getDisplayString( - false, - ( $linked !== false ) && ( !is_null( $linked ) ), - false - ); - } - } - - public function getShortHTMLText( $linker = null ) { - if ( $this->m_caption !== false ) { - return smwfXMLContentEncode( $this->m_caption ); - } else { - return $this->getDisplayString( - false, - ( $linker !== false ) && ( !is_null( $linker ) ), - true - ); - } - } - - public function getLongWikiText( $linked = null ) { - return $this->getDisplayString( - true, - ( $linked !== false ) && ( !is_null( $linked ) ), - false - ); - } - - /** - * @todo Rather parse input to obtain properly formatted HTML. - */ - public function getLongHTMLText( $linker = null ) { - return $this->getDisplayString( - true, - ( $linker !== false ) && ( !is_null( $linker ) ), - true - ); - } - - public function getWikiValue() { - return $this->isValid() ? $this->m_dataitem->getString() : 'error'; - } - - public function getInfolinks() { - if ( $this->m_typeid != '_cod' ) { - return parent::getInfolinks(); - } else { - return $this->m_infolinks; - } - } - - protected function getServiceLinkParams() { - // Create links to mapping services based on a wiki-editable message. The parameters - // available to the message are: - // $1: urlencoded string - if ( $this->isValid() ) { - return array( rawurlencode( $this->m_dataitem->getString() ) ); - } else { - return false; - } - } - - /** - * Get the string that should be displayed for this value. - * The result is only escaped to be HTML-safe if this is requested - * explicitly. The result will contain mark-up that must not be escaped - * again. - * - * @since 1.8 - * @param boolean $abbreviate - * @param boolean $linked set to false to disable tooltips - * @param boolean $forHtml should the result be escaped to be HTML-safe? - * @return string - */ - protected function getDisplayString( $abbreviate, $linked, $forHtml ) { - if ( !$this->isValid() ) { - return ''; - } elseif ( $this->m_typeid == '_cod' ) { - return $this->getCodeDisplay( $this->m_dataitem->getString(), $abbreviate ); - } else { - return $this->getTextDisplay( $this->m_dataitem->getString(), $abbreviate, $linked, $forHtml ); - } - } - - /** - * Make a possibly shortened printout string for displaying the value. - * The result is only escaped to be HTML-safe if this is requested - * explicitly. The result will contain mark-up that must not be escaped - * again. - * - * @todo The method abbreviates very long strings for display by simply - * taking substrings. This is not in all cases a good idea, since it may - * break XML entities and mark-up. - * - * @since 1.8 - * @param string $value - * @param boolean $abbreviate limit overall display length? - * @param boolean $linked should abbreviated values use tooltips? - * @param boolean $forHtml should the result be escaped to be HTML-safe? - * @return string - */ - protected function getTextDisplay( $value, $abbreviate, $linked, $forHtml ) { - if ( $forHtml ) { - $value = smwfXMLContentEncode( $value ); - } - - $length = mb_strlen( $value ); - if ( $abbreviate && $length > 255 ) { - if ( !$linked ) { - $ellipsis = ' <span class="smwwarning">…</span> '; - } else { - $highlighter = SMW\Highlighter::factory( SMW\Highlighter::TYPE_TEXT ); - $highlighter->setContent( array ( - 'caption' => ' … ', - 'content' => $value - ) ); - - $ellipsis = $highlighter->getHtml(); - } - - return mb_substr( $value, 0, 42 ) . $ellipsis . mb_substr( $value, $length - 42 ); - } else { - return $value; - } - } - - /** - * Escape and wrap values of type Code. The result is escaped to be - * HTML-safe (it will also work in wiki context). The result will - * contain mark-up that must not be escaped again. - * - * @param string $value - * @param boolean $abbreviate should the code box be limited vertically? - * @return string - */ - protected function getCodeDisplay( $value, $abbreviate ) { - SMWOutputs::requireResource( 'ext.smw.style' ); - // This disables all active wiki and HTML markup: - $result = str_replace( - array( '<', '>', ' ', '[', '{', '=', "'", ':', "\n" ), - array( '<', '>', ' ', '[', '{', '=', ''', ':', "<br />" ), - $value ); - - if ( $abbreviate ) { - $result = "<div style=\"height:5em; overflow:auto;\">$result</div>"; - } - - return "<div class=\"smwpre\">$result</div>"; - } - -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Temperature.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Temperature.php deleted file mode 100644 index 462f4ab9..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Temperature.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements unit support for measuring temperatures. This is - * mostly an example implementation of how to realise custom unit types easily. - * The implementation lacks support for localization and for selecting - * "display units" on the property page as possible for the types with linear - * unit conversion. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWTemperatureValue extends SMWNumberValue { - - protected function convertToMainUnit( $number, $unit ) { - // Find current ID and covert main values to Kelvin, if possible - // Note: there is no error when unknown units are used. - $this->m_unitin = $this->getUnitID( $unit ); - switch ( $this->m_unitin ) { - case 'K': - $value = $number; - break; - case '°C': - $value = $number + 273.15; - break; - case '°F': - $value = ( $number - 32 ) / 1.8 + 273.15; - break; - case '°R': - $value = ( $number ) / 1.8; - break; - default: return false; // unsupported unit - } - $this->m_dataitem = new SMWDINumber( $value, $this->m_typeid ); - return true; - } - - protected function makeConversionValues() { - /// NOTE This class currently ignores display units. - if ( $this->m_unitvalues !== false ) return; // do this only once - if ( !$this->isValid() ) { - $this->m_unitvalues = array(); - } else { - $this->m_unitvalues = array( 'K' => $this->m_dataitem->getNumber(), - '°C' => $this->m_dataitem->getNumber() - 273.15, - '°F' => ( $this->m_dataitem->getNumber() - 273.15 ) * 1.8 + 32, - '°R' => ( $this->m_dataitem->getNumber() ) * 1.8 ); - } - } - - protected function makeUserValue() { - $value = false; - if ( ( $this->m_outformat ) && ( $this->m_outformat != '-' ) && - ( $this->m_outformat != '-n' ) && ( $this->m_outformat != '-u' ) ) { // first try given output unit - $printunit = SMWNumberValue::normalizeUnit( $this->m_outformat ); - $this->m_unitin = $this->getUnitID( $printunit ); - switch ( $this->m_unitin ) { - case 'K': - $value = $this->m_dataitem->getNumber(); - break; - case '°C': - $value = $this->m_dataitem->getNumber() - 273.15; - break; - case '°F': - $value = ( $this->m_dataitem->getNumber() - 273.15 ) * 1.8 + 32; - break; - case '°R': - $value = ( $this->m_dataitem->getNumber() ) * 1.8; - break; - // default: unit not supported - } - } - if ( $value === false ) { // no valid output unit requested - $value = $this->m_dataitem->getNumber(); - $this->m_unitin = 'K'; - $printunit = 'K'; - } - - $this->m_caption = ''; - if ( $this->m_outformat != '-u' ) { // -u is the format for displaying the unit only - $this->m_caption .= ( ( $this->m_outformat != '-' ) && ( $this->m_outformat != '-n' ) ? smwfNumberFormat( $value ) : $value ); - } - if ( ( $printunit !== '' ) && ( $this->m_outformat != '-n' ) ) { // -n is the format for displaying the number only - if ( $this->m_outformat != '-u' ) { - $this->m_caption .= ( $this->m_outformat != '-' ? ' ' : ' ' ); - } - $this->m_caption .= $printunit; - } - } - - /** - * Helper method to find the main representation of a certain unit. - */ - protected function getUnitID( $unit ) { - /// TODO possibly localise some of those strings - switch ( $unit ) { - case '': case 'K': case 'Kelvin': case 'kelvin': case 'kelvins': return 'K'; - // There's a dedicated Unicode character (℃, U+2103) for degrees C. - // Your font may or may not display it; do not be alarmed. - case '°C': case '℃': case 'Celsius': case 'centigrade': return '°C'; - case '°F': case 'Fahrenheit': return '°F'; - case '°R': case 'Rankine': return '°R'; - default: return false; - } - } - - public function getUnitList() { - return array( 'K', '°C', '°F', '°R' ); - } - - public function getUnit() { - return 'K'; - } - -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Time.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Time.php deleted file mode 100644 index 0978a0d8..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Time.php +++ /dev/null @@ -1,874 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue captures values of dates and times, in many formats, - * throughout history and pre-history. The implementation can handle dates - * across history with full precision for storing, and substantial precision - * for sorting and querying. The range of supported past dates should encompass - * the Beginning of Time according to most of today's theories. The range of - * supported future dates is limited more strictly, but it does also allow - * year numbers in the order of 10^9. - * - * The implementation notices and stores whether parts of a date/time have been - * omitted (as in "2008" or "May 2007"). For all exporting and sorting - * purposes, incomplete dates are completed with defaults (usually using the - * earliest possible time, i.e. interpreting "2008" as "Jan 1 2008 00:00:00"). - * The information on what was unspecified is kept internally for improving - * behavior e.g. for outputs (defaults are not printed when querying for a - * value). This largely uses the precision handling of SMWDITime. - * - * - * Date formats - * - * Dates can be given in many formats, using numbers, month names, and - * abbreviated month names. The preferred interpretation of ambiguous dates - * ("1 2 2008" or even "1 2 3 BC") is controlled by the language file, as is - * the local naming of months. English month names are always supported. - * - * Dates can be given in Gregorian or Julian calendar, set by the token "Jl" - * or "Gr" in the input. If neither is set, a default is chosen: inputs after - * October 15, 1582 (the time when the Gregorian calendar was first inaugurated - * in some parts of the world) are considered Gr, earlier inputs are considered - * Jl. In addition to Jl and Gr, we support "OS" (Old Style English dates that - * refer to the use of Julian calendar with a displaced change of year on March - * 24), JD (direct numerical input in Julian Day notation), and MJD (direct - * numerical input in Modified Julian Day notation as used in aviation and - * space flight). - * - * The class does not support the input of negative year numbers but uses the - * markers "BC"/"BCE" and "AD"/"CE" instead. There is no year 0 in Gregorian or - * Julian calendars, but the class graciously considers this input to mean year - * 1 BC(E). - * - * For prehisoric dates before 9999 BC(E) only year numbers are allowed - * (nothing else makes much sense). At this time, the years of Julian and - * Gregorian calendar still overlap significantly, so the transition to a - * purely solar annotation of prehistoric years is smooth. Technically, the - * class will consider prehistoric dates as Gregorian but very ancient times - * may be interpreted as desired (probably with reference to a physical notion - * of time that is not dependent on revolutions of earth around the sun). - * - * - * Time formats - * - * Times can be in formats like "23:12:45" and "12:30" possibly with additional - * modifiers "am" or "pm". Timezones are supported: the class knows many - * international timezone monikers (e.g. CET or GMT) and also allows time - * offsets directly after a time (e.g. "10:30-3:30" or "14:45:23+2"). Such - * offsets always refer to UTC. Timezones are only used on input and are not - * stored as part of the value. - * - * Time offsets take leap years into account, e.g. the date - * "Feb 28 2004 23:00+2:00" is equivalent to "29 February 2004 01:00:00", while - * "Feb 28 1900 23:00+2:00" is equivalent to "1 March 1900 01:00:00". - * - * Military time format is supported. This consists of 4 or 6 numeric digits - * followed by a one-letter timezone code (e.g. 1240Z is equivalent to 12:40 - * UTC). - * - * - * I18N - * - * Currently, neither keywords like "BCE", "Jl", or "pm", nor timezone monikers - * are internationalized. Timezone monikers may not require this, other than - * possibly for Cyrillic (added when needed). Month names are fully - * internationalized, but English names and abbreviations will also work in all - * languages. The class also supports ordinal day-of-month annotations like - * "st" and "rd", again only for English. - * - * I18N includes the preferred order of dates, e.g. to interpret "5 6 2010". - * - * @todo Theparsing process can encounter many kinds of well-defined problems - * but uses only one error message. More detailed reporting should be done. - * @todo Try to reuse more of MediaWiki's records, e.g. to obtain month names - * or to format dates. The problem is that MW is based on SIO timestamps that - * don't extend to very ancient or future dates, and that MW uses PHP functions - * that are bound to UNIX time. - * - * @author Markus Krötzsch - * @author Fabian Howahl - * @author Terry A. Hurlbut - * @ingroup SMWDataValues - */ -class SMWTimeValue extends SMWDataValue { - protected $m_dataitem_greg = null; - protected $m_dataitem_jul = null; - - protected $m_wikivalue; // a suitable wiki input value - - // The following are constant (array-valued constants are not supported, hence the declaration as private static variable): - protected static $m_months = array( 'January', 'February', 'March', 'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' ); - protected static $m_monthsshort = array( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ); - protected static $m_formats = array( SMW_Y => array( 'y' ), SMW_YM => array( 'y', 'm' ), SMW_MY => array( 'm', 'y' ), SMW_YDM => array( 'y', 'd', 'm' ), SMW_YMD => array( 'y', 'm', 'd' ), SMW_DMY => array( 'd', 'm', 'y' ), SMW_MDY => array( 'm', 'd', 'y' ) ); - - /// General purpose time zone monikers and their associated offsets in hours and fractions of hours - protected static $m_tz = array( 'A' => 1, 'ACDT' => 10.5, 'ACST' => 9.5, 'ADT' => -3, 'AEDT' => 11, - 'AEST' => 10, 'AKDT' => -8, 'AKST' => -9, 'AST' => -4, 'AWDT' => 9, 'AWST' => 8, - 'B' => 2, 'BST' => 1, 'C' => 3, 'CDT' => - 5, 'CEDT' => 2, 'CEST' => 2, - 'CET' => 1, 'CST' => -6, 'CXT' => 7, 'D' => 4, 'E' => 5, 'EDT' => - 4, - 'EEDT' => 3, 'EEST' => 3, 'EET' => 2, 'EST' => - 5, 'F' => 6, 'G' => 7, - 'GMT' => 0, 'H' => 8, 'HAA' => - 3, 'HAC' => - 5, 'HADT' => - 9, 'HAE' => -4, - 'HAP' => -7, 'HAR' => -6, 'HAST' => -10, 'HAT' => -2.5, 'HAY' => -8, - 'HNA' => -4, 'HNC' => -6, 'HNE' => -5, 'HNP' => -8, 'HNR' => -7, 'HNT' => -3.5, - 'HNY' => -9, 'I' => 9, 'IST' => 1, 'K' => 10, 'L' => 11, 'M' => 12, - 'MDT' => -6, 'MESZ' => 2, 'MEZ' => 1, 'MSD' => 4, 'MSK' => 3, 'MST' => -7, - 'N' => -1, 'NDT' => -2.5, 'NFT' => 11.5, 'NST' => -3.5, 'O' => -2, 'P' => -3 , - 'PDT' => -7, 'PST' => -8, 'Q' => - 4, 'R' => - 5, 'S' => -6, 'T' => -7, - 'U' => -8, 'UTC' => 0, 'V' => - 9, 'W' => -10, 'WDT' => 9, 'WEDT' => 1, - 'WEST' => 1, 'WET' => 0, 'WST' => 8, 'X' => -11, 'Y' => -12, 'Z' => 0 ); - /// Military time zone monikers and their associated offsets in hours - protected static $m_miltz = array( 'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, - 'G' => 7, 'H' => 8, 'I' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => -1, 'O' => -2, - 'P' => -3, 'Q' => -4, 'R' => -5, 'S' => -6, 'T' => -7, 'U' => -8, 'V' => -9, - 'W' => -10, 'X' => -11, 'Y' => -12, 'Z' => 0 ); - - /// Moment of switchover to Gregorian calendar. - const J1582 = 2299160.5; - /// Offset of Julian Days for Modified JD inputs. - const MJD_EPOCH = 2400000.5; - /// The year before which we do not accept anything but year numbers and largely discourage calendar models. - const PREHISTORY = -10000; - - protected function parseUserValue( $value ) { - $value = trim( $value ); // ignore whitespace - $this->m_wikivalue = $value; - if ( $this->m_caption === false ) { // Store the caption now. - $this->m_caption = $value; - } - $this->m_dataitem = null; - - /// TODO Direct JD input currently cannot cope with decimal numbers - $datecomponents = array(); - $calendarmodel = $era = $hours = $minutes = $seconds = $timeoffset = false; - - // Check if it's parseable by wfTimestamp when it's not a year (which is wrongly interpreted). - if ( strlen( $value ) != 4 && wfTimestamp( TS_MW, $value ) !== false ) { - $this->m_dataitem = SMWDITime::newFromTimestamp( $value ); - } - elseif ( $this->parseDateString( $value, $datecomponents, $calendarmodel, $era, $hours, $minutes, $seconds, $timeoffset ) ) { - if ( ( $calendarmodel === false ) && ( $era === false ) && ( count( $datecomponents ) == 1 ) && ( intval( end( $datecomponents ) ) >= 100000 ) ) { - $calendarmodel = 'JD'; // default to JD input if a single number was given as the date - } - - if ( ( $calendarmodel == 'JD' ) || ( $calendarmodel == 'MJD' ) ) { - if ( ( $era === false ) && ( $hours === false ) && ( $timeoffset == 0 ) ) { - try { - $jd = floatval( reset( $datecomponents ) ); - if ( $calendarmodel == 'MJD' ) $jd += self::MJD_EPOCH; - $this->m_dataitem = SMWDITime::newFromJD( $jd, SMWDITime::CM_GREGORIAN, SMWDITime::PREC_YMDT, $this->m_typeid ); - } catch ( SMWDataItemException $e ) { - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - } - } else { - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - } - } else { - $this->setDateFromParsedValues( $datecomponents, $calendarmodel, $era, $hours, $minutes, $seconds, $timeoffset ); - } - } - - if ( is_null( $this->m_dataitem ) ) { // make sure that m_dataitem is set in any case - $this->m_dataitem = new SMWDITime( SMWDITime::CM_GREGORIAN, 32202 ); - } - } - - /** - * Parse the given string to check if it a date/time value. - * The function sets the provided call-by-ref values to the respective - * values. If errors are encountered, they are added to the objects - * error list and false is returned. Otherwise, true is returned. - * @param $string string input time representation, e.g. "12 May 2007 13:45:23-3:30" - * @param $datecomponents array of strings that might belong to the specification of a date - * @param $calendarmodesl string if model was set in input, otherwise false - * @param $era string '+' or '-' if provided, otherwise false - * @param $hours integer set to a value between 0 and 24 - * @param $minutes integer set to a value between 0 and 59 - * @param $seconds integer set to a value between 0 and 59, or false if not given - * @param $timeoffset double set to a value for time offset (e.g. 3.5), or false if not given - * @return boolean stating if the parsing succeeded - * @todo This method in principle allows date parsing to be internationalized further. Should be done. - */ - protected function parseDateString( $string, &$datecomponents, &$calendarmodel, &$era, &$hours, &$minutes, &$seconds, &$timeoffset ) { - // crude preprocessing for supporting different date separation characters; - // * this does not allow localized time notations such as "10.34 pm" - // * this creates problems with keywords that contain "." such as "p.m." - // * yet "." is an essential date separation character in languages such as German - $parsevalue = str_replace( array( '/', '.', ' ', ',' ), array( '-', ' ', ' ', ' ' ), $string ); - - $matches = preg_split( "/([T]?[0-2]?[0-9]:[\:0-9]+[+\-]?[0-2]?[0-9\:]+|[\p{L}]+|[0-9]+|[ ])/u", $parsevalue , -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); - $datecomponents = array(); - $calendarmodel = $timezoneoffset = $era = $ampm = false; - $hours = $minutes = $seconds = $timeoffset = false; - $unclearparts = array(); - $matchisnumber = false; // used for looking back; numbers are days/months/years by default but may be re-interpreted if certain further symbols are found - $matchisdate = false; // used for ensuring that date parts are in one block - - foreach ( $matches as $match ) { - $prevmatchwasnumber = $matchisnumber; - $prevmatchwasdate = $matchisdate; - $matchisnumber = $matchisdate = false; - - if ( $match == ' ' ) { - $matchisdate = $prevmatchwasdate; // spaces in dates do not end the date - } elseif ( $match == '-' ) { // can only occur separately between date components - $datecomponents[] = $match; // we check later if this makes sense - $matchisdate = true; - } elseif ( is_numeric( $match ) && - ( $prevmatchwasdate || count( $datecomponents ) == 0 ) ) { - $datecomponents[] = $match; - $matchisnumber = true; - $matchisdate = true; - } elseif ( $era === false && in_array( $match, array( 'AD', 'CE' ) ) ) { - $era = '+'; - } elseif ( $era === false && in_array( $match, array( 'BC', 'BCE' ) ) ) { - $era = '-'; - } elseif ( $calendarmodel === false && in_array( $match, array( 'Gr', 'He', 'Jl', 'MJD', 'JD', 'OS' ) ) ) { - $calendarmodel = $match; - } elseif ( $ampm === false && ( strtolower( $match ) === 'am' || strtolower( $match ) === 'pm' ) ) { - $ampm = strtolower( $match ); - } elseif ( $hours === false && self::parseTimeString( $match, $hours, $minutes, $seconds, $timeoffset ) ) { - // nothing to do - } elseif ( $hours !== false && $timezoneoffset === false && - array_key_exists( $match, self::$m_tz ) ) { - // only accept timezone if time has already been set - $timezoneoffset = self::$m_tz[ $match ]; - } elseif ( $prevmatchwasnumber && $hours === false && $timezoneoffset === false && - array_key_exists( $match, self::$m_miltz ) && - self::parseMilTimeString( end( $datecomponents ), $hours, $minutes, $seconds ) ) { - // military timezone notation is found after a number -> re-interpret the number as military time - array_pop( $datecomponents ); - $timezoneoffset = self::$m_miltz[ $match ]; - } elseif ( ( $prevmatchwasdate || count( $datecomponents ) == 0 ) && - $this->parseMonthString( $match, $monthname ) ) { - $datecomponents[] = $monthname; - $matchisdate = true; - } elseif ( $prevmatchwasnumber && $prevmatchwasdate && in_array( $match, array( 'st', 'nd', 'rd', 'th' ) ) ) { - $datecomponents[] = 'd' . strval( array_pop( $datecomponents ) ); // must be a day; add standard marker - $matchisdate = true; - } else { - $unclearparts[] = $match; - } - } - // Useful for debugging: - // print "\n\n Results \n\n"; - // debug_zval_dump( $datecomponents ); - // print "\ncalendarmodel: $calendarmodel \ntimezoneoffset: $timezoneoffset \nera: $era \nampm: $ampm \nh: $hours \nm: $minutes \ns:$seconds \ntimeoffset: $timeoffset \n"; - // debug_zval_dump( $unclearparts ); - - // Abort if we found unclear or over-specific information: - if ( count( $unclearparts ) != 0 || - ( $timezoneoffset !== false && $timeoffset !== false ) ) { - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - return false; - } - - $timeoffset = $timeoffset + $timezoneoffset; - // Check if the a.m. and p.m. information is meaningful - - if ( $ampm !== false && ( $hours > 12 || $hours == 0 ) ) { // Note: the == 0 check subsumes $hours===false - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - return false; - } elseif ( $ampm == 'am' && $hours == 12 ) { - $hours = 0; - } elseif ( $ampm == 'pm' && $hours < 12 ) { - $hours += 12; - } - - return true; - } - - /** - * Parse the given string to check if it encodes an international time. - * If successful, the function sets the provided call-by-ref values to - * the respective numbers and returns true. Otherwise, it returns - * false and does not set any values. - * @note This method is only temporarily public for enabling SMWCompatibilityHelpers. Do not use it directly in your code. - * - * @param $string string input time representation, e.g. "13:45:23-3:30" - * @param $hours integer between 0 and 24 - * @param $minutes integer between 0 and 59 - * @param $seconds integer between 0 and 59, or false if not given - * @param $timeoffset double for time offset (e.g. 3.5), or false if not given - * @return boolean stating if the parsing succeeded - */ - public static function parseTimeString( $string, &$hours, &$minutes, &$seconds, &$timeoffset ) { - if ( !preg_match( "/^[T]?([0-2]?[0-9]):([0-5][0-9])(:[0-5][0-9])?(([+\-][0-2]?[0-9])(:(30|00))?)?$/u", $string, $match ) ) { - return false; - } else { - $nhours = intval( $match[1] ); - $nminutes = $match[2] ? intval( $match[2] ) : false; - if ( ( count( $match ) > 3 ) && ( $match[3] !== '' ) ) { - $nseconds = intval( substr( $match[3], 1 ) ); - } else { - $nseconds = false; - } - if ( ( $nhours < 25 ) && ( ( $nhours < 24 ) || ( $nminutes + $nseconds == 0 ) ) ) { - $hours = $nhours; - $minutes = $nminutes; - $seconds = $nseconds; - if ( ( count( $match ) > 5 ) && ( $match[5] !== '' ) ) { - $timeoffset = intval( $match[5] ); - if ( ( count( $match ) > 7 ) && ( $match[7] == '30' ) ) { - $timeoffset += 0.5; - } - } else { - $timeoffset = false; - } - return true; - } else { - return false; - } - } - } - - /** - * Parse the given string to check if it encodes a "military time". - * If successful, the function sets the provided call-by-ref values to - * the respective numbers and returns true. Otherwise, it returns - * false and does not set any values. - * @param $string string input time representation, e.g. "134523" - * @param $hours integer between 0 and 24 - * @param $minutes integer between 0 and 59 - * @param $seconds integer between 0 and 59, or false if not given - * @return boolean stating if the parsing succeeded - */ - protected static function parseMilTimeString( $string, &$hours, &$minutes, &$seconds ) { - if ( !preg_match( "/^([0-2][0-9])([0-5][0-9])([0-5][0-9])?$/u", $string, $match ) ) { - return false; - } else { - $nhours = intval( $match[1] ); - $nminutes = $match[2] ? intval( $match[2] ) : false; - $nseconds = ( ( count( $match ) > 3 ) && $match[3] ) ? intval( $match[3] ) : false; - if ( ( $nhours < 25 ) && ( ( $nhours < 24 ) || ( $nminutes + $nseconds == 0 ) ) ) { - $hours = $nhours; - $minutes = $nminutes; - $seconds = $nseconds; - return true; - } else { - return false; - } - } - } - - /** - * Parse the given string to check if it refers to the string name ot - * abbreviation of a month name. If yes, it is replaced by a normalized - * month name (placed in the call-by-ref parameter) and true is - * returned. Otherwise, false is returned and $monthname is not changed. - * @param $string string month name or abbreviation to parse - * @param $monthname string with standard 3-letter English month abbreviation - * @return boolean stating whether a month was found - */ - protected static function parseMonthString( $string, &$monthname ) { - /** - * @var SMWLanguage $smwgContLang - */ - global $smwgContLang; - - $monthnum = $smwgContLang->findMonth( $string ); // takes precedence over English month names! - - if ( $monthnum !== false ) { - $monthnum -= 1; - } else { - $monthnum = array_search( $string, self::$m_months ); // check English names - } - - if ( $monthnum !== false ) { - $monthname = self::$m_monthsshort[ $monthnum ]; - return true; - } elseif ( array_search( $string, self::$m_monthsshort ) !== false ) { - $monthname = $string; - return true; - } else { - return false; - } - } - - /** - * Validate and interpret the date components as retrieved when parsing - * a user input. The method takes care of guessing how a list of values - * such as "10 12 13" is to be interpreted using the current language - * settings. The result is stored in the call-by-ref parameter - * $date that uses keys 'y', 'm', 'd' and contains the respective - * numbers as values, or false if not specified. If errors occur, error - * messages are added to the objects list of errors, and false is - * returned. Otherwise, true is returned. - * @param $datecomponents array of strings that might belong to the specification of a date - * @param $date array set to result - * @return boolean stating if successful - */ - protected function interpretDateComponents( $datecomponents, &$date ) { - global $smwgContLang; - // The following code segment creates a bit vector to encode - // which role each digit of the entered date can take (day, - // year, month). The vector starts with 1 and contains three - // bits per date component, set ot true whenever this component - // could be a month, a day, or a year (this is the order). - // Examples: - // 100 component could only be a month - // 010 component could only be a day - // 001 component could only be a year - // 011 component could be a day or a year but no month etc. - // For three components, we thus get a 10 digit bit vector. - $datevector = 1; - $propercomponents = array(); - $justfounddash = true; // avoid two dashes in a row, or dashes at the end - $error = false; - $numvalue = 0; - foreach ( $datecomponents as $component ) { - if ( $component == "-" ) { - if ( $justfounddash ) { - $error = true; - break; - } - $justfounddash = true; - } else { - $justfounddash = false; - $datevector = ( $datevector << 3 ) | $this->checkDateComponent( $component, $numvalue ); - $propercomponents[] = $numvalue; - } - } - if ( ( $error ) || ( $justfounddash ) || ( count( $propercomponents ) == 0 ) || ( count( $propercomponents ) > 3 ) ) { - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - return false; - } - // Now use the bitvector to find the preferred interpretation of the date components: - $dateformats = $smwgContLang->getDateFormats(); - $date = array( 'y' => false, 'm' => false, 'd' => false ); - foreach ( $dateformats[count( $propercomponents ) - 1] as $formatvector ) { - if ( !( ~$datevector & $formatvector ) ) { // check if $formatvector => $datevector ("the input supports the format") - $i = 0; - foreach ( self::$m_formats[$formatvector] as $fieldname ) { - $date[$fieldname] = $propercomponents[$i]; - $i += 1; - } - break; - } - } - if ( $date['y'] === false ) { // no band matches the entered date - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - return false; - } - return true; - } - - /** - * Initialise data from the provided intermediate results after - * parsing, assuming that a conventional date notation is used. - * If errors occur, error messages are added to the objects list of - * errors, and false is returned. Otherwise, true is returned. - * @param $datecomponents array of strings that might belong to the specification of a date - * @param $calendarmodesl string if model was set in input, otherwise false - * @param $era string '+' or '-' if provided, otherwise false - * @param $hours integer value between 0 and 24 - * @param $minutes integer value between 0 and 59 - * @param $seconds integer value between 0 and 59, or false if not given - * @param $timeoffset double value for time offset (e.g. 3.5), or false if not given - * @return boolean stating if successful - */ - protected function setDateFromParsedValues( $datecomponents, $calendarmodel, $era, $hours, $minutes, $seconds, $timeoffset ) { - $date = false; - if ( !$this->interpretDateComponents( $datecomponents, $date ) ) { - return false; - } - - // Handle BC: the year is negative. - if ( ( $era == '-' ) && ( $date['y'] > 0 ) ) { // see class documentation on BC, "year 0", and ISO conformance ... - $date['y'] = -( $date['y'] ); - } - // Old Style is a special case of Julian calendar model where the change of the year was 25 March: - if ( ( $calendarmodel == 'OS' ) && - ( ( $date['m'] < 3 ) || ( ( $date['m'] == 3 ) && ( $date['d'] < 25 ) ) ) ) { - $date['y']++; - } - - $calmod = $this->getCalendarModel( $calendarmodel, $date['y'], $date['m'], $date['d'] ); - try { - $this->m_dataitem = new SMWDITime( $calmod, $date['y'], $date['m'], $date['d'], $hours, $minutes, $seconds, $this->m_typeid ); - } catch ( SMWDataItemException $e ) { - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - return false; - } - - // Having more than years or specifying a calendar model does - // not make sense for prehistoric dates, and our calendar - // conversion would not be reliable if JD numbers get too huge: - if ( ( $date['y'] <= self::PREHISTORY ) && - ( ( $this->m_dataitem->getPrecision() > SMWDITime::PREC_Y ) || ( $calendarmodel !== false ) ) ) { - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - return false; - } - if ( $timeoffset != 0 ) { - $newjd = $this->m_dataitem->getJD() - $timeoffset / 24; - try { - $this->m_dataitem = SMWDITime::newFromJD( $newjd, $calmod, $this->m_dataitem->getPrecision(), $this->m_typeid ); - } catch ( SMWDataItemException $e ) { - $this->addError( wfMessage( 'smw_nodatetime', $this->m_wikivalue )->inContentLanguage()->text() ); - return false; - } - } - return true; - } - - /** - * Check which roles a string component might play in a date, and - * set the call-by-ref parameter to the proper numerical - * representation. The component string has already been normalized to - * be either a plain number, a month name, or a plain number with "d" - * pre-pended. The result is a bit vector to indicate the possible - * interpretations. - * @param $component string - * @param $numvalue integer representing the components value - * @return integer that encodes a three-digit bit vector - */ - protected static function checkDateComponent( $component, &$numvalue ) { - if ( $component === '' ) { // should not happen - $numvalue = 0; - return 0; - } elseif ( is_numeric( $component ) ) { - $numvalue = intval( $component ); - if ( ( $numvalue >= 1 ) && ( $numvalue <= 12 ) ) { - return SMW_DAY_MONTH_YEAR; // can be a month, day or year - } elseif ( ( $numvalue >= 1 ) && ( $numvalue <= 31 ) ) { - return SMW_DAY_YEAR; // can be day or year - } else { // number can just be a year - return SMW_YEAR; - } - } elseif ( $component { 0 } == 'd' ) { // already marked as day - if ( is_numeric( substr( $component, 1 ) ) ) { - $numvalue = intval( substr( $component, 1 ) ); - return ( ( $numvalue >= 1 ) && ( $numvalue <= 31 ) ) ? SMW_DAY : 0; - } else { - return 0; - } - } else { - $monthnum = array_search( $component, self::$m_monthsshort ); - if ( $monthnum !== false ) { - $numvalue = $monthnum + 1; - return SMW_MONTH; - } else { - return 0; - } - } - } - - /** - * Determine the calender model under which an input should be - * interpreted based on the given input data. - * @param $presetmodel mixed string related to a user input calendar model (OS, Jl, Gr) or false - * @param $year integer of the given year (adjusted for BC(E), i.e. possibly negative) - * @param $month mixed integer of the month or false - * @param $day mixed integer of the day or false - * @return integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - */ - protected function getCalendarModel( $presetmodel, $year, $month, $day ) { - if ( $presetmodel == 'OS' ) { // Old Style is a notational convention of Julian dates only - $presetmodel = 'Jl'; - } - if ( $presetmodel == 'Gr' ) { - return SMWDITime::CM_GREGORIAN; - } elseif ( $presetmodel == 'Jl' ) { - return SMWDITime::CM_JULIAN; - } - if ( ( $year > 1582 ) || - ( ( $year == 1582 ) && ( $month > 10 ) ) || - ( ( $year == 1582 ) && ( $month == 10 ) && ( $day > 4 ) ) ) { - return SMWDITime::CM_GREGORIAN; - } elseif ( $year > self::PREHISTORY ) { - return SMWDITime::CM_JULIAN; - } else { - // proleptic Julian years at some point deviate from the count of complete revolutions of the earth around the sun - // hence assume that earlier date years are Gregorian (where this effect is very weak only) - // This is mostly for internal use since we will not allow users to specify calendar models at this scale - return SMWDITime::CM_GREGORIAN; - } - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_TIME ) { - $this->m_dataitem = $dataItem; - $this->m_caption = $this->m_wikivalue = false; - return true; - } else { - return false; - } - } - - public function getShortWikiText( $linked = NULL ) { - if ( $this->isValid() ) { - return ( $this->m_caption !== false ) ? $this->m_caption : $this->getPreferredCaption(); - } else { - return $this->getErrorText(); - } - } - - public function getShortHTMLText( $linker = NULL ) { - return $this->getShortWikiText( $linker ); // safe in HTML - } - - public function getLongWikiText( $linked = NULL ) { - return $this->isValid() ? $this->getPreferredCaption() : $this->getErrorText(); - } - - public function getLongHTMLText( $linker = NULL ) { - return $this->getLongWikiText( $linker ); // safe in HTML - } - - /// @todo The preferred caption may not be suitable as a wiki value (i.e. not parsable). - public function getWikiValue() { - return $this->m_wikivalue ? $this->m_wikivalue : $this->getPreferredCaption(); - } - - public function isNumeric() { - return true; - } - - /** - * Return the year number in the given calendar model, or false if - * this number is not available (typically when attempting to get - * prehistoric Julian calendar dates). As everywhere in this class, - * there is no year 0. - * @param $calendarmodel integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @return mixed typically a number but possibly false - */ - public function getYear( $calendarmodel = SMWDITime::CM_GREGORIAN ) { - $di = $this->getDataForCalendarModel( $calendarmodel ); - if ( !is_null( $di ) ) { - return $di->getYear(); - } else { - return false; - } - } - - /** - * Return the month number in the given calendar model, or false if - * this number is not available (typically when attempting to get - * prehistoric Julian calendar dates). - * @param $calendarmodel integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @param $default value to return if month is not set at our level of precision - * @return mixed typically a number but possibly anything given as $default - */ - public function getMonth( $calendarmodel = SMWDITime::CM_GREGORIAN, $default = 1 ) { - $di = $this->getDataForCalendarModel( $calendarmodel ); - if ( !is_null( $di ) ) { - return ( $di->getPrecision() >= SMWDITime::PREC_YM ) ? $di->getMonth() : $default; - } else { - return false; - } - } - - /** - * Return the day number in the given calendar model, or false if this - * number is not available (typically when attempting to get - * prehistoric Julian calendar dates). - * @param $calendarmodel integer either SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @param $default value to return if day is not set at our level of precision - * @return mixed typically a number but possibly anything given as $default - */ - public function getDay( $calendarmodel = SMWDITime::CM_GREGORIAN, $default = 1 ) { - $di = $this->getDataForCalendarModel( $calendarmodel ); - if ( !is_null( $di ) ) { - return ( $di->getPrecision() >= SMWDITime::PREC_YMD ) ? $di->getDay() : $default; - } else { - return false; - } - } - - /** - * Return the time as a string. The time string has the format HH:MM:SS, - * without any timezone information (see class documentation for details - * on current timezone handling). - * The parameter $default optionally specifies the value returned - * if the date is valid but has no explicitly specified time. It can - * also be set to false to detect this situation. - */ - public function getTimeString( $default = '00:00:00' ) { - if ( $this->m_dataitem->getPrecision() < SMWDITime::PREC_YMDT ) { - return $default; - } else { - return sprintf( "%02d", $this->m_dataitem->getHour() ) . ':' . - sprintf( "%02d", $this->m_dataitem->getMinute() ) . ':' . - sprintf( "%02d", $this->m_dataitem->getSecond() ); - } - } - - /** - * @deprecated This method is now called getISO8601Date(). It will vanish before SMW 1.7. - */ - public function getXMLSchemaDate( $mindefault = true ) { - return $this->getISO8601Date( $mindefault ); - } - - /** - * Compute a string representation that largely follows the ISO8601 - * standard of representing dates. Large year numbers may have more - * than 4 digits, which is not strictly conforming to the standard. - * The date includes year, month, and day regardless of the input - * precision, but will only include time when specified. - * - * Conforming to the 2000 version of ISO8601, year 1 BC(E) is - * represented as "0000", year 2 BC(E) as "-0001" and so on. - * - * @param $mindefault boolean determining whether values below the - * precision of our input should be completed with minimal or maximal - * conceivable values - * @return string - */ - public function getISO8601Date( $mindefault = true ) { - $result = ( $this->getYear() > 0 ) ? '' : '-'; - $monthnum = $this->getMonth( SMWDITime::CM_GREGORIAN, ( $mindefault ? 1 : 12 ) ); - $result .= str_pad( $this->getYear(), 4, "0", STR_PAD_LEFT ) . - '-' . str_pad( $monthnum, 2, "0", STR_PAD_LEFT ); - if ( !$mindefault && ( $this->m_dataitem->getPrecision() < SMWDITime::PREC_YMD ) ) { - $maxday = SMWDITime::getDayNumberForMonth( $monthnum, $this->getYear(), SMWDITime::CM_GREGORIAN ); - $result .= '-' . str_pad( $this->getDay( SMWDITime::CM_GREGORIAN, $maxday ), 2, "0", STR_PAD_LEFT ); - } else { - $result .= '-' . str_pad( $this->getDay(), 2, "0", STR_PAD_LEFT ); - } - if ( $this->m_dataitem->getPrecision() == SMWDITime::PREC_YMDT ) { - $result .= 'T' . $this->getTimeString( ( $mindefault ? '00:00:00' : '23:59:59' ) ); - } - return $result; - } - - /** - * Use MediaWiki's date and time formatting. It can't handle all inputs - * properly, but has superior i18n support. - * - * @return string - */ - public function getMediaWikiDate() { - global $wgContLang; - - $dataitem = $this->m_dataitem; - $precision = $dataitem->getPrecision(); - - $year = $this->getYear(); - if ( $year < 0 || $year > 9999 ) $year = '0000'; - $year = str_pad( $year, 4, "0", STR_PAD_LEFT ); - - if ( $precision <= SMWDITime::PREC_Y ) { - return $wgContLang->formatNum( $year, true ); - } - - $month = str_pad( $this->getMonth( SMWDITime::CM_GREGORIAN ), 2, "0", STR_PAD_LEFT ); - $day = str_pad( $this->getDay( SMWDITime::CM_GREGORIAN ), 2, "0", STR_PAD_LEFT ); - - if ( $precision <= SMWDITime::PREC_YMD ) { - return $wgContLang->date( "$year$month$day" . '000000', false, false ); - } - - $time = str_replace( ':', '', $this->getTimeString() ); - return $wgContLang->timeanddate( "$year$month$day$time", false, false ); - } - - /** - * Get the current data in the specified calendar model. Conversion is - * not done for prehistoric dates (where it might lead to precision - * errors and produce results that are not meaningful). In this case, - * null might be returned if no data in the specified format is - * available. - * @param $calendarmodel integer one of SMWDITime::CM_GREGORIAN or SMWDITime::CM_JULIAN - * @return SMWDITime - */ - protected function getDataForCalendarModel( $calendarmodel ) { - if ( $this->m_dataitem->getYear() <= self::PREHISTORY ) { - return ( $this->m_dataitem->getCalendarModel() == $calendarmodel ) ? $this->m_dataitem : null; - } elseif ( $calendarmodel == SMWDITime::CM_GREGORIAN ) { - if ( is_null( $this->m_dataitem_greg ) ) { - $this->m_dataitem_greg = $this->m_dataitem->getForCalendarModel( SMWDITime::CM_GREGORIAN ); - } - return $this->m_dataitem_greg; - } else { - if ( is_null( $this->m_dataitem_jul ) ) { - $this->m_dataitem_jul = $this->m_dataitem->getForCalendarModel( SMWDITime::CM_JULIAN ); - } - return $this->m_dataitem_jul; - } - } - - /** - * Compute a suitable string to display the given date item. - * @note MediaWiki's date functions are not applicable for the range of historic dates we support. - * - * @since 1.6 - * - * @param SMWDITime $dataitem - * - * @return string - * @todo Internationalize the CE and BCE strings. - */ - public function getCaptionFromDataitem( SMWDITime $dataitem ) { - /** - * @var SMWLanguage $smwgContLang - */ - global $smwgContLang; - - if ( $dataitem->getYear() > 0 ) { - $cestring = ''; - $result = number_format( $dataitem->getYear(), 0, '.', '' ) . ( $cestring ? ( ' ' . $cestring ) : '' ); - } else { - $bcestring = 'BC'; - $result = number_format( -( $dataitem->getYear() ), 0, '.', '' ) . ( $bcestring ? ( ' ' . $bcestring ) : '' ); - } - - if ( $dataitem->getPrecision() >= SMWDITime::PREC_YM ) { - $result = $smwgContLang->getMonthLabel( $dataitem->getMonth() ) . " " . $result; - } - - if ( $dataitem->getPrecision() >= SMWDITime::PREC_YMD ) { - $result = $dataitem->getDay() . " " . $result; - } - - if ( $dataitem->getPrecision() >= SMWDITime::PREC_YMDT ) { - $result .= " " . $this->getTimeString(); - } - - return $result; - } - - /** - * Compute a suitable string to display this date, taking into account - * the output format and the preferrable calendar models for the data. - * @note MediaWiki's date functions are not applicable for the range of historic dates we support. - * @return string - */ - protected function getPreferredCaption() { - $year = $this->m_dataitem->getYear(); - $format = strtoupper( $this->m_outformat ); - - if ( $format == 'ISO' || $this->m_outformat == '-' ) { - return $this->getISO8601Date(); - } elseif ( $format == 'MEDIAWIKI' ) { - return $this->getMediaWikiDate(); - } elseif ( $format == 'SORTKEY' ) { - return $this->m_dataitem->getSortKey(); - } elseif ( $year > self::PREHISTORY && $this->m_dataitem->getPrecision() >= SMWDITime::PREC_YM ) { - // Do not convert between Gregorian and Julian if only - // year is given (years largely overlap in history, but - // assuming 1 Jan as the default date, the year number - // would change in conversion). - // Also do not convert calendars in prehistory: not - // meaningful (getDataForCalendarModel may return null). - if ( ( $format == 'JL' ) || - ( $this->m_dataitem->getJD() < self::J1582 - && $format != 'GR' ) ) { - $model = SMWDITime::CM_JULIAN; - } else { - $model = SMWDITime::CM_GREGORIAN; - } - return $this->getCaptionFromDataitem( $this->getDataForCalendarModel( $model ) ); - } else { - return $this->getCaptionFromDataitem( $this->m_dataitem ); - } - } -} diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_Types.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_Types.php deleted file mode 100644 index 7a781e53..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_Types.php +++ /dev/null @@ -1,182 +0,0 @@ -<?php - -use SMW\DataTypeRegistry; - -/** - * This datavalue implements special processing suitable for defining types of - * properties. Types behave largely like values of type SMWWikiPageValue - * with three main differences. First, they actively check if a value is an - * alias for another type, modifying the internal representation accordingly. - * Second, they have a modified display for emphasizing if some type is defined - * in SMW (built-in). Third, they use type ids for storing data (DB keys) - * instead of using page titles. - * - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWTypesValue extends SMWDataValue { - protected $m_isAlias; // record whether this is an alias to another type, used to avoid duplicates when listing page types - protected $m_realLabel; - protected $m_givenLabel; - protected $m_typeId; - - public static function newFromTypeId( $typeId ) { - $result = new SMWTypesValue( '__typ' ); - try { - $dataItem = self::getTypeUriFromTypeId( $typeId ); - } catch ( SMWDataItemException $e ) { - $dataItem = self::getTypeUriFromTypeId( 'notype' ); - } - $result->setDataItem( $dataItem ); - return $result; - } - - public static function getTypeUriFromTypeId( $typeId ) { - return new SMWDIUri( 'http', 'semantic-mediawiki.org/swivt/1.0', '', $typeId ); - } - - protected function parseUserValue( $value ) { - global $wgContLang, $smwgHistoricTypeNamespace; - - if ( $this->m_caption === false ) { - $this->m_caption = $value; - } - - $valueParts = explode( ':', $value, 2 ); - if ( $smwgHistoricTypeNamespace && count( $valueParts ) > 1 ) { - $namespace = smwfNormalTitleText( $valueParts[0] ); - $value = $valueParts[1]; - $typeNamespace = $wgContLang->getNsText( SMW_NS_TYPE ); - if ( $namespace != $typeNamespace ) { - $this->addError( wfMessage( 'smw_wrong_namespace', $typeNamespace )->inContentLanguage()->text() ); - } - } - - $this->m_givenLabel = smwfNormalTitleText( $value ); - $this->m_typeId = DataTypeRegistry::getInstance()->findTypeId( $this->m_givenLabel ); - if ( $this->m_typeId === '' ) { - $this->addError( wfMessage( 'smw_unknowntype', $this->m_givenLabel )->inContentLanguage()->text() ); - $this->m_realLabel = $this->m_givenLabel; - } else { - $this->m_realLabel = DataTypeRegistry::getInstance()->findTypeLabel( $this->m_typeId ); - } - $this->m_isAlias = ( $this->m_realLabel === $this->m_givenLabel ) ? false : true; - - try { - $this->m_dataitem = self::getTypeUriFromTypeId( $this->m_typeId ); - } catch ( SMWDataItemException $e ) { - $this->m_dataitem = self::getTypeUriFromTypeId( 'notype' ); - $this->addError( wfMessage( 'smw_parseerror' )->inContentLanguage()->text() ); - } - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( ( $dataItem instanceof SMWDIUri ) && ( $dataItem->getScheme() == 'http' ) && - ( $dataItem->getHierpart() == 'semantic-mediawiki.org/swivt/1.0' ) && - ( $dataItem->getQuery() === '' ) ) { - $this->m_isAlias = false; - $this->m_typeId = $dataItem->getFragment(); - $this->m_realLabel = DataTypeRegistry::getInstance()->findTypeLabel( $this->m_typeId ); - $this->m_caption = $this->m_givenLabel = $this->m_realLabel; - $this->m_dataitem = $dataItem; - return true; - } else { - return false; - } - } - - public function getShortWikiText( $linker = null ) { - global $wgContLang; - if ( !$linker || $this->m_outformat === '-' || $this->m_caption === '' ) { - return $this->m_caption; - } else { - $titleText = $this->getSpecialPageTitleText(); - $namespace = $wgContLang->getNsText( NS_SPECIAL ); - return "[[$namespace:$titleText|{$this->m_caption}]]"; - } - } - - public function getShortHTMLText( $linker = null ) { - if ( !$linker || $this->m_outformat === '-' || $this->m_caption === '' ) { - return htmlspecialchars( $this->m_caption ); - } else { - $title = Title::makeTitle( NS_SPECIAL, $this->getSpecialPageTitleText() ); - return $linker->link( $title, htmlspecialchars( $this->m_caption ) ); - } - } - - public function getLongWikiText( $linker = null ) { - global $wgContLang; - if ( !$linker || $this->m_realLabel === '' ) { - return $this->m_realLabel; - } else { - $titleText = $this->getSpecialPageTitleText(); - $namespace = $wgContLang->getNsText( NS_SPECIAL ); - return "[[$namespace:$titleText|{$this->m_realLabel}]]"; - } - } - - public function getLongHTMLText( $linker = null ) { - if ( !$linker || $this->m_realLabel === '' ) { - return htmlspecialchars( $this->m_realLabel ); - } else { - $title = Title::makeTitle( NS_SPECIAL, $this->getSpecialPageTitleText() ); - return $linker->link( $title, htmlspecialchars( $this->m_realLabel ) ); - } - } - - /** - * Gets the title text for the types special page. - * - * @since 1.6 - * - * @return string - */ - protected function getSpecialPageTitleText() { - return SpecialPageFactory::getLocalNameFor( 'Types', $this->m_realLabel ); - } - - public function getWikiValue() { - return $this->m_realLabel; - } - - public function getHash() { - return $this->m_realLabel; - } - - /** - * This class uses type ids as DB keys. - * - * @return string - */ - public function getDBkey() { - return ( $this->isValid() ) ? DataTypeRegistry::getInstance()->findTypeID( $this->m_realLabel ) : ''; - } - - /** - * Is this a built-in datatype shipped with SMW (or an extension of SMW)? - * (Alternatively it would be a user-defined derived datatype.) - * - * @deprecated As of SMW 1.6, there are no more user-defined datatypes, making this method useless. Will vanish in SMW 1.6. - */ - public function isBuiltIn() { - return true; - } - - /** - * Is this an alias for another datatype in SMW? This information is used to - * explain entries in Special:Types that are found since they have pages. - * - * @return boolean - */ - public function isAlias() { - return $this->m_isAlias; - } - -} - diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_URI.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_URI.php deleted file mode 100644 index ed3f651c..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_URI.php +++ /dev/null @@ -1,299 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -define( 'SMW_URI_MODE_EMAIL', 1 ); -define( 'SMW_URI_MODE_URI', 3 ); -define( 'SMW_URI_MODE_ANNOURI', 4 ); -define( 'SMW_URI_MODE_TEL', 5 ); - -/** - * This datavalue implements URL/URI/ANNURI/PHONE/EMAIL datavalues suitable for - * defining the respective types of properties. - * - * @author Nikolas Iwan - * @author Markus Krötzsch - * @ingroup SMWDataValues - * @bug Correctly create safe HTML and Wiki text. - */ -class SMWURIValue extends SMWDataValue { - - /** - * The value as returned by getWikitext() and getLongText(). - * @var string - */ - protected $m_wikitext; - /** - * One of the basic modes of operation for this class (emails, URL, - * telephone number URI, ...). - * @var integer - */ - private $m_mode; - - public function __construct( $typeid ) { - parent::__construct( $typeid ); - switch ( $typeid ) { - case '_ema': - $this->m_mode = SMW_URI_MODE_EMAIL; - break; - case '_anu': - $this->m_mode = SMW_URI_MODE_ANNOURI; - break; - case '_tel': - $this->m_mode = SMW_URI_MODE_TEL; - break; - case '_uri': case '_url': case '__spu': default: - $this->m_mode = SMW_URI_MODE_URI; - break; - } - } - - protected function parseUserValue( $value ) { - $value = trim( $value ); - $this->m_wikitext = $value; - if ( $this->m_caption === false ) { - $this->m_caption = $this->m_wikitext; - } - - $scheme = $hierpart = $query = $fragment = ''; - if ( $value === '' ) { // do not accept empty strings - $this->addError( wfMessage( 'smw_emptystring' )->inContentLanguage()->text() ); - return; - } - - switch ( $this->m_mode ) { - case SMW_URI_MODE_URI: case SMW_URI_MODE_ANNOURI: - $parts = explode( ':', $value, 2 ); // try to split "schema:rest" - if ( count( $parts ) == 1 ) { // possibly add "http" as default - $value = 'http://' . $value; - $parts[1] = $parts[0]; - $parts[0] = 'http'; - } - // check against blacklist - $uri_blacklist = explode( "\n", wfMessage( 'smw_uri_blacklist' )->inContentLanguage()->text() ); - foreach ( $uri_blacklist as $uri ) { - $uri = trim( $uri ); - if ( $uri == mb_substr( $value, 0, mb_strlen( $uri ) ) ) { // disallowed URI! - $this->addError( wfMessage( 'smw_baduri', $value )->inContentLanguage()->text() ); - return; - } - } - // decompose general URI components - $scheme = $parts[0]; - $parts = explode( '?', $parts[1], 2 ); // try to split "hier-part?queryfrag" - if ( count( $parts ) == 2 ) { - $hierpart = $parts[0]; - $parts = explode( '#', $parts[1], 2 ); // try to split "query#frag" - $query = $parts[0]; - $fragment = ( count( $parts ) == 2 ) ? $parts[1] : ''; - } else { - $query = ''; - $parts = explode( '#', $parts[0], 2 ); // try to split "hier-part#frag" - $hierpart = $parts[0]; - $fragment = ( count( $parts ) == 2 ) ? $parts[1] : ''; - } - // We do not validate the URI characters (the data item will do this) but we do some escaping: - // encode most characters, but leave special symbols as given by user: - $hierpart = str_replace( array( '%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25' ), array( ':', '/', '#', '@', '?', '=', '&', '%' ), rawurlencode( $hierpart ) ); - $query = str_replace( array( '%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25' ), array( ':', '/', '#', '@', '?', '=', '&', '%' ), rawurlencode( $query ) ); - $fragment = str_replace( array( '%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25' ), array( ':', '/', '#', '@', '?', '=', '&', '%' ), rawurlencode( $fragment ) ); - /// NOTE: we do not support raw [ (%5D) and ] (%5E), although they are needed for ldap:// (but rarely in a wiki) - /// NOTE: "+" gets encoded, as it is interpreted as space by most browsers when part of a URL; - /// this prevents tel: from working directly, but we have a datatype for this anyway. - - if ( substr( $hierpart, 0, 2 ) === '//' ) { - $hierpart = substr( $hierpart, 2 ); - } - break; - case SMW_URI_MODE_TEL: - $scheme = 'tel'; - if ( substr( $value, 0, 4 ) === 'tel:' ) { // accept optional "tel" - $value = substr( $value, 4 ); - $this->m_wikitext = $value; - } - $hierpart = preg_replace( '/(?<=[0-9]) (?=[0-9])/', '\1-\2', $value ); - $hierpart = str_replace( ' ', '', $hierpart ); - if ( substr( $hierpart, 0, 2 ) == '00' ) { - $hierpart = '+' . substr( $hierpart, 2 ); - } - if ( ( strlen( preg_replace( '/[^0-9]/', '', $hierpart ) ) < 6 ) || - ( preg_match( '<[-+./][-./]>', $hierpart ) ) || - ( !SMWURIValue::isValidTelURI( 'tel:' . $hierpart ) ) ) { /// TODO: introduce error-message for "bad" phone number - $this->addError( wfMessage( 'smw_baduri', $this->m_wikitext )->inContentLanguage()->text() ); - return; - } - break; - case SMW_URI_MODE_EMAIL: - $scheme = 'mailto'; - if ( strpos( $value, 'mailto:' ) === 0 ) { // accept optional "mailto" - $value = substr( $value, 7 ); - $this->m_wikitext = $value; - } - - $check = Sanitizer::validateEmail( $value ); - if ( !$check ) { - /// TODO: introduce error-message for "bad" email - $this->addError( wfMessage( 'smw_baduri', $value )->inContentLanguage()->text() ); - return; - } - $hierpart = str_replace( array( '%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25' ), array( ':', '/', '#', '@', '?', '=', '&', '%' ), rawurlencode( $value ) ); - } - - // Now create the URI data item: - try { - $this->m_dataitem = new SMWDIUri( $scheme, $hierpart, $query, $fragment, $this->m_typeid ); - } catch ( SMWDataItemException $e ) { - $this->addError( wfMessage( 'smw_baduri', $this->m_wikitext )->inContentLanguage()->text() ); - } - } - - /** - * Returns true if the argument is a valid RFC 3966 phone number. - * Only global phone numbers are supported, and no full validation - * of parameters (appended via ;param=value) is performed. - */ - protected static function isValidTelURI( $s ) { - $tel_uri_regex = '<^tel:\+[0-9./-]*[0-9][0-9./-]*(;[0-9a-zA-Z-]+=(%[0-9a-zA-Z][0-9a-zA-Z]|[0-9a-zA-Z._~:/?#[\]@!$&\'()*+,;=-])*)*$>'; - return (bool) preg_match( $tel_uri_regex, $s ); - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_URI ) { - $this->m_dataitem = $dataItem; - if ( $this->m_mode == SMW_URI_MODE_EMAIL ) { - $this->m_wikitext = substr( $dataItem->getURI(), 7 ); - } elseif ( $this->m_mode == SMW_URI_MODE_TEL ) { - $this->m_wikitext = substr( $dataItem->getURI(), 4 ); - } else { - $this->m_wikitext = $dataItem->getURI(); - } - $this->m_caption = $this->m_wikitext; - return true; - } else { - return false; - } - } - - public function getShortWikiText( $linked = null ) { - $url = $this->getURL(); - if ( is_null( $linked ) || ( $linked === false ) || ( $url === '' ) || - ( $this->m_outformat == '-' ) || ( $this->m_caption === '' ) ) { - return $this->m_caption; - } elseif ( $this->m_outformat == 'nowiki' ) { - return $this->makeNonlinkedWikiText( $this->m_caption ); - } else { - return '[' . $url . ' ' . $this->m_caption . ']'; - } - } - - public function getShortHTMLText( $linker = null ) { - $url = $this->getURL(); - if ( is_null( $linker ) || ( !$this->isValid() ) || ( $url === '' ) || - ( $this->m_outformat == '-' ) || ( $this->m_outformat == 'nowiki' ) || - ( $this->m_caption === '' ) ) { - return $this->m_caption; - } else { - return $linker->makeExternalLink( $url, $this->m_caption ); - } - } - - public function getLongWikiText( $linked = null ) { - if ( !$this->isValid() ) { - return $this->getErrorText(); - } - $url = $this->getURL(); - - if ( is_null( $linked ) || ( $linked === false ) || ( $url === '' ) || - ( $this->m_outformat == '-' ) ) { - return $this->m_wikitext; - } elseif ( $this->m_outformat == 'nowiki' ) { - return $this->makeNonlinkedWikiText( $this->m_wikitext ); - } else { - return '[' . $url . ' ' . $this->m_wikitext . ']'; - } - } - - public function getLongHTMLText( $linker = null ) { - if ( !$this->isValid() ) { - return $this->getErrorText(); - } - - $url = $this->getURL(); - - if ( is_null( $linker ) || ( !$this->isValid() ) || ( $url === '' ) || - ( $this->m_outformat == '-' ) || ( $this->m_outformat == 'nowiki' ) ) { - return htmlspecialchars( $this->m_wikitext ); - } else { - return $linker->makeExternalLink( $url, $this->m_wikitext ); - } - } - - public function getWikiValue() { - return $this->m_wikitext; - } - - public function getURI() { - return $this->getUriDataitem()->getURI(); - } - - protected function getServiceLinkParams() { - // Create links to mapping services based on a wiki-editable message. The parameters - // available to the message are: - // $1: urlencoded version of URI/URL value (includes mailto: for emails) - return array( rawurlencode( $this->getUriDataitem()->getURI() ) ); - } - - /** - * Get a URL for hyperlinking this URI, or the empty string if this URI - * is not hyperlinked in MediaWiki. - * @return string - */ - public function getURL() { - global $wgUrlProtocols; - - foreach ( $wgUrlProtocols as $prot ) { - if ( ( $prot == $this->getUriDataitem()->getScheme() . ':' ) || ( $prot == $this->getUriDataitem()->getScheme() . '://' ) ) { - return $this->getUriDataitem()->getURI(); - } - } - - return ''; - } - - /** - * Helper function to get the current dataitem, or some dummy URI - * dataitem if the dataitem was not set. This makes it easier to - * write code that avoids errors even if the data was not - * initialized properly. - * @return SMWDIUri - */ - protected function getUriDataitem() { - if ( isset( $this->m_dataitem ) ) { - return $this->m_dataitem; - } else { // note: use "noprotocol" to avoid accidental use in an MW link, see getURL() - return new SMWDIUri( 'noprotocol', 'x', '', '', $this->m_typeid ); - } - } - - /** - * Helper function that changes a URL string in such a way that it - * can be used in wikitext without being turned into a hyperlink, - * while still displaying the same characters. The use of - * <nowiki> is avoided, since the resulting strings may be - * inserted during parsing, after this has been stripped. - * - * @since 1.8 - */ - protected function makeNonlinkedWikiText( $url ) { - return str_replace( ':', ':', $url ); - } - -} - diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php b/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php deleted file mode 100644 index 8260c908..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php +++ /dev/null @@ -1,532 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataValues - */ - -/** - * This datavalue implements special processing suitable for defining - * wikipages as values of properties. - * - * The class can support general wiki pages, or pages of a fixed - * namespace, Whether a namespace is fixed is decided based on the - * type ID when the object is constructed. - * - * The short display simulates the behavior of the MediaWiki "pipe trick" - * but always includes fragments. This can be overwritten by setting a - * caption, which is also done by default when generating a value from user - * input. The long display always includes all relevant information. Only if a - * fixed namespace is used for the datatype, the namespace prefix is omitted. - * This behavior has changed in SMW 1.7: up to this time, short displays have - * always inlcuded the namespace and long displays used the pipe trick, leading - * to a paradoxical confusion of "long" and "short". - * - * @author Nikolas Iwan - * @author Markus Krötzsch - * @ingroup SMWDataValues - */ -class SMWWikiPageValue extends SMWDataValue { - - /** - * Fragment text for user-specified title. Not stored, but kept for - * printout on page. - * @var string - */ - protected $m_fragment = ''; - - /** - * Full titletext with prefixes, including interwiki prefix. - * Set to empty string if not computed yet. - * @var string - */ - protected $m_prefixedtext = ''; - - /** - * Cache for the related MW page ID. - * Set to -1 if not computed yet. - * @var integer - */ - protected $m_id = -1; - - /** - * Cache for the related MW title object. - * Set to null if not computed yet. - * @var Title - */ - protected $m_title = null; - - /** - * If this has a value other than NS_MAIN, the datavalue will only - * accept pages in this namespace. This field is initialized when - * creating the object (based on the type id or base on the preference - * of some subclass); it is not usually changed afterwards. - * @var integer - */ - protected $m_fixNamespace = NS_MAIN; - - public function __construct( $typeid ) { - parent::__construct( $typeid ); - switch ( $typeid ) { - case '__typ': - $this->m_fixNamespace = SMW_NS_TYPE; - break; - case '_wpp' : case '__sup': - $this->m_fixNamespace = SMW_NS_PROPERTY; - break; - case '_wpc' : case '__suc': case '__sin': - $this->m_fixNamespace = NS_CATEGORY; - break; - case '_wpf' : case '__spf': - $this->m_fixNamespace = SF_NS_FORM; - break; - default: // case '_wpg': - $this->m_fixNamespace = NS_MAIN; - } - } - - protected function parseUserValue( $value ) { - global $wgContLang; - - // support inputs like " [[Test]] "; - // note that this only works in pages if $smwgLinksInValues is set to true - $value = ltrim( rtrim( $value, ' ]' ), ' [' ); - - if ( $this->m_caption === false ) { - $this->m_caption = $value; - } - - if ( $value !== '' ) { - if ( $value[0] == '#' ) { - if ( is_null( $this->m_contextPage ) ) { - $this->addError( wfMessage( 'smw_notitle', $value )->inContentLanguage()->text() ); - return; - } else { - $this->m_title = Title::makeTitle( $this->m_contextPage->getNamespace(), - $this->m_contextPage->getDBkey(), substr( $value, 1 ), - $this->m_contextPage->getInterwiki() ); - } - } else { - $this->m_title = Title::newFromText( $value, $this->m_fixNamespace ); - } - - /// TODO: Escape the text so users can see punctuation problems (bug 11666). - if ( is_null( $this->m_title ) ) { - $this->addError( wfMessage( 'smw_notitle', $value )->inContentLanguage()->text() ); - } elseif ( ( $this->m_fixNamespace != NS_MAIN ) && - ( $this->m_fixNamespace != $this->m_title->getNamespace() ) ) { - $this->addError( wfMessage( 'smw_wrong_namespace', - $wgContLang->getNsText( $this->m_fixNamespace ) )->inContentLanguage()->text() ); - } else { - $this->m_fragment = str_replace( ' ', '_', $this->m_title->getFragment() ); - $this->m_prefixedtext = ''; - $this->m_id = -1; // unset id - $this->m_dataitem = SMWDIWikiPage::newFromTitle( $this->m_title, $this->m_typeid ); - } - } else { - $this->addError( wfMessage( 'smw_notitle', $value )->inContentLanguage()->text() ); - } - } - - /** - * @see SMWDataValue::loadDataItem() - * @param $dataitem SMWDataItem - * @return boolean - */ - protected function loadDataItem( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_CONTAINER ) { - // might throw an exception, we just pass it through - $dataItem = $dataItem->getSemanticData()->getSubject(); - } - - if ( $dataItem->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) { - $this->m_dataitem = $dataItem; - $this->m_id = -1; - $this->m_title = null; - $this->m_fragment = $dataItem->getSubobjectName(); - $this->m_prefixedtext = ''; - $this->m_caption = false; // this class can handle this - - if ( ( $this->m_fixNamespace != NS_MAIN ) && - ( $this->m_fixNamespace != $dataItem->getNamespace() ) ) { - global $wgContLang; - $this->addError( wfMessage( 'smw_wrong_namespace', - $wgContLang->getNsText( $this->m_fixNamespace ) )->inContentLanguage()->text() ); - } - return true; - } else { - return false; - } - } - - /** - * Display the value on a wiki page. This is used to display the value - * in the place where it was annotated on a wiki page. The desired - * behavior is that the display in this case looks as if no property - * annotation had been given, i.e. an annotation [[property::page|foo]] - * should display like [[page|foo]] in MediaWiki. But this should lead - * to a link, not to a category assignment. This means that: - * - * (1) If Image: is used (instead of Media:) then let MediaWiki embed - * the image. - * - * (2) If Category: is used, treat it as a page and link to it (do not - * categorize the page) - * - * (3) Preserve everything given after "|" for display (caption, image - * parameters, ...) - * - * (4) Use the (default) caption for display. When the value comes from - * user input, this includes the full value that one would also see in - * MediaWiki. - * - * @param $linked mixed generate links if not null or false - * @return string - */ - public function getShortWikiText( $linked = null ) { - if ( is_null( $linked ) || $linked === false || - $this->m_outformat == '-' || !$this->isValid() || - $this->m_caption === '' ) { - return $this->m_caption !== false ? $this->m_caption : $this->getWikiValue(); - } else { - if ( $this->m_dataitem->getNamespace() == NS_FILE ) { - $linkEscape = ''; - $defaultCaption = '|' . $this->getShortCaptionText() . '|frameless|border|text-top'; - } else { - $linkEscape = ':'; - $defaultCaption = '|' . $this->getShortCaptionText(); - } - if ( $this->m_caption === false ) { - return '[[' . $linkEscape . $this->getWikiLinkTarget() . $defaultCaption . ']]'; - } else { - return '[[' . $linkEscape . $this->getWikiLinkTarget() . '|' . $this->m_caption . ']]'; - } - } - } - - /** - * Display the value as in getShortWikiText() but create HTML. - * The only difference is that images are not embedded. - * - * @param Linker $linker mixed the Linker object to use or null if no linking is desired - * @return string - */ - public function getShortHTMLText( $linker = null ) { - // init the Title object, may reveal hitherto unnoticed errors: - if ( !is_null( $linker ) && $linker !== false && - $this->m_caption !== '' && $this->m_outformat != '-' ) { - $this->getTitle(); - } - - if ( is_null( $linker ) || $linker === false || !$this->isValid() || - $this->m_outformat == '-' || $this->m_caption === '' ) { - - $caption = $this->m_caption === false ? $this->getWikiValue() : $this->m_caption; - return htmlspecialchars( $caption ); - } else { - $caption = $this->m_caption === false ? $this->getShortCaptionText() : $this->m_caption; - $caption = htmlspecialchars( $caption ); - - if ( $this->getNamespace() == NS_MEDIA ) { // this extra case *is* needed - return $linker->makeMediaLinkObj( $this->getTitle(), $caption ); - } else { - return $linker->link( $this->getTitle(), $caption ); - } - } - } - - /** - * Display the "long" value on a wiki page. This behaves largely like - * getShortWikiText() but does not use the caption. Instead, it always - * takes the long display form (wiki value). - * - * @param $linked mixed if true the result will be linked - * @return string - */ - public function getLongWikiText( $linked = null ) { - if ( !$this->isValid() ) { - return $this->getErrorText(); - } - - if ( is_null( $linked ) || $linked === false || $this->m_outformat == '-' ) { - return $this->getWikiValue(); - } elseif ( $this->m_dataitem->getNamespace() == NS_FILE ) { - // Embed images and other files - // Note that the embedded file links to the image, hence needs no additional link text. - // There should not be a linebreak after an impage, just like there is no linebreak after - // other values (whether formatted or not). - return '[[' . $this->getWikiLinkTarget() . '|' . - $this->getLongCaptionText() . '|frameless|border|text-top]]'; - } else { - return '[[:' . $this->getWikiLinkTarget() . '|' . $this->getLongCaptionText() . ']]'; - } - } - - /** - * Display the "long" value in HTML. This behaves largely like - * getLongWikiText() but does not embed images. - * - * @param $linker mixed if a Linker is given, the result will be linked - * @return string - */ - public function getLongHTMLText( $linker = null ) { - // init the Title object, may reveal hitherto unnoticed errors: - if ( !is_null( $linker ) && ( $this->m_outformat != '-' ) ) { - $this->getTitle(); - } - if ( !$this->isValid() ) { - return $this->getErrorText(); - } - - if ( is_null( $linker ) || $this->m_outformat == '-' ) { - return htmlspecialchars( $this->getWikiValue() ); - } elseif ( $this->getNamespace() == NS_MEDIA ) { // this extra case is really needed - return $linker->makeMediaLinkObj( $this->getTitle(), - htmlspecialchars( $this->getLongCaptionText() ) ); - } else { // all others use default linking, no embedding of images here - return $linker->link( $this->getTitle(), - htmlspecialchars( $this->getLongCaptionText() ) ); - } - } - - /** - * Return a string that could be used in an in-page property assignment - * for setting this value. This does not include initial ":" for - * escaping things like Category: links since the property value does - * not include such escapes either. Fragment information is included. - * Namespaces are omitted if a fixed namespace is used, since they are - * not needed in this case when making a property assignment. - * - * @return string - */ - public function getWikiValue() { - return ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText() : $this->getText() ) . - ( $this->m_fragment !== '' ? "#{$this->m_fragment}" : '' ); - } - - public function getHash() { - return $this->isValid() ? $this->getPrefixedText() : implode( "\t", $this->getErrors() ); - } - - /** - * Create links to mapping services based on a wiki-editable message. - * The parameters available to the message are: - * $1: urlencoded article name (no namespace) - * - * @return array - */ - protected function getServiceLinkParams() { - if ( $this->isValid() ) { - return array( rawurlencode( str_replace( '_', ' ', $this->m_dataitem->getDBkey() ) ) ); - } else { - return array(); - } - } - -///// special interface for wiki page values - - /** - * Return according Title object or null if no valid value was set. - * null can be returned even if this object returns true for isValid(), - * since the latter function does not check whether MediaWiki can really - * make a Title out of the given data. - * However, isValid() will return false *after* this function failed in - * trying to create a title. - * - * @return Title - */ - public function getTitle() { - if ( ( $this->isValid() ) && is_null( $this->m_title ) ) { - $this->m_title = $this->m_dataitem->getTitle(); - - if ( is_null( $this->m_title ) ) { // should not normally happen, but anyway ... - global $wgContLang; - $this->addError( wfMessage( - 'smw_notitle', - $wgContLang->getNsText( $this->m_dataitem->getNamespace() ) . ':' . $this->m_dataitem->getDBkey() - )->inContentLanguage()->text() ); - } - } - - return $this->m_title; - } - - /** - * Get MediaWiki's ID for this value or 0 if not available. - * - * @return integer - */ - public function getArticleID() { - if ( $this->m_id === false ) { - $this->m_id = !is_null( $this->getTitle() ) ? $this->m_title->getArticleID() : 0; - } - - return $this->m_id; - } - - /** - * Get namespace constant for this value. - * - * @return integer - */ - public function getNamespace() { - return $this->m_dataitem->getNamespace(); - } - - /** - * Get DBKey for this value. Subclasses that allow for values that do not - * correspond to wiki pages may choose a DB key that is not a legal title - * DB key but rather another suitable internal ID. Thus it is not suitable - * to use this method in places where only MediaWiki Title keys are allowed. - * - * @return string - */ - public function getDBkey() { - return $this->m_dataitem->getDBkey(); - } - - /** - * Get text label for this value, just like Title::getText(). - * - * @return string - */ - public function getText() { - return str_replace( '_', ' ', $this->m_dataitem->getDBkey() ); - } - - /** - * Get the prefixed text for this value, including a localized namespace - * prefix. - * - * @return string - */ - public function getPrefixedText() { - global $wgContLang; - if ( $this->m_prefixedtext === '' ) { - if ( $this->isValid() ) { - $nstext = $wgContLang->getNSText( $this->m_dataitem->getNamespace() ); - $this->m_prefixedtext = - ( $this->m_dataitem->getInterwiki() !== '' ? - $this->m_dataitem->getInterwiki() . ':' : '' ) . - ( $nstext !== '' ? "$nstext:" : '' ) . $this->getText(); - } else { - $this->m_prefixedtext = 'NO_VALID_VALUE'; - } - } - return $this->m_prefixedtext; - } - - /** - * Get interwiki prefix or empty string. - * - * @return string - */ - public function getInterwiki() { - return $this->m_dataitem->getInterwiki(); - } - - /** - * Get a short caption used to label this value. In particular, this - * omits namespace and interwiki prefixes (similar to the MediaWiki - * "pipe trick"). Fragments are included unless they start with an - * underscore (used for generated fragment names that are not helpful - * for users and that might change easily). - * - * @since 1.7 - * @return string - */ - protected function getShortCaptionText() { - if ( $this->m_fragment !== '' && $this->m_fragment[0] != '_' ) { - $fragmentText = '#' . $this->m_fragment; - } else { - $fragmentText = ''; - } - return $this->getText() . $fragmentText; - } - - /** - * Get a long caption used to label this value. In particular, this - * includes namespace and interwiki prefixes, while fragments are only - * included if they do not start with an underscore (used for generated - * fragment names that are not helpful for users and that might change - * easily). - * - * @since 1.7 - * @return string - */ - protected function getLongCaptionText() { - if ( $this->m_fragment !== '' && $this->m_fragment[0] != '_' ) { - $fragmentText = '#' . $this->m_fragment; - } else { - $fragmentText = ''; - } - return ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText() : $this->getText() ) . $fragmentText; - } - - /** - * Compute a text that can be used in wiki text to link to this - * datavalue. Processing includes some escaping and adding the - * fragment. - * - * @since 1.7 - * @return string - */ - protected function getWikiLinkTarget() { - return str_replace( "'", ''', $this->getPrefixedText() ) . - ( $this->m_fragment !== '' ? "#{$this->m_fragment}" : '' ); - } - - /** - * Find the sortkey for this object. - * - * @deprecated Use SMWStore::getWikiPageSortKey(). Will vanish before SMW 1.7 - * - * @return string sortkey - */ - public function getSortKey() { - return \SMW\StoreFactory::getStore()->getWikiPageSortKey( $this->m_dataitem ); - } - - /** - * Static function for creating a new wikipage object from - * data as it is typically stored internally. In particular, - * the title string is supposed to be in DB key form. - * - * @note The resulting wikipage object might be invalid if - * the provided title is not allowed. An object is returned - * in any case. - * - * @deprecated This method will vanish before SMW 1.7. If you really need this, simply copy its code. - * - * @return SMWWikiPageValue - */ - static public function makePage( $dbkey, $namespace, $ignoredParameter = '', $interwiki = '' ) { - $diWikiPage = new SMWDIWikiPage( $dbkey, $namespace, $interwiki ); - $dvWikiPage = new SMWWikiPageValue( '_wpg' ); - $dvWikiPage->setDataItem( $diWikiPage ); - return $dvWikiPage; - } - - /** - * Static function for creating a new wikipage object from a - * MediaWiki Title object. - * - * @deprecated This method will vanish before SMW 1.7. If you really need this, simply copy its code. - * - * @return SMWWikiPageValue - */ - static public function makePageFromTitle( Title $title ) { - $dvWikiPage = new SMWWikiPageValue( '_wpg' ); - $diWikiPage = SMWDIWikiPage::newFromTitle( $title ); - $dvWikiPage->setDataItem( $diWikiPage ); - $dvWikiPage->m_title = $title; // optional, just for efficiency - return $dvWikiPage; - } - -} - -/** - * SMW\WikiPageValue - * - * @since 1.9 - */ -class_alias( 'SMWWikiPageValue', 'SMW\WikiPageValue' ); diff --git a/SemanticMediaWiki/includes/datavalues/SMW_DataValue.php b/SemanticMediaWiki/includes/datavalues/SMW_DataValue.php deleted file mode 100644 index 92f58219..00000000 --- a/SemanticMediaWiki/includes/datavalues/SMW_DataValue.php +++ /dev/null @@ -1,768 +0,0 @@ -<?php - -/** - * This group contains all parts of SMW that relate to the processing of datavalues - * of various types. - * - * @defgroup SMWDataValues SMWDataValues - * @ingroup SMW - */ -use SMW\DataValueFactory; - -/** - * Objects of this type represent all that is known about a certain user-provided - * data value, especially its various representations as strings, tooltips, - * numbers, etc. Objects can be created as "emtpy" containers of a certain type, - * but are then usually filled with data to present one particular data value. - * - * Data values have two chief representation forms: the user-facing syntax and the - * internal representation. In user syntax, every value is (necessarily) a single - * string, however complex the value is. For example, a string such as "Help:editing" - * may represent a wiki page called "Editing" in the namespace for "Help". The - * internal representation may be any numerical array of strings and numbers. In the - * example, it might be array("Editing",12), where 12 is the number used for identifying - * the namespace "Help:". Of course, the internal representation could also use a single - * string value, such as in array("Help:Editing"), but this might be less useful for - * certain operations (e.g. filterng by namespace). Moreover, all values that are - * restored from the database are given in the internal format, so it wise to choose a - * format that allows for very fast and easy processing without unnecessary parsing. - * - * The main functions of data value objects are: - * - setUserValue() which triggers parseUserValue() to process a user-level string. - * - * In addition, there are a number of get-functions that provide useful output versions - * for displaying and serializing the value. - * - * @ingroup SMWDataValues - * - * @author Markus Krötzsch - */ -abstract class SMWDataValue { - - /** - * Associated data item. This is the reference to the immutable object - * that represents the current data content. All other data stored here - * is only about presentation and parsing, but is not relevant to the - * actual data that is represented (and stored later on). - * - * This variable must always be set to some data item, even if there - * have been errors in initialising the data. - * @var SMWDataItem - */ - protected $m_dataitem; - - /** - * The property for which this value is constructed or null if none - * given. Property pages are used to make settings that affect parsing - * and display, hence it is sometimes needed to know them. - * - * @var SMWDIProperty - */ - protected $m_property = null; - - /** - * Wiki page in the context of which the value is to be interpreted, or - * null if not given (or not on a page). This information is used to - * parse user values such as "#subsection" which only make sense when - * used on a certain page. - * - * @var SMWDIWikiPage - */ - protected $m_contextPage = null; - - /** - * The text label to be used for output or false if none given. - * @var string - */ - protected $m_caption; - - /** - * The type id for this value object. - * @var string - */ - protected $m_typeid; - - /** - * Array of SMWInfolink objects. - * @var array - */ - protected $m_infolinks = array(); - - /** - * Output formatting string, false when not set. - * @see setOutputFormat() - * @var mixed - */ - protected $m_outformat = false; - - /** - * Used to control the addition of the standard search link. - * @var boolean - */ - private $mHasSearchLink; - - /** - * Used to control service link creation. - * @var boolean - */ - private $mHasServiceLinks; - - /** - * Array of error text messages. Private to allow us to track error insertion - * (PHP's count() is too slow when called often) by using $mHasErrors. - * @var array - */ - private $mErrors = array(); - - /** - * Boolean indicating if there where any errors. - * Should be modified accordingly when modifying $mErrors. - * @var boolean - */ - private $mHasErrors = false; - - /** - * Constructor. - * - * @param string $typeid - */ - public function __construct( $typeid ) { - $this->m_typeid = $typeid; - } - -///// Set methods ///// - - /** - * Set the user value (and compute other representations if possible). - * The given value is a string as supplied by some user. An alternative - * label for printout might also be specified. - * - * The third argument was added in SMW 1.9 and should not be used from outside SMW. - * - * @param string $value - * @param mixed $caption - * @param boolean $ignoreAllowedValues - */ - public function setUserValue( $value, $caption = false, $ignoreAllowedValues = false ) { - wfProfileIn( 'SMWDataValue::setUserValue (SMW)' ); - - $this->m_dataitem = null; - $this->mErrors = array(); // clear errors - $this->mHasErrors = false; - $this->m_infolinks = array(); // clear links - $this->mHasSearchLink = false; - $this->mHasServiceLinks = false; - $this->m_caption = is_string( $caption ) ? trim( $caption ) : false; - - - $this->parseUserValue( $value ); // may set caption if not set yet, depending on datavalue - - // The following checks for markers generated by MediaWiki to handle special content, - // e.g. math. In general, we are not prepared to handle such content properly, and we - // also have no means of obtaining the user input at this point. Hence the assignement - // just fails, even if parseUserValue() above might not have noticed this issue. - // Note: \x07 was used in MediaWiki 1.11.0, \x7f is used now (backwards compatiblity, b/c) - if ( ( strpos( $value, "\x7f" ) !== false ) || ( strpos( $value, "\x07" ) !== false ) ) { - $this->addError( wfMessage( 'smw_parseerror' )->inContentLanguage()->text() ); - } - - if ( $this->isValid() && !$ignoreAllowedValues ) { - $this->checkAllowedValues(); - } - - wfProfileOut( 'SMWDataValue::setUserValue (SMW)' ); - } - - /** - * Set the actual data contained in this object. The method returns - * true if this was successful (requiring the type of the dataitem - * to match the data value). If false is returned, the data value is - * left unchanged (the data item was rejected). - * - * @note Even if this function returns true, the data value object - * might become invalid if the content of the data item caused errors - * in spite of it being of the right basic type. False is only returned - * if the data item is fundamentally incompatible with the data value. - * - * @param $dataitem SMWDataItem - * @return boolean - */ - public function setDataItem( SMWDataItem $dataItem ) { - $this->m_dataitem = null; - $this->mErrors = $this->m_infolinks = array(); - $this->mHasErrors = $this->mHasSearchLink = $this->mHasServiceLinks = $this->m_caption = false; - return $this->loadDataItem( $dataItem ); - } - - /** - * Specify the property to which this value refers. Property pages are - * used to make settings that affect parsing and display, hence it is - * sometimes needed to know them. - * - * @since 1.6 - * - * @param SMWDIProperty $property - */ - public function setProperty( SMWDIProperty $property ) { - $this->m_property = $property; - } - - /** - * Returns the property to which this value refers. - * - * @since 1.8 - * - * @return SMWDIProperty|null - */ - public function getProperty() { - return $this->m_property; - } - - /** - * Specify the wiki page to which this value refers. This information is - * used to parse user values such as "#subsection" which only make sense - * when used on a certain page. - * - * @since 1.7 - * - * @param SMWDIWikiPage $contextPage - */ - public function setContextPage( SMWDIWikiPage $contextPage ) { - $this->m_contextPage = $contextPage; - } - - /** - * Change the caption (the text used for displaying this datavalue). The given - * value must be a string. - * - * @param string $caption - */ - public function setCaption( $caption ) { - $this->m_caption = $caption; - } - - /** - * Adds a single SMWInfolink object to the m_infolinks array. - * - * @param SMWInfolink $link - */ - public function addInfolink( SMWInfolink $link ) { - $this->m_infolinks[] = $link; - } - - /** - * Servicelinks are special kinds of infolinks that are created from - * current parameters and in-wiki specification of URL templates. This - * method adds the current property's servicelinks found in the - * messages. The number and content of the parameters is depending on - * the datatype, and the service link message is usually crafted with a - * particular datatype in mind. - */ - public function addServiceLinks() { - if ( $this->mHasServiceLinks ) { - return; - } - - if ( !is_null( $this->m_property ) ) { - $propertyDiWikiPage = $this->m_property->getDiWikiPage(); - } - - if ( is_null( $this->m_property ) || is_null( $propertyDiWikiPage ) ) { - return; // no property known, or not associated with a page - } - - $args = $this->getServiceLinkParams(); - - if ( $args === false ) { - return; // no services supported - } - - array_unshift( $args, '' ); // add a 0 element as placeholder - $servicelinks = \SMW\StoreFactory::getStore()->getPropertyValues( $propertyDiWikiPage, new SMWDIProperty( '_SERV' ) ); - - foreach ( $servicelinks as $dataItem ) { - if ( !( $dataItem instanceof SMWDIBlob ) ) { - continue; - } - - $args[0] = 'smw_service_' . str_replace( ' ', '_', $dataItem->getString() ); // messages distinguish ' ' from '_' - // @todo FIXME: Use wfMessage/Message class here. - $text = call_user_func_array( 'wfMsgForContent', $args ); - $links = preg_split( "/[\n][\s]?/u", $text ); - - foreach ( $links as $link ) { - $linkdat = explode( '|', $link, 2 ); - - if ( count( $linkdat ) == 2 ) { - $this->addInfolink( SMWInfolink::newExternalLink( $linkdat[0], trim( $linkdat[1] ) ) ); - } - } - } - $this->mHasServiceLinks = true; - } - - /** - * Define a particular output format. Output formats are user-supplied strings - * that the datavalue may (or may not) use to customise its return value. For - * example, quantities with units of measurement may interpret the string as - * a desired output unit. In other cases, the output format might be built-in - * and subject to internationalisation (which the datavalue has to implement). - * In any case, an empty string resets the output format to the default. - * - * There is one predeeind output format that all datavalues should respect: the - * format '-' indicates "plain" output that is most useful for further processing - * the value in a template. It should not use any wiki markup or beautification, - * and it should also avoid localization to the current language. When users - * explicitly specify an empty format string in a query, it is normalized to "-" - * to avoid confusion. Note that empty format strings are not interpreted in - * this way when directly passed to this function. - * - * @param string $formatString - */ - public function setOutputFormat( $formatString ) { - $this->m_outformat = $formatString; // just store it, subclasses may or may not use this - } - - /** - * Add a new error string or array of such strings to the error list. - * - * @note Errors should not be escaped here in any way, in contradiction to what - * the docs used to say here in 1.5 and before. Escaping should happen at the output. - * - * @param mixed $error A single string, or array of strings. - */ - public function addError( $error ) { - if ( is_array( $error ) ) { - $this->mErrors = array_merge( $this->mErrors, $error ); - $this->mHasErrors = $this->mHasErrors || ( count( $error ) > 0 ); - } else { - $this->mErrors[] = $error; - $this->mHasErrors = true; - } - } - - /** - * Clear error messages. This function is provided temporarily to allow - * n-ary to do this. - * properly so that this function will vanish again. - * @note Do not use this function in external code. - * @todo Check if we can remove this function again. - */ - protected function clearErrors() { - $this->mErrors = array(); - $this->mHasErrors = false; - } - -///// Abstract processing methods ///// - - /** - * Initialise the datavalue from the given value string. - * The format of this strings might be any acceptable user input - * and especially includes the output of getWikiValue(). - * - * @param string $value - */ - abstract protected function parseUserValue( $value ); - - /** - * Set the actual data contained in this object. The method returns - * true if this was successful (requiring the type of the dataitem - * to match the data value). If false is returned, the data value is - * left unchanged (the data item was rejected). - * - * @note Even if this function returns true, the data value object - * might become invalid if the content of the data item caused errors - * in spite of it being of the right basic type. False is only returned - * if the data item is fundamentally incompatible with the data value. - * - * @since 1.6 - * - * @param SMWDataItem $dataItem - * - * @return boolean - */ - abstract protected function loadDataItem( SMWDataItem $dataItem ); - - -///// Query support ///// - - /** - * Create an SMWDescription object based on a value string that was entered - * in a query. Turning inputs that a user enters in place of a value within - * a query string into query conditions is often a standard procedure. The - * processing must take comparators like "<" into account, but otherwise - * the normal parsing function can be used. However, there can be datatypes - * where processing is more complicated, e.g. if the input string contains - * more than one value, each of which may have comparators, as in - * SMWRecordValue. In this case, it makes sense to overwrite this method. - * Another reason to do this is to add new forms of comparators or new ways - * of entering query conditions. - * - * The resulting SMWDescription may or may not make use of the datavalue - * object that this function was called on, so it must be ensured that this - * value is not used elsewhere when calling this method. The function can - * return SMWThingDescription to not impose any condition, e.g. if parsing - * failed. Error messages of this SMWDataValue object are propagated. - * - * @note Descriptions of values need to know their property to be able to - * create a parsable wikitext version of a query condition again. Thus it - * might be necessary to call setProperty() before using this method. - * - * @param string $value - * - * @return SMWDescription - * @throws InvalidArgumentException - */ - public function getQueryDescription( $value ) { - if ( !is_string( $value ) ) { - throw new InvalidArgumentException( '$value needs to be a string' ); - } - - $comparator = SMW_CMP_EQ; - - self::prepareValue( $value, $comparator ); - - if( $comparator == SMW_CMP_LIKE ) { - // ignore allowed values when the LIKE comparator is used (BUG 21893) - $this->setUserValue( $value, false, true ); - } else { - $this->setUserValue( $value ); - } - - if ( $this->isValid() ) { - return new SMWValueDescription( $this->getDataItem(), $this->m_property, $comparator ); - } else { - return new SMWThingDescription(); - } - } - - /** - * Helper function for getQueryDescription() that prepares a single value - * string, possibly extracting comparators. $value is changed to consist - * only of the remaining effective value string (without the comparator). - * - * @param string $value - * @param string $comparator - */ - static protected function prepareValue( &$value, &$comparator ) { - // Loop over the comparators to determine which one is used and what the actual value is. - foreach ( SMWQueryLanguage::getComparatorStrings() as $string ) { - if ( strpos( $value, $string ) === 0 ) { - $comparator = SMWQueryLanguage::getComparatorFromString( substr( $value, 0, strlen( $string ) ) ); - $value = substr( $value, strlen( $string ) ); - break; - } - } - } - -///// Get methods ///// - - /** - * Get the actual data contained in this object or null if the data is - * not defined (due to errors or due to not being set at all). - * @note Most implementations ensure that a data item is always set, - * even if errors occurred, to avoid additional checks for not - * accessing null. Hence, one must not assume that a non-null return - * value here implies that isValid() returns true. - * - * @since 1.6 - * - * @return SMWDataItem|SMWDIError - */ - public function getDataItem() { - if ( $this->isValid() ) { - return $this->m_dataitem; - } else { - return new SMWDIError( $this->mErrors ); - } - } - - /** - * Returns a short textual representation for this data value. If the value - * was initialised from a user supplied string, then this original string - * should be reflected in this short version (i.e. no normalisation should - * normally happen). There might, however, be additional parts such as code - * for generating tooltips. The output is in wiki text. - * - * The parameter $linked controls linking of values such as titles and should - * be non-NULL and non-false if this is desired. - */ - abstract public function getShortWikiText( $linked = null ); - - /** - * Returns a short textual representation for this data value. If the value - * was initialised from a user supplied string, then this original string - * should be reflected in this short version (i.e. no normalisation should - * normally happen). There might, however, be additional parts such as code - * for generating tooltips. The output is in HTML text. - * - * The parameter $linker controls linking of values such as titles and should - * be some Linker object (or NULL for no linking). - */ - abstract public function getShortHTMLText( $linker = null ); - - /** - * Return the long textual description of the value, as printed for - * example in the factbox. If errors occurred, return the error message - * The result always is a wiki-source string. - * - * The parameter $linked controls linking of values such as titles and should - * be non-NULL and non-false if this is desired. - */ - abstract public function getLongWikiText( $linked = null ); - - /** - * Return the long textual description of the value, as printed for - * example in the factbox. If errors occurred, return the error message - * The result always is an HTML string. - * - * The parameter $linker controls linking of values such as titles and should - * be some Linker object (or NULL for no linking). - */ - abstract public function getLongHTMLText( $linker = null ); - - /** - * Returns a short textual representation for this data value. If the value - * was initialised from a user supplied string, then this original string - * should be reflected in this short version (i.e. no normalisation should - * normally happen). There might, however, be additional parts such as code - * for generating tooltips. The output is in the specified format. - * - * The parameter $linker controls linking of values such as titles and should - * be some Linker object (for HTML output), or NULL for no linking. - */ - public function getShortText( $outputformat, $linker = null ) { - switch ( $outputformat ) { - case SMW_OUTPUT_WIKI: - return $this->getShortWikiText( $linker ); - case SMW_OUTPUT_HTML: - case SMW_OUTPUT_FILE: - default: - return $this->getShortHTMLText( $linker ); - } - } - - /** - * Return the long textual description of the value, as printed for - * example in the factbox. If errors occurred, return the error message. - * The output is in the specified format. - * - * The parameter $linker controls linking of values such as titles and should - * be some Linker object (for HTML output), or NULL for no linking. - */ - public function getLongText( $outputformat, $linker = null ) { - switch ( $outputformat ) { - case SMW_OUTPUT_WIKI: - return $this->getLongWikiText( $linker ); - case SMW_OUTPUT_HTML: - case SMW_OUTPUT_FILE: - default: - return $this->getLongHTMLText( $linker ); - } - } - - /** - * Return text serialisation of info links. Ensures more uniform layout - * throughout wiki (Factbox, Property pages, ...). - * - * @param integer $outputformat Element of the SMW_OUTPUT_ enum - * @param $linker - * - * @return string - */ - public function getInfolinkText( $outputformat, $linker = null ) { - $result = ''; - $first = true; - $extralinks = array(); - - switch ( $outputformat ) { - case SMW_OUTPUT_WIKI: - foreach ( $this->getInfolinks() as $link ) { - if ( $first ) { - $result .= '<!-- --> ' . $link->getWikiText(); - // the comment is needed to prevent MediaWiki from linking URL-strings together with the nbsps! - $first = false; - } else { - $extralinks[] = $link->getWikiText(); - } - } - break; - - case SMW_OUTPUT_HTML: case SMW_OUTPUT_FILE: default: - foreach ( $this->getInfolinks() as $link ) { - if ( $first ) { - $result .= '  ' . $link->getHTML( $linker ); - $first = false; - } else { - $extralinks[] = $link->getHTML( $linker ); - } - } - break; - } - - if ( count( $extralinks ) > 0 ) { - $result .= smwfEncodeMessages( $extralinks, 'service', '', false ); - } - - return $result; - } - - /** - * Return the plain wiki version of the value, or - * FALSE if no such version is available. The returned - * string suffices to reobtain the same DataValue - * when passing it as an input string to setUserValue(). - */ - abstract public function getWikiValue(); - - /** - * Return a short string that unambiguously specify the type of this - * value. This value will globally be used to identify the type of a - * value (in spite of the class it actually belongs to, which can still - * implement various types). - */ - public function getTypeID() { - return $this->m_typeid; - } - - /** - * Return an array of SMWLink objects that provide additional resources - * for the given value. Captions can contain some HTML markup which is - * admissible for wiki text, but no more. Result might have no entries - * but is always an array. - */ - public function getInfolinks() { - if ( $this->isValid() && !is_null( $this->m_property ) ) { - if ( !$this->mHasSearchLink ) { // add default search link - $this->mHasSearchLink = true; - $this->m_infolinks[] = SMWInfolink::newPropertySearchLink( '+', - $this->m_property->getLabel(), $this->getWikiValue() ); - } - - if ( !$this->mHasServiceLinks ) { // add further service links - $this->addServiceLinks(); - } - } - - return $this->m_infolinks; - } - - /** - * Overwritten by callers to supply an array of parameters that can be used for - * creating servicelinks. The number and content of values in the parameter array - * may vary, depending on the concrete datatype. - */ - protected function getServiceLinkParams() { - return false; - } - - /** - * Return a string that identifies the value of the object, and that can - * be used to compare different value objects. - * Possibly overwritten by subclasses (e.g. to ensure that returned - * value is normalized first) - * - * @return string - */ - public function getHash() { - return $this->isValid() ? $this->m_dataitem->getHash() : implode( "\t", $this->mErrors ); - } - - /** - * Convenience method that checks if the value that is used to sort - * data of this type is numeric. This only works if the value is set. - * - * @return boolean - */ - public function isNumeric() { - if ( isset( $this->m_dataitem ) ) { - return is_numeric( $this->m_dataitem->getSortKey() ); - } else { - return false; - } - } - - /** - * Return true if a value was defined and understood by the given type, - * and false if parsing errors occurred or no value was given. - * - * @return boolean - */ - public function isValid() { - return !$this->mHasErrors && isset( $this->m_dataitem ); - } - - /** - * Return a string that displays all error messages as a tooltip, or - * an empty string if no errors happened. - * - * @return string - */ - public function getErrorText() { - return smwfEncodeMessages( $this->mErrors ); - } - - /** - * Return an array of error messages, or an empty array - * if no errors occurred. - * - * @return array - */ - public function getErrors() { - return $this->mErrors; - } - - /** - * Check if property is range restricted and, if so, whether the current value is allowed. - * Creates an error if the value is illegal. - */ - protected function checkAllowedValues() { - if ( !is_null( $this->m_property ) ) { - $propertyDiWikiPage = $this->m_property->getDiWikiPage(); - } - - if ( is_null( $this->m_property ) || is_null( $propertyDiWikiPage ) || - !isset( $this->m_dataitem ) ) { - return; // no property known, or no data to check - } - - $allowedvalues = \SMW\StoreFactory::getStore()->getPropertyValues( - $propertyDiWikiPage, - new SMWDIProperty( '_PVAL' ) - ); - - if ( count( $allowedvalues ) == 0 ) { - return; - } - - $hash = $this->m_dataitem->getHash(); - $testdv = DataValueFactory::getInstance()->newTypeIDValue( $this->getTypeID() ); - $accept = false; - $valuestring = ''; - - foreach ( $allowedvalues as $di ) { - if ( $di instanceof SMWDIBlob ) { - $testdv->setUserValue( $di->getString() ); - - if ( $hash === $testdv->getDataItem()->getHash() ) { - $accept = true; - break; - } else { - if ( $valuestring !== '' ) { - $valuestring .= ', '; - } - $valuestring .= $di->getString(); - } - } - } - - if ( !$accept ) { - $this->addError( wfMessage( - 'smw_notinenum', - $this->getWikiValue(), $valuestring - )->inContentLanguage()->text() - ); - } - } - -} diff --git a/SemanticMediaWiki/includes/dic/BaseDependencyContainer.php b/SemanticMediaWiki/includes/dic/BaseDependencyContainer.php deleted file mode 100644 index 805475f1..00000000 --- a/SemanticMediaWiki/includes/dic/BaseDependencyContainer.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -namespace SMW; - -/** - * Implements the DependencyContainer interface and is responsible for handling - * object storage, and retrieval of object definitions - * - * Examples and a more exhaustive description can be found at /docs/dic.md - * - * @ingroup DependencyContainer - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -abstract class BaseDependencyContainer extends ObjectStorage implements DependencyContainer { - - /** - * @see ObjectStorage::contains - * - * @since 1.9 - */ - public function has( $key ) { - return $this->contains( $key ); - } - - /** - * @see ObjectStorage::lookup - * - * @since 1.9 - */ - public function get( $key ) { - return $this->lookup( $key ); - } - - /** - * @see ObjectStorage::attach - * - * @since 1.9 - */ - public function set( $key, $value ) { - return $this->attach( $key, $value ); - } - - /** - * @see ObjectStorage::detach - * - * @since 1.9 - */ - public function remove( $key ) { - return $this->detach( $key ); - } - - /** - * @see ObjectStorage::detach - * - * @since 1.9 - */ - public function toArray() { - return $this->storage; - } - - /** - * Merges elements of one or more arrays together - * - * @since 1.9 - * - * @return array - */ - public function merge( array $mergeable ) { - $this->storage = array_merge_recursive( $this->storage, $mergeable ); - } - - /** - * Register an object via magic method __set - * - * @since 1.9 - * - * @param string $objectName - * @param mixed $objectSignature - */ - public function __set( $objectName, $objectSignature ) { - $this->registerObject( $objectName, $objectSignature ); - } - - /** - * @see DependencyContainer::registerObject - * - * @since 1.9 - * - * @param string $objectName - * @param mixed $objectSignature an arbitrary signature of any kind such Closure, DependencyObject etc. - * @param mixed $objectScope - */ - public function registerObject( $objectName, $objectSignature, $objectScope = DependencyObject::SCOPE_PROTOTYPE ) { - $this->set( $objectName, array( $objectSignature, $objectScope ) ); - } - - /** - * @see DependencyContainer::loadAllDefinitions - * - * @since 1.9 - * - * @return array - */ - public function loadAllDefinitions() { - - if ( !$this->has( 'def_' ) ) { - $this->set( 'def_', $this->getDefinitions() ); - } - - return $this->get( 'def_' ); - } - - /** - * @since 1.9 - * - * @return array - */ - protected abstract function getDefinitions(); - -} diff --git a/SemanticMediaWiki/includes/dic/DependencyBuilder.php b/SemanticMediaWiki/includes/dic/DependencyBuilder.php deleted file mode 100644 index dd8eafdf..00000000 --- a/SemanticMediaWiki/includes/dic/DependencyBuilder.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interfaces specifying a DependencyBuilder - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Interface that specifies a method to create a new object - * - * @ingroup DependencyBuilder - */ -interface DependencyFactory { - - /** - * Returns a dependency object - * - * @since 1.9 - * - * @param string $objectName - * @param mixed $objectArguments - */ - public function newObject( $objectName, $objectArguments = null ); - -} - -/** - * Interface that specifies methods to handle injection container and objects - * - * @ingroup DependencyBuilder - */ -interface DependencyBuilder extends DependencyFactory { - - /** - * Returns invoked dependency container object - * - * @since 1.9 - * - * @return DependencyContainer - */ - public function getContainer(); - - /** - * Returns an invoked constructor argument - * - * @since 1.9 - * - * @param string $key - */ - public function getArgument( $key ); - - /** - * Returns whether the argument is known - * - * @since 1.9 - * - * @param string $key - * - * @return boolean - */ - public function hasArgument( $key ); - - /** - * Adds an argument that can be used during object creation - * - * @since 1.9 - * - * @param string $key - * @param mixed $value - */ - public function addArgument( $key, $value ); - - /** - * Defines an object scope used during the build process - * - * This overrides temporarily the object scope during the build process and - * will only be effective during the build while the original object scope - * keeps intact - * - * @since 1.9 - * - * @param $scope - */ - public function setScope( $scope ); - -} diff --git a/SemanticMediaWiki/includes/dic/DependencyContainer.php b/SemanticMediaWiki/includes/dic/DependencyContainer.php deleted file mode 100644 index aaadf929..00000000 --- a/SemanticMediaWiki/includes/dic/DependencyContainer.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface specifying a dependency object - * - * @ingroup DependencyContainer - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface DependencyObject { - - /** A new instance is created each time the service is requested */ - const SCOPE_PROTOTYPE = 0; - - /** Same instance is used over the lifetime of a request */ - const SCOPE_SINGLETON = 1; - - /** - * Defines an object - * - * @since 1.9 - * - * @param DependencyBuilder $builder - */ - public function retrieveDefinition( DependencyBuilder $builder ); - -} - -/** - * Interface specifying a dependency container - * - * @ingroup DependencyContainer - */ -interface DependencyContainer extends Accessible, Changeable, Combinable { - - /** - * Register a dependency object - * - * @since 1.9 - */ - public function registerObject( $objectName, $objectSignature, $objectScope ); - - /** - * Retrieves object definitions - * - * @since 1.9 - */ - public function loadAllDefinitions(); - -} diff --git a/SemanticMediaWiki/includes/dic/DependencyInjector.php b/SemanticMediaWiki/includes/dic/DependencyInjector.php deleted file mode 100644 index 9b112d6a..00000000 --- a/SemanticMediaWiki/includes/dic/DependencyInjector.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -namespace SMW; - -/** - * Abstract class that implements the DependencyRequestor to enable convenience - * access to an injected DependencyBuilder - * - * @par Example: - * @code - * class FooClass extends DependencyInjector { ... } - * - * $fooClass = new FooClass( ... ) - * $fooClass->setDependencyBuilder( new SimpleDependencyBuilder( - * new GenericDependencyContainer() - * ) ); - * - * $fooClass->getDependencyBuilder()->newObject( 'Bar' ); - * @endcode - * - * @ingroup DependencyRequestor - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -abstract class DependencyInjector implements DependencyRequestor { - - /** @var DependencyBuilder */ - protected $dependencyBuilder; - - /** - * @see DependencyRequestor::setDependencyBuilder - * - * @since 1.9 - * - * @param DependencyBuilder $builder - */ - public function setDependencyBuilder( DependencyBuilder $builder ) { - $this->dependencyBuilder = $builder; - } - - /** - * @see DependencyRequestor::getDependencyBuilder - * - * @since 1.9 - * - * @return DependencyBuilder - */ - public function getDependencyBuilder() { - return $this->dependencyBuilder; - } -} diff --git a/SemanticMediaWiki/includes/dic/DependencyRequestor.php b/SemanticMediaWiki/includes/dic/DependencyRequestor.php deleted file mode 100644 index 21c970fb..00000000 --- a/SemanticMediaWiki/includes/dic/DependencyRequestor.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -namespace SMW; - -use InvalidArgumentException; -use OutOfBoundsException; - -/** - * Interface specifying access to a DependencyBuilder - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Interface specifying access to a DependencyBuilder within a client that - * requests dependency injection - * - * @ingroup DependencyRequestor - */ -interface DependencyRequestor { - - /** - * Sets DependencyBuilder - * - * @since 1.9 - * - * @param DependencyBuilder $builder - */ - public function setDependencyBuilder( DependencyBuilder $builder ); - - /** - * Returns invoked DependencyBuilder - * - * @since 1.9 - * - * @return DependencyBuilder - */ - public function getDependencyBuilder(); - -} diff --git a/SemanticMediaWiki/includes/dic/NullDependencyContainer.php b/SemanticMediaWiki/includes/dic/NullDependencyContainer.php deleted file mode 100644 index 513103b3..00000000 --- a/SemanticMediaWiki/includes/dic/NullDependencyContainer.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW; - -/** - * Provides an empty DependencyContainer entity - * - * @ingroup DependencyContainer - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class NullDependencyContainer extends BaseDependencyContainer { - - /** - * @since 1.9 - */ - protected function getDefinitions() { - return null; - } - -} diff --git a/SemanticMediaWiki/includes/dic/SharedDependencyContainer.php b/SemanticMediaWiki/includes/dic/SharedDependencyContainer.php deleted file mode 100644 index dfa9cfac..00000000 --- a/SemanticMediaWiki/includes/dic/SharedDependencyContainer.php +++ /dev/null @@ -1,364 +0,0 @@ -<?php - -namespace SMW; - -use SMW\MediaWiki\TitleCreator; -use SMW\MediaWiki\PageCreator; - -/** - * Extends the BaseDependencyContainer to provide general purpose dependency - * object definitions - * - * @ingroup DependencyContainer - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SharedDependencyContainer extends BaseDependencyContainer { - - /** - * @since 1.9 - */ - public function __construct() { - $this->loadAtInstantiation(); - } - - /** - * @since 1.9 - */ - protected function loadAtInstantiation() { - - /** - * Settings object definition - * - * @since 1.9 - * - * @return Settings - */ - $this->registerObject( 'Settings', function () { - return Settings::newFromGlobals(); - }, DependencyObject::SCOPE_SINGLETON ); - - /** - * Store object definition - * - * @since 1.9 - * - * @return Store - */ - $this->registerObject( 'Store', function ( DependencyBuilder $builder ) { - return StoreFactory::getStore( $builder->newObject( 'Settings' )->get( 'smwgDefaultStore' ) ); - }, DependencyObject::SCOPE_SINGLETON ); - - /** - * CacheHandler object definition - * - * @since 1.9 - * - * @return CacheHandler - */ - $this->registerObject( 'CacheHandler', function ( DependencyBuilder $builder ) { - return CacheHandler::newFromId( $builder->newObject( 'Settings' )->get( 'smwgCacheType' ) ); - }, DependencyObject::SCOPE_SINGLETON ); - - } - - /** - * @see BaseDependencyContainer::registerDefinitions - * - * @since 1.9 - * - * @return array - */ - protected function getDefinitions() { - return array( - 'ParserData' => $this->getParserData(), - 'NamespaceExaminer' => $this->getNamespaceExaminer(), - 'NullPropertyAnnotator' => $this->NullPropertyAnnotator(), - 'CommonPropertyAnnotator' => $this->CommonPropertyAnnotator(), - 'PredefinedPropertyAnnotator' => $this->PredefinedPropertyAnnotator(), - 'QueryProfiler' => $this->QueryProfiler(), - - 'JobFactory' => function ( DependencyBuilder $builder ) { - return new \SMW\MediaWiki\Jobs\JobFactory(); - }, - - /** - * ContentParser object definition - * - * @since 1.9 - * - * @return ContentParser - */ - 'ContentParser' => function ( DependencyBuilder $builder ) { - return new ContentParser( $builder->getArgument( 'Title' ) ); - }, - - /** - * RequestContext object definition - * - * @since 1.9 - * - * @return RequestContext - */ - 'RequestContext' => function ( DependencyBuilder $builder ) { - - $instance = new \RequestContext(); - - if ( $builder->hasArgument( 'Title' ) ) { - $instance->setTitle( $builder->getArgument( 'Title' ) ); - } - - if ( $builder->hasArgument( 'Language' ) ) { - $instance->setLanguage( $builder->getArgument( 'Language' ) ); - } - - return $instance; - }, - - /** - * WikiPage object definition - * - * @since 1.9 - * - * @return WikiPage - */ - 'WikiPage' => function ( DependencyBuilder $builder ) { - return \WikiPage::factory( $builder->getArgument( 'Title' ) ); - }, - - /** - * @since 2.0 - * - * @return TitleCreator - */ - 'TitleCreator' => function ( DependencyBuilder $builder ) { - return new TitleCreator( new PageCreator() ); - }, - - /** - * @since 2.0 - * - * @return PageCreator - */ - 'PageCreator' => function ( DependencyBuilder $builder ) { - return new PageCreator(); - }, - - /** - * MessageFormatter object definition - * - * @since 1.9 - * - * @return MessageFormatter - */ - 'MessageFormatter' => function ( DependencyBuilder $builder ) { - return new MessageFormatter( $builder->getArgument( 'Language' ) ); - }, - - /** - * AskParserFunction object definition - * - * @since 1.9 - * - * @return AskParserFunction - */ - 'AskParserFunction' => function ( DependencyBuilder $builder ) { - - $parser = $builder->getArgument( 'Parser' ); - $builder->addArgument( 'Language', $parser->getTargetLanguage() ); - - $parserData = $builder->newObject( 'ParserData', array( - 'Title' => $parser->getTitle(), - 'ParserOutput' => $parser->getOutput() - ) ); - - $instance = new AskParserFunction( $parserData, $builder->newObject( 'ExtensionContext' ) ); - - return $instance; - }, - - /** - * ShowParserFunction object definition - * - * @since 1.9 - * - * @return ShowParserFunction - */ - 'ShowParserFunction' => function ( DependencyBuilder $builder ) { - - $parser = $builder->getArgument( 'Parser' ); - $builder->addArgument( 'Language', $parser->getTargetLanguage() ); - - $parserData = $builder->newObject( 'ParserData', array( - 'Title' => $parser->getTitle(), - 'ParserOutput' => $parser->getOutput() - ) ); - - $instance = new ShowParserFunction( $parserData, $builder->newObject( 'ExtensionContext' ) ); - - return $instance; - }, - - /** - * SubobjectParserFunction object definition - * - * @since 1.9 - * - * @return SubobjectParserFunction - */ - 'SubobjectParserFunction' => function ( DependencyBuilder $builder ) { - - $parser = $builder->getArgument( 'Parser' ); - - $parserData = $builder->newObject( 'ParserData', array( - 'Title' => $parser->getTitle(), - 'ParserOutput' => $parser->getOutput() - ) ); - - $subobject = new Subobject( $parser->getTitle() ); - - $messageFormatter = $builder->newObject( 'MessageFormatter', array( - 'Language' => $parser->getTargetLanguage() - ) ); - - $instance = new SubobjectParserFunction( $parserData, $subobject, $messageFormatter ); - - return $instance; - }, - - /** - * ExtensionContext object definition - * - * @since 1.9 - * - * @return ExtensionContext - */ - 'ExtensionContext' => function ( DependencyBuilder $builder ) { - return new ExtensionContext( $builder ); - } - - ); - } - - /** - * ParserData object definition - * - * @since 1.9 - * - * @return ParserData - */ - protected function getParserData() { - return function ( DependencyBuilder $builder ) { - - $instance = new ParserData( - $builder->getArgument( 'Title' ), - $builder->getArgument( 'ParserOutput' ) - ); - - return $instance; - }; - } - - /** - * NamespaceExaminer object definition - * - * @since 1.9 - * - * @return NamespaceExaminer - */ - protected function getNamespaceExaminer() { - return function ( DependencyBuilder $builder ) { - return NamespaceExaminer::newFromArray( $builder->newObject( 'Settings' )->get( 'smwgNamespacesWithSemanticLinks' ) ); - }; - } - - /** - * NullPropertyAnnotator object definition - * - * @since 1.9 - * - * @return NullPropertyAnnotator - */ - protected function NullPropertyAnnotator() { - return function ( DependencyBuilder $builder ) { - return new \SMW\Annotator\NullPropertyAnnotator( - $builder->getArgument( 'SemanticData' ) - ); - }; - } - - /** - * PropertyAnnotator object definition - * - * @since 1.9 - * - * @return PropertyAnnotator - */ - protected function CommonPropertyAnnotator() { - return function ( DependencyBuilder $builder ) { - - $annotator = $builder->newObject( 'NullPropertyAnnotator' ); - - if ( $builder->hasArgument( 'DefaultSort' ) ) { - $annotator = new \SMW\Annotator\SortkeyPropertyAnnotator( - $annotator, - $builder->getArgument( 'DefaultSort' ) - ); - } - - if ( $builder->hasArgument( 'CategoryLinks' ) ) { - $annotator = new \SMW\Annotator\CategoryPropertyAnnotator( - $annotator, - $builder->getArgument( 'CategoryLinks' ) - ); - } - - return $annotator; - }; - } - - /** - * @since 1.9 - * - * @return PredefinedPropertyAnnotator - */ - protected function PredefinedPropertyAnnotator() { - return function ( DependencyBuilder $builder ) { - - $annotator = $builder->newObject( 'NullPropertyAnnotator' ); - - $valueProvider = new \SMW\MediaWiki\PageInfoProvider( - $builder->getArgument( 'WikiPage' ), - $builder->hasArgument( 'Revision' ) ? $builder->getArgument( 'Revision' ) : null, - $builder->hasArgument( 'User' ) ? $builder->getArgument( 'User' ) : null - ); - - return new \SMW\Annotator\PredefinedPropertyAnnotator( $annotator, $valueProvider ); - }; - } - - /** - * @since 1.9 - * - * @return ProfileAnnotator - */ - protected function QueryProfiler() { - return function ( DependencyBuilder $builder ) { - - $profiler = new \SMW\Query\Profiler\NullProfile( - new Subobject( $builder->getArgument( 'Title' ) ), - new HashIdGenerator( $builder->getArgument( 'QueryParameters' ) ) - ); - - $profiler = new \SMW\Query\Profiler\DescriptionProfile( $profiler, $builder->getArgument( 'QueryDescription' ) ); - $profiler = new \SMW\Query\Profiler\FormatProfile( $profiler, $builder->getArgument( 'QueryFormat' ) ); - $profiler = new \SMW\Query\Profiler\DurationProfile( $profiler, $builder->getArgument( 'QueryDuration' ) ); - - return $profiler; - }; - } - -} diff --git a/SemanticMediaWiki/includes/dic/SimpleDependencyBuilder.php b/SemanticMediaWiki/includes/dic/SimpleDependencyBuilder.php deleted file mode 100644 index 38c064f6..00000000 --- a/SemanticMediaWiki/includes/dic/SimpleDependencyBuilder.php +++ /dev/null @@ -1,349 +0,0 @@ -<?php - -namespace SMW; - -use InvalidArgumentException; -use OutOfBoundsException; - -/** - * Implements a basic DependencyBuilder - * - * @par Example: - * For a more exhaustive description and examples on how to "work with - * a DependencyBuilder/Container", see /docs/dic.md - * - * @ingroup DependencyBuilder - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SimpleDependencyBuilder implements DependencyBuilder { - - /** @var DependencyContainer */ - protected $dependencyContainer = null; - - /** @var integer */ - protected $objectScope = null; - - /** - * Iteration counter which indicates the level of iteration over resolving an - * object graph for a single definition. It is expected that a certain level - * of recursion is necessary to fully expand an object but it is in anticipation - * that no definition will have a depth greater than $recursionDepth - * - * @var integer - */ - protected $recursionLevel = 0; - - /** - * Specifies a max depth (or threshold) for a dependency graph. In case a build - * will overstep this limit it is assumed that the builder is caught in an - * infinite loop due to a self-reference (circular reference) within its - * object definition - * - * @var integer - */ - protected $recursionDepth = 10; - - /** - * @note In case no DependencyContainer has been injected during construction - * an empty container is set as default to enable registration without the need - * to rely on constructor injection. - * - * @since 1.9 - * - * @param DependencyContainer|null $dependencyContainer - */ - public function __construct( DependencyContainer $dependencyContainer = null ) { - - $this->dependencyContainer = $dependencyContainer; - - if ( $this->dependencyContainer === null ) { - $this->dependencyContainer = new NullDependencyContainer(); - } - - } - - /** - * Register a DependencyContainer - * - * @since 1.9 - * - * @param DependencyContainer $container - */ - public function registerContainer( DependencyContainer $container ) { - - $this->dependencyContainer->loadAllDefinitions(); - $container->loadAllDefinitions(); - - $this->dependencyContainer->merge( $container->toArray() ); - } - - /** - * @see DependencyBuilder::getContainer - * - * @since 1.9 - * - * @return DependencyContainer - */ - public function getContainer() { - return $this->dependencyContainer; - } - - /** - * Create a new object - * - * @note When adding arguments it is preferable to use type hinting even - * though auto type recognition is supported but using mock objects during - * testing will cause objects being recognized with their mock name instead - * of the original mocked entity - * - * @since 1.9 - * - * @param string $objectName - * @param array|null $objectArguments - * - * @return mixed - * @throws InvalidArgumentException - */ - public function newObject( $objectName, $objectArguments = null ) { - - if ( !is_string( $objectName ) ) { - throw new InvalidArgumentException( 'Object name is not a string' ); - } - - if ( $objectArguments !== null ) { - - if ( !is_array( $objectArguments ) ) { - throw new InvalidArgumentException( "Arguments are not an array type" ); - } - - foreach ( $objectArguments as $key => $value ) { - $this->addArgument( is_string( $key ) ? $key : get_class( $value ), $value ); - } - } - - return $this->build( $objectName ); - } - - /** - * Create a new object using the magic __call method - * - * @param string $objectName - * @param array|null $objectArguments - * - * @return mixed - */ - public function __call( $objectName, $objectArguments = null ) { - - if ( isset( $objectArguments[0] ) && is_array( $objectArguments[0] ) ) { - $objectArguments = $objectArguments[0]; - } - - return $this->newObject( $objectName, $objectArguments ); - } - - /** - * @see DependencyBuilder::getArgument - * - * @note Arguments are being preceded by a "arg_" to distinguish those - * objects internally from registered DI objects. The handling is only - * relevant for those internal functions and hidden from the public - * - * @since 1.9 - * - * @param string $key - * - * @return mixed - * @throws OutOfBoundsException - */ - public function getArgument( $key ) { - - if ( !( $this->hasArgument( $key ) ) ) { - throw new OutOfBoundsException( "'{$key}' argument is invalid or unknown." ); - } - - return $this->dependencyContainer->get( 'arg_' . $key ); - } - - /** - * @see DependencyBuilder::hasArgument - * - * @since 1.9 - * - * @param string $key - * - * @return mixed - * @throws InvalidArgumentException - */ - public function hasArgument( $key ) { - - if ( !is_string( $key ) ) { - throw new InvalidArgumentException( "Argument is not a string" ); - } - - return $this->dependencyContainer->has( 'arg_' . $key ); - } - - /** - * @see DependencyBuilder::addArgument - * - * @since 1.9 - * - * @param string $key - * @param mixed $value - * - * @return DependencyBuilder - * @throws InvalidArgumentException - */ - public function addArgument( $key, $value ) { - - if ( !is_string( $key ) ) { - throw new InvalidArgumentException( "Argument is not a string" ); - } - - $this->dependencyContainer->set( 'arg_' . $key, $value ); - - return $this; - } - - /** - * @see DependencyBuilder::setScope - * - * @since 1.9 - * - * @param $objectScope - * - * @return DependencyBuilder - */ - public function setScope( $objectScope ) { - $this->objectScope = $objectScope; - return $this; - } - - /** - * Builds an object from a registered specification - * - * @since 1.9 - * - * @param $object - * - * @return mixed - * @throws OutOfBoundsException - */ - protected function build( $objectName ) { - - if ( !$this->dependencyContainer->has( $objectName ) ) { - - if ( !$this->searchObjectByName( $objectName ) ) { - throw new OutOfBoundsException( "{$objectName} is not registered or available as service object" ); - }; - - } - - if ( $this->recursionLevel++ > $this->recursionDepth ) { - throw new OutOfBoundsException( "Possible circular reference for '{$objectName}' has been detected" ); - } - - list( $objectSignature, $objectScope ) = $this->dependencyContainer->get( $objectName ); - - if ( is_string( $objectSignature ) && class_exists( $objectSignature ) ) { - $objectSignature = new $objectSignature; - } - - if ( $objectSignature instanceOf DependencyObject ) { - $objectSignature = $objectSignature->retrieveDefinition( $this ); - } - - return $this->load( $objectName, $objectSignature, $objectScope ); - } - - /** - * Initializes an object in correspondence with its scope and specification - * - * @note An object scope invoked during the build process has priority - * over the original scope definition - * - * @param string $objectName - * @param mixed $objectSignature - * @param integer $objectScope - * - * @return mixed - */ - private function load( $objectName, $objectSignature, $objectScope ) { - - if ( $this->objectScope !== null ) { - $objectScope = $this->objectScope; - } - - if ( $objectScope === DependencyObject::SCOPE_SINGLETON ) { - $objectSignature = $this->singleton( $objectName, $objectSignature ); - } - - $instance = is_callable( $objectSignature ) ? $objectSignature( $this ) : $objectSignature; - - $this->objectScope = null; - $this->recursionLevel--; - - return $instance; - } - - /** - * Builds singleton instance - * - * @note A static context within a closure is kept static for its lifetime - * therefore any repeated call to the same instance within the same request - * will return the static context it was first initialized - * - * @note Objects with a singleton scope are internally stored and preceded by - * a 'sing_' as object identifier - * - * @param mixed $objectSignature - * - * @return Closure - */ - private function singleton( $objectName, $objectSignature ) { - - $objectName = 'sing_' . $objectName; - - if ( !$this->dependencyContainer->has( $objectName ) ) { - - // Resolves an object and uses the result for further processing - $object = is_callable( $objectSignature ) ? $objectSignature( $this ) : $objectSignature; - - // Binds static context - $singleton = function() use ( $object ) { - static $singleton; - return $singleton = $singleton === null ? $object : $singleton; - }; - - $this->dependencyContainer->set( $objectName, $singleton ); - } else { - $singleton = $this->dependencyContainer->get( $objectName ); - } - - return $singleton; - } - - /** - * @since 1.9 - * - * @return boolean - */ - private function searchObjectByName( $objectName ) { - - $objectCatalog = $this->dependencyContainer->loadAllDefinitions(); - - if ( isset( $objectCatalog[$objectName] ) ) { - - $this->dependencyContainer->registerObject( $objectName, $objectCatalog[$objectName] ); - return true; - - } - - return false; - } - -} diff --git a/SemanticMediaWiki/includes/exceptions/DataItemException.php b/SemanticMediaWiki/includes/exceptions/DataItemException.php deleted file mode 100644 index 15669c57..00000000 --- a/SemanticMediaWiki/includes/exceptions/DataItemException.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace SMW; - -use MWException; - -/** - * @codeCoverageIgnore - * Exception to be thrown when data items are created from unsuitable inputs - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - */ -class DataItemException extends MWException {} diff --git a/SemanticMediaWiki/includes/exceptions/InvalidNamespaceException.php b/SemanticMediaWiki/includes/exceptions/InvalidNamespaceException.php deleted file mode 100644 index 09f9c243..00000000 --- a/SemanticMediaWiki/includes/exceptions/InvalidNamespaceException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW; - -use MWException; - -/** - * Exception for an invalid namespace - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Exception for an invalid semantic data object - * - * @ingroup Exception - * @codeCoverageIgnore - */ -class InvalidNamespaceException extends MWException {}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/exceptions/InvalidPredefinedPropertyException.php b/SemanticMediaWiki/includes/exceptions/InvalidPredefinedPropertyException.php deleted file mode 100644 index cd4e2d87..00000000 --- a/SemanticMediaWiki/includes/exceptions/InvalidPredefinedPropertyException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -namespace SMW; - -/** - * Exception for an invalid predefined property - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Exception for an invalid predefined property - * - * @ingroup Exception - * @codeCoverageIgnore - */ -class InvalidPredefinedPropertyException extends InvalidPropertyException {}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/exceptions/InvalidPropertyException.php b/SemanticMediaWiki/includes/exceptions/InvalidPropertyException.php deleted file mode 100644 index 9e08f7bb..00000000 --- a/SemanticMediaWiki/includes/exceptions/InvalidPropertyException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -namespace SMW; - -/** - * Exception for an invalid property - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Exception for an invalid property - * - * @ingroup Exception - * @codeCoverageIgnore - */ -class InvalidPropertyException extends DataItemException {}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/exceptions/InvalidResultException.php b/SemanticMediaWiki/includes/exceptions/InvalidResultException.php deleted file mode 100644 index eee4dea7..00000000 --- a/SemanticMediaWiki/includes/exceptions/InvalidResultException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW; - -use MWException; - -/** - * Exception for an invalid result object - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Exception for an invalid result object - * - * @ingroup Exception - * @codeCoverageIgnore - */ -class InvalidResultException extends MWException {}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/exceptions/InvalidSemanticDataException.php b/SemanticMediaWiki/includes/exceptions/InvalidSemanticDataException.php deleted file mode 100644 index c0b89f83..00000000 --- a/SemanticMediaWiki/includes/exceptions/InvalidSemanticDataException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW; - -use MWException; - -/** - * Exception for an invalid semantic data object - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Exception for an invalid semantic data object - * - * @ingroup Exception - * @codeCoverageIgnore - */ -class InvalidSemanticDataException extends MWException {}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/exceptions/InvalidSettingsArgumentException.php b/SemanticMediaWiki/includes/exceptions/InvalidSettingsArgumentException.php deleted file mode 100644 index 3ced3172..00000000 --- a/SemanticMediaWiki/includes/exceptions/InvalidSettingsArgumentException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW; - -use MWException; - -/** - * Exception for an invalid settings argument - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Exception for an invalid settings argument - * - * @ingroup Exception - * @codeCoverageIgnore - */ -class InvalidSettingsArgumentException extends MWException {}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/exceptions/InvalidStoreException.php b/SemanticMediaWiki/includes/exceptions/InvalidStoreException.php deleted file mode 100644 index 1609beab..00000000 --- a/SemanticMediaWiki/includes/exceptions/InvalidStoreException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW; - -use MWException; - -/** - * Exception for an invalid store instance - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Exception for an invalid store instance - * - * @ingroup Exception - * @codeCoverageIgnore - */ -class InvalidStoreException extends MWException {}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/exceptions/UnknownIdException.php b/SemanticMediaWiki/includes/exceptions/UnknownIdException.php deleted file mode 100644 index 0f311692..00000000 --- a/SemanticMediaWiki/includes/exceptions/UnknownIdException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW; - -use MWException; - -/** - * Exception for an unknown Id - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Exception for an unknown Id - * - * @ingroup Exception - * @codeCoverageIgnore - */ -class UnknownIdException extends MWException {}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/export/SMW_Exp_Data.php b/SemanticMediaWiki/includes/export/SMW_Exp_Data.php deleted file mode 100644 index a430d490..00000000 --- a/SemanticMediaWiki/includes/export/SMW_Exp_Data.php +++ /dev/null @@ -1,255 +0,0 @@ -<?php -/** - * SMWExpData is a class representing semantic data that is ready for easy - * serialisation in OWL or RDF. - * - * @author Markus Krötzsch - * @file - * @ingroup SMW - */ - -/** - * SMWExpData is a data container for export-ready semantic content. It is - * organised as a tree-shaped data structure with one root subject and zero - * or more children connected with labelled edges to the root. Children are - * again SMWExpData objects, and edges are annotated with SMWExpNsElements - * specifying properties. - * @note We do not allow property element without namespace abbreviation - * here. Property aabbreviations are mandatory for some serialisations. - * - * @ingroup SMW - */ -class SMWExpData extends SMWExpElement { - /** - * The subject of the data that we store. - * @var SMWExpResource - */ - protected $m_subject; - /** - * Array mapping property URIs to arrays their values, given as - * SMWExpElement objects. - * @var array of array of SMWElement - */ - protected $m_children = array(); - /** - * Array mapping property URIs to arrays their SMWExpResource - * @var array of SMWExpResource - */ - protected $m_edges = array(); - - /** - * Constructor. $subject is the SMWExpResource for the - * subject about which this SMWExpData is. - */ - public function __construct( SMWExpResource $subject ) { - parent::__construct( $subject->getDataItem() ); - $this->m_subject = $subject; - } - - /** - * Turn an array of SMWExpElements into an RDF collection. - * - * @param $elements array of SMWExpElement - * @return SMWExpData - */ - public static function makeCollection( array $elements ) { - if ( count( $elements ) == 0 ) { - return new SMWExpData( SMWExporter::getSpecialNsResource( 'rdf', 'nil' ) ); - } else { - $rdftype = SMWExporter::getSpecialNsResource( 'rdf', 'type' ); - $rdffirst = SMWExporter::getSpecialNsResource( 'rdf', 'first' ); - $rdfrest = SMWExporter::getSpecialNsResource( 'rdf', 'rest' ); - $result = new SMWExpData( new SMWExpResource( '' ) ); // bnode - $result->addPropertyObjectValue( $rdftype, new SMWExpData( SMWExporter::getSpecialNsResource( 'rdf', 'List' ) ) ); - $result->addPropertyObjectValue( $rdffirst, array_shift( $elements ) ); - $result->addPropertyObjectValue( $rdfrest, SMWExpData::makeCollection( $elements ) ); - return $result; - } - } - - /** - * Return subject to which the stored semantic annotation refer to. - * - * @return SMWExpResource - */ - public function getSubject() { - return $this->m_subject; - } - - /** - * Store a value for a property identified by its title object. No - * duplicate elimination as this is usually done in SMWSemanticData - * already (which is typically used to generate this object). - * - * @param SMWExpNsResource $property - * @param SMWExpData $child - */ - public function addPropertyObjectValue( SMWExpNsResource $property, SMWExpElement $child ) { - if ( !array_key_exists( $property->getUri(), $this->m_edges ) ) { - $this->m_children[$property->getUri()] = array(); - $this->m_edges[$property->getUri()] = $property; - } - $this->m_children[$property->getUri()][] = $child; - } - - /** - * Return the list of SMWExpResource objects for all properties for - * which some values have been given. - * - * @return array of SMWExpResource - */ - public function getProperties() { - return $this->m_edges; - } - - /** - * Return the list of SMWExpElement values associated to some property - * (element). - * - * @return array of SMWExpElement - */ - public function getValues( SMWExpResource $property ) { - if ( array_key_exists( $property->getUri(), $this->m_children ) ) { - return $this->m_children[$property->getUri()]; - } else { - return array(); - } - } - - /** - * Return the list of SMWExpData values associated to some property that is - * specifed by a standard namespace id and local name. - * - * @param $namespaceId string idetifying a known special namespace (e.g. "rdf") - * @param $localName string of local name (e.g. "type") - * @return array of SMWExpData - */ - public function getSpecialValues( $namespaceId, $localName ) { - $pe = SMWExporter::getSpecialNsResource( $namespaceId, $localName ); - return $this->getValues( $pe ); - } - - /** - * This function finds the main type (class) element of the subject - * based on the current property assignments. It returns this type - * element (SMWExpElement) and removes the according type assignement - * from the data. If no type is assigned, the element for rdf:Resource - * is returned. - * - * @note Under all normal conditions, the result will be an - * SMWExpResource. - * - * @return SMWExpElement - */ - public function extractMainType() { - $pe = SMWExporter::getSpecialNsResource( 'rdf', 'type' ); - if ( array_key_exists( $pe->getUri(), $this->m_children ) ) { - $result = array_shift( $this->m_children[$pe->getUri()] ); - if ( count( $this->m_children[$pe->getUri()] ) == 0 ) { - unset( $this->m_edges[$pe->getUri()] ); - unset( $this->m_children[$pe->getUri()] ); - } - return ( $result instanceof SMWExpData ) ? $result->getSubject() : $result; - } else { - return SMWExporter::getSpecialNsResource( 'rdf', 'Resource' ); - } - } - - /** - * Check if this element encodes an RDF list, and if yes return an - * array of SMWExpElements corresponding to the collection elements in - * the specified order. Otherwise return false. - * The method only returns lists that can be encoded using - * parseType="Collection" in RDF/XML, i.e. only lists of non-literal - * resources. - * - * @return mixed array of SMWExpElement (but not SMWExpLiteral) or false - */ - public function getCollection() { - $rdftypeUri = SMWExporter::getSpecialNsResource( 'rdf', 'type' )->getUri(); - $rdffirstUri = SMWExporter::getSpecialNsResource( 'rdf', 'first' )->getUri(); - $rdfrestUri = SMWExporter::getSpecialNsResource( 'rdf', 'rest' )->getUri(); - $rdfnilUri = SMWExporter::getSpecialNsResource( 'rdf', 'nil' )->getUri(); - // first check if we are basically an RDF List: - if ( ( $this->m_subject->isBlankNode() ) && - ( count( $this->m_children ) == 3 ) && - ( array_key_exists( $rdftypeUri, $this->m_children ) ) && - ( count( $this->m_children[$rdftypeUri] ) == 1 ) && - ( array_key_exists( $rdffirstUri, $this->m_children ) ) && - ( count( $this->m_children[$rdffirstUri] ) == 1 ) && - !( end( $this->m_children[$rdffirstUri] ) instanceof SMWExpLiteral ) && - // (parseType collection in RDF not possible with literals :-/) - ( array_key_exists( $rdfrestUri, $this->m_children ) ) && - ( count( $this->m_children[$rdfrestUri] ) == 1 ) ) { - $typedata = end( $this->m_children[$rdftypeUri] ); - $rdflistUri = SMWExporter::getSpecialNsResource( 'rdf', 'List' )->getUri(); - if ( $typedata->getSubject()->getUri() == $rdflistUri ) { - $first = end( $this->m_children[$rdffirstUri] ); - $rest = end( $this->m_children[$rdfrestUri] ); - if ( $rest instanceof SMWExpData ) { - $restlist = $rest->getCollection(); - if ( $restlist === false ) { - return false; - } else { - array_unshift( $restlist, $first ); - return $restlist; - } - } elseif ( ( $rest instanceof SMWExpResource ) && - ( $rest->getUri() == $rdfnilUri ) ) { - return array( $first ); - } else { - return false; - } - } else { - return false; - } - } elseif ( ( count( $this->m_children ) == 0 ) && ( $this->m_subject->getUri() == $rdfnilUri ) ) { - return array(); - } else { - return false; - } - } - - /** - * Return an array of ternary arrays (subject predicate object) of - * SMWExpElements that represents the flattened version of this data. - * - * @return array of array of SMWExpElement - */ - public function getTripleList( SMWExpElement $subject = null ) { - global $smwgBnodeCount; - if ( !isset( $smwgBnodeCount ) ) { - $smwgBnodeCount = 0; - } - - if ( $subject == null ) { - $subject = $this->m_subject; - } - - $result = array(); - - foreach ( $this->m_edges as $key => $edge ) { - foreach ( $this->m_children[$key] as $childElement ) { - if ( $childElement instanceof SMWExpData ) { - $childSubject = $childElement->getSubject(); - } else { - $childSubject = $childElement; - } - - if ( ( $childSubject instanceof SMWExpResource ) && - ( $childSubject->isBlankNode() ) ) { // bnode, rename ID to avoid unifying bnodes of different contexts - // TODO: should we really rename bnodes of the form "_id" here? - $childSubject = new SMWExpResource( '_' . $smwgBnodeCount++, $childSubject->getDataItem() ); - } - - $result[] = array( $subject, $edge, $childSubject ); - if ( $childElement instanceof SMWExpData ) { // recursively add child's triples - $result = array_merge( $result, $childElement->getTripleList( $childSubject ) ); - } - } - } - - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/export/SMW_Exp_Element.php b/SemanticMediaWiki/includes/export/SMW_Exp_Element.php deleted file mode 100644 index 8cba4b4e..00000000 --- a/SemanticMediaWiki/includes/export/SMW_Exp_Element.php +++ /dev/null @@ -1,282 +0,0 @@ -<?php -/** - * SMWExpElement is a class for representing single elements that appear in - * exported data, such as individual resources, data literals, or blank nodes. - * - * @author Markus Krötzsch - * @file - * @ingroup SMW - */ - -/** - * A single element for export, e.g. a data literal, instance name, or blank - * node. This abstract base class declares the basic common functionality of - * export elements (which is not much, really). - * @note This class should not be instantiated directly. - * - * @ingroup SMW - */ -abstract class SMWExpElement { - - /** - * The SMWDataItem that this export element is associated with, if - * any. Might be unset if not given yet. - * - * @var SMWDataItem|null - */ - protected $dataItem; - - /** - * Constructor. - * - * @param $dataItem SMWDataItem|null - */ - public function __construct( SMWDataItem $dataItem = null ) { - $this->dataItem = $dataItem; - } - - /** - * Get a SMWDataItem object that represents the contents of this export - * element in SMW, or null if no such data item could be found. - * - * @return SMWDataItem|null - */ - public function getDataItem() { - return $this->dataItem; - } -} - -/** - * A single resource (individual) for export, as defined by a URI. - * This class can also be used to represent blank nodes: It is assumed that all - * objects of class SMWExpElement or any of its subclasses represent a blank - * node if their name is empty or of the form "_id" where "id" is any - * identifier string. IDs are local to the current context, such as a list of - * triples or an SMWExpData container. - * - * @ingroup SMW - */ -class SMWExpResource extends SMWExpElement { - - /** - * @var string - */ - protected $uri; - - /** - * Constructor. The given URI must not contain serialization-specific - * abbreviations or escapings, such as XML entities. - * - * @param string $uri The full URI - * @param SMWDataItem|null $dataItem - * - * @throws InvalidArgumentException - */ - public function __construct( $uri, SMWDataItem $dataItem = null ) { - if ( !is_string( $uri ) ) { - throw new InvalidArgumentException( '$uri needs to be a string' ); - } - - parent::__construct( $dataItem ); - - $this->uri = $uri; - } - - /** - * Return true if this resource represents a blank node. - * - * @return boolean - */ - public function isBlankNode() { - return $this->uri === '' || $this->uri{0} == '_'; - } - - /** - * Get the URI of this resource. The result is a UTF-8 encoded URI (or - * IRI) without any escaping. - * - * @return string - */ - public function getUri() { - return $this->uri; - } - -} - - -/** - * A single resource (individual) for export, defined by a URI for which there - * also is a namespace abbreviation. - * - * @ingroup SMW - */ -class SMWExpNsResource extends SMWExpResource { - - /** - * Namespace URI prefix of the abbreviated URI - * @var string - */ - protected $namespace; - - /** - * Namespace abbreviation of the abbreviated URI - * @var string - */ - protected $namespaceId; - - /** - * Local part of the abbreviated URI - * @var string - */ - protected $localName; - - /** - * Constructor. The given URI must not contain serialization-specific - * abbreviations or escapings, such as XML entities. - * - * @param string $localName Local part of the abbreviated URI - * @param string $namespace Namespace URI prefix of the abbreviated URI - * @param string $namespaceId Namespace abbreviation of the abbreviated URI - * @param SMWDataItem|null $dataItem - * - * @throws InvalidArgumentException - */ - public function __construct( $localName, $namespace, $namespaceId, SMWDataItem $dataItem = null ) { - if ( !is_string( $localName ) ) { - throw new InvalidArgumentException( '$localName needs to be a string' ); - } - - if ( !is_string( $namespace ) ) { - throw new InvalidArgumentException( '$namespace needs to be a string' ); - } - - if ( !is_string( $namespaceId ) ) { - throw new InvalidArgumentException( '$namespaceId needs to be a string' ); - } - - parent::__construct( $namespace . $localName, $dataItem ); - - $this->namespace = $namespace; - $this->namespaceId = $namespaceId; - $this->localName = $localName; - } - - /** - * Return a qualified name for the element. - * - * @return string - */ - public function getQName() { - return $this->namespaceId . ':' . $this->localName; - } - - /** - * Get the namespace identifier used (the part before :). - * - * @return string - */ - public function getNamespaceId() { - return $this->namespaceId; - } - - /** - * Get the namespace URI that is used in the abbreviation. - * - * @return string - */ - public function getNamespace() { - return $this->namespace; - } - - /** - * Get the local name (the part after :). - * - * @return string - */ - public function getLocalName() { - return $this->localName; - } - - /** - * Check if the local name is qualifies as a local name in XML and - * Turtle. The function returns true if this is surely the case, and - * false if it may not be the case. However, we do not check the whole - * range of allowed Unicode entities for performance reasons. - * - * @return boolean - */ - public function hasAllowedLocalName() { - return preg_match( '/^[A-Za-z_][-A-Za-z_0-9]*$/u', $this->localName ); - } - -} - -/** - * A single datatype literal for export. Defined by a literal value and a - * datatype URI. - * - * @todo Currently no support for language tags. - * - * @ingroup SMW - */ -class SMWExpLiteral extends SMWExpElement { - - /** - * Datatype URI for the literal. - * @var string - */ - protected $datatype; - - /** - * Lexical form of the literal. - * @var string - */ - protected $lexicalForm; - - /** - * Constructor. The given lexical form should be the plain string for - * representing the literal without datatype or language information. - * It must not use any escaping or abbreviation mechanisms. - * - * @param string $lexicalForm lexical form - * @param string $datatype Data type URI or empty for untyped literals - * @param SMWDataItem|null $dataItem - * - * @throws InvalidArgumentException - */ - public function __construct( $lexicalForm, $datatype = '', SMWDataItem $dataItem = null ) { - if ( !is_string( $lexicalForm ) ) { - throw new InvalidArgumentException( '$lexicalForm needs to be a string' ); - } - - if ( !is_string( $datatype ) ) { - throw new InvalidArgumentException( '$datatype needs to be a string' ); - } - - parent::__construct( $dataItem ); - - $this->lexicalForm = $lexicalForm; - $this->datatype = $datatype; - } - - /** - * Return the URI of the datatype used, or the empty string if untyped. - * - * @return string - */ - public function getDatatype() { - return $this->datatype; - } - - /** - * Return the lexical form of the literal. The result does not use - * any escapings and might still need to be escaped in some contexts. - * The lexical form is not validated or canonicalized. - * - * @return string - */ - public function getLexicalForm() { - return $this->lexicalForm; - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/export/SMW_ExportController.php b/SemanticMediaWiki/includes/export/SMW_ExportController.php deleted file mode 100644 index d305ebe5..00000000 --- a/SemanticMediaWiki/includes/export/SMW_ExportController.php +++ /dev/null @@ -1,633 +0,0 @@ -<?php - -/** - * File holding the SMWExportController class that provides basic functions for - * exporting pages to RDF and OWL. - * - * @file SMW_ExportController.php - * @ingroup SMW - * - * @author Markus Krötzsch - */ - -/** - * Class for controlling the export of SMW page data, supporting high-level - * features such as recursive export and backlink inclusion. The class controls - * export independent of the serialisation syntax that is used. - * - * @ingroup SMW - */ -class SMWExportController { - const MAX_CACHE_SIZE = 5000; // do not let cache arrays get larger than this - const CACHE_BACKJUMP = 500; // kill this many cached entries if limit is reached, - // avoids too much array copying; <= MAX_CACHE_SIZE! - /** - * The object used for serialisation. - * @var SMWSerializer - */ - protected $serializer; - /** - * An array that keeps track of the elements for which we still need to - * write auxiliary definitions/declarations. - */ - protected $element_queue; - /** - * An array that keeps track of the recursion depth with which each object - * has been serialised. - */ - protected $element_done; - /** - * Boolean to indicate whether all objects that are exported in full (with - * all data) should also lead to the inclusion of all "inlinks" that they - * receive from other objects. If yes, these other objects are also - * serialised with at least the relevant inlinking properties included. - * Adding such dependencies counts as "recursive serialisation" and whether - * or not inlinking objects are included in full depends on the setting for - * recursion depth. Setting this to true enables "browsable RDF". - */ - protected $add_backlinks; - /** - * Controls how long to wait until flushing content to output. Flushing - * early may reduce the memory footprint of serialization functions. - * Flushing later has some advantages for export formats like RDF/XML where - * global namespace declarations are only possible by modifying the header, - * so that only local declarations are possible after the first flush. - */ - protected $delay_flush; - /** - * File handle for a potential output file to write to, or null if printing - * to standard output. - */ - protected $outputfile; - - /** - * Constructor. - * @param SMWSerializer $serializer defining the object used for syntactic - * serialization. - * @param boolean $enable_backlinks defining if backlinks are included, - * see $add_backlinks for details. - */ - public function __construct( SMWSerializer $serializer, $enable_backlinks = false ) { - $this->serializer = $serializer; - $this->outputfile = null; - $this->add_backlinks = $enable_backlinks; - } - - /** - * Enable or disable inclusion of backlinks into the output. - * @param boolean $enable - */ - public function enableBacklinks( $enable ) { - $this->add_backlinks = $enable; - } - - /** - * Initialize all internal structures to begin with some serialization. - * Returns true if initialization was successful (this means that the - * optional output file is writable). - * @param string $outfilename URL of the file that output should be written - * to, or empty string for writting to the standard output. - */ - protected function prepareSerialization( $outfilename = '' ) { - $this->serializer->clear(); - $this->element_queue = array(); - $this->element_done = array(); - if ( $outfilename !== '' ) { - $this->outputfile = fopen( $outfilename, 'w' ); - if ( !$this->outputfile ) { // TODO Rather throw an exception here. - print "\nCannot open \"$outfilename\" for writing.\n"; - return false; - } - } - return true; - } - - /** - * Serialize data associated to a specific page. This method works on the - * level of pages, i.e. it serialises parts of SMW content and implements - * features like recursive export or backlinks that are available for this - * type of data. - * - * The recursion depth means the following. Depth of 1 or above means - * the object is serialised with all property values, and referenced - * objects are serialised with depth reduced by 1. Depth 0 means that only - * minimal declarations are serialised, so no dependencies are added. A - * depth of -1 encodes "infinite" depth, i.e. a complete recursive - * serialisation without limit. - * - * @param SMWDIWikiPage $diWikiPage specifying the page to be exported - * @param integer $recursiondepth specifying the depth of recursion - */ - protected function serializePage( SMWDIWikiPage $diWikiPage, $recursiondepth = 1 ) { - if ( $this->isPageDone( $diWikiPage, $recursiondepth ) ) return; // do not export twice - $this->markPageAsDone( $diWikiPage, $recursiondepth ); - $semData = $this->getSemanticData( $diWikiPage, ( $recursiondepth == 0 ) ); - $expData = SMWExporter::makeExportData( $semData ); - $this->serializer->serializeExpData( $expData, $recursiondepth ); - - foreach( $semData->getSubSemanticData() as $subobjectSemData ) { - $this->serializer->serializeExpData( SMWExporter::makeExportData( $subobjectSemData ) ); - } - - // let other extensions add additional RDF data for this page - $additionalDataArray = array(); - wfRunHooks( 'smwAddToRDFExport', array( $diWikiPage, &$additionalDataArray, ( $recursiondepth != 0 ), $this->add_backlinks ) ); - foreach ( $additionalDataArray as $additionalData ) { - $this->serializer->serializeExpData( $additionalData ); // serialise - } - - if ( $recursiondepth != 0 ) { - $subrecdepth = $recursiondepth > 0 ? ( $recursiondepth - 1 ) : - ( $recursiondepth == 0 ? 0 : -1 ); - - foreach ( $expData->getProperties() as $property ) { - if ( $property->getDataItem() instanceof SMWWikiPageValue ) { - $this->queuePage( $property->getDataItem(), 0 ); // no real recursion along properties - } - $wikipagevalues = false; - foreach ( $expData->getValues( $property ) as $valueExpElement ) { - $valueResource = $valueExpElement instanceof SMWExpData ? $valueExpElement->getSubject() : $valueExpElement; - if ( !$wikipagevalues && ( $valueResource->getDataItem() instanceof SMWWikiPageValue ) ) { - $wikipagevalues = true; - } elseif ( !$wikipagevalues ) { - break; - } - $this->queuePage( $valueResource->getDataItem(), $subrecdepth ); - } - } - - // Add backlinks: - // Note: Backlinks are different from recursive serialisations, since - // stub declarations (recdepth==0) still need to have the property that - // links back to the object. So objects that would be exported with - // recdepth 0 cannot be put into the main queue but must be done right - // away. They also might be required many times, if they link back to - // many different objects in many ways (we cannot consider them "Done" - // if they were serialised at recdepth 0 only). - if ( $this->add_backlinks ) { - wfProfileIn( "RDF::PrintPages::GetBacklinks" ); - $inprops = \SMW\StoreFactory::getStore()->getInProperties( $diWikiPage ); - - foreach ( $inprops as $inprop ) { - $propWikiPage = $inprop->getDiWikiPage(); - - if ( !is_null( $propWikiPage ) ) { - $this->queuePage( $propWikiPage, 0 ); // no real recursion along properties - } - - $inSubs = \SMW\StoreFactory::getStore()->getPropertySubjects( $inprop, $diWikiPage ); - - foreach ( $inSubs as $inSub ) { - if ( !$this->isPageDone( $inSub, $subrecdepth ) ) { - $semdata = $this->getSemanticData( $inSub, true ); - $semdata->addPropertyObjectValue( $inprop, $diWikiPage ); - $expData = SMWExporter::makeExportData( $semdata ); - $this->serializer->serializeExpData( $expData, $subrecdepth ); - } - } - } - - if ( NS_CATEGORY === $diWikiPage->getNamespace() ) { // also print elements of categories - $options = new SMWRequestOptions(); - $options->limit = 100; // Categories can be large, always use limit - $instances = \SMW\StoreFactory::getStore()->getPropertySubjects( new SMWDIProperty( '_INST' ), $diWikiPage, $options ); - $pinst = new SMWDIProperty( '_INST' ); - - foreach ( $instances as $instance ) { - if ( !array_key_exists( $instance->getHash(), $this->element_done ) ) { - $semdata = $this->getSemanticData( $instance, true ); - $semdata->addPropertyObjectValue( $pinst, $diWikiPage ); - $expData = SMWExporter::makeExportData( $semdata ); - $this->serializer->serializeExpData( $expData, $subrecdepth ); - } - } - } elseif ( SMW_NS_CONCEPT === $diWikiPage->getNamespace() ) { // print concept members (slightly different code) - $desc = new SMWConceptDescription( $diWikiPage ); - $desc->addPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, '' ) ); - $query = new SMWQuery( $desc ); - $query->setLimit( 100 ); - - $res = \SMW\StoreFactory::getStore()->getQueryResult( $query ); - $resarray = $res->getNext(); - $pinst = new SMWDIProperty( '_INST' ); - - while ( $resarray !== false ) { - $instance = end( $resarray )->getNextDataItem(); - - if ( !array_key_exists( $instance->getHash(), $this->element_done ) ) { - $semdata = $this->getSemanticData( $instance, true ); - $semdata->addPropertyObjectValue( $pinst, $diWikiPage ); - $expData = SMWExporter::makeExportData( $semdata ); - $this->serializer->serializeExpData( $expData ); - } - - $resarray = $res->getNext(); - } - } - wfProfileOut( "RDF::PrintPages::GetBacklinks" ); - } - } - } - - /** - * Add a given SMWDIWikiPage to the export queue if needed. - */ - protected function queuePage( SMWDIWikiPage $diWikiPage, $recursiondepth ) { - if ( !$this->isPageDone( $diWikiPage, $recursiondepth ) ) { - $diWikiPage->recdepth = $recursiondepth; // add a field - $this->element_queue[$diWikiPage->getHash()] = $diWikiPage; - } - } - - /** - * Mark an article as done while making sure that the cache used for this - * stays reasonably small. Input is given as an SMWDIWikiPage object. - */ - protected function markPageAsDone( SMWDIWikiPage $di, $recdepth ) { - $this->markHashAsDone( $di->getHash(), $recdepth ); - } - - /** - * Mark a task as done while making sure that the cache used for this - * stays reasonably small. - */ - protected function markHashAsDone( $hash, $recdepth ) { - if ( count( $this->element_done ) >= self::MAX_CACHE_SIZE ) { - $this->element_done = array_slice( $this->element_done, - self::CACHE_BACKJUMP, - self::MAX_CACHE_SIZE - self::CACHE_BACKJUMP, - true ); - } - if ( !$this->isHashDone( $hash, $recdepth ) ) { - $this->element_done[$hash] = $recdepth; // mark title as done, with given recursion - } - unset( $this->element_queue[$hash] ); // make sure it is not in the queue - } - - /** - * Check if the given object has already been serialised at sufficient - * recursion depth. - * @param SMWDIWikiPage $st specifying the object to check - */ - protected function isPageDone( SMWDIWikiPage $di, $recdepth ) { - return $this->isHashDone( $di->getHash(), $recdepth ); - } - - /** - * Check if the given task has already been completed at sufficient - * recursion depth. - */ - protected function isHashDone( $hash, $recdepth ) { - return ( ( array_key_exists( $hash, $this->element_done ) ) && - ( ( $this->element_done[$hash] == -1 ) || - ( ( $recdepth != -1 ) && ( $this->element_done[$hash] >= $recdepth ) ) ) ); - } - - /** - * Retrieve a copy of the semantic data for a wiki page, possibly filtering - * it so that only essential properties are included (in some cases, we only - * want to export stub information about a page). - * We make a copy of the object since we may want to add more data later on - * and we do not want to modify the store's result which may be used for - * caching purposes elsewhere. - */ - protected function getSemanticData( SMWDIWikiPage $diWikiPage, $core_props_only ) { - $semdata = \SMW\StoreFactory::getStore()->getSemanticData( $diWikiPage, $core_props_only ? array( '__spu', '__typ', '__imp' ) : false ); // advise store to retrieve only core things - if ( $core_props_only ) { // be sure to filter all non-relevant things that may still be present in the retrieved - $result = new SMWSemanticData( $diWikiPage ); - foreach ( array( '_URI', '_TYPE', '_IMPO' ) as $propid ) { - $prop = new SMWDIProperty( $propid ); - $values = $semdata->getPropertyValues( $prop ); - foreach ( $values as $dv ) { - $result->addPropertyObjectValue( $prop, $dv ); - } - } - } else { - $result = clone $semdata; - } - return $result; - } - - /** - * Send to the output what has been serialized so far. The flush might - * be deferred until later unless $force is true. - */ - protected function flush( $force = false ) { - if ( !$force && ( $this->delay_flush > 0 ) ) { - $this->delay_flush -= 1; - } elseif ( !is_null( $this->outputfile ) ) { - fwrite( $this->outputfile, $this->serializer->flushContent() ); - } else { - ob_start(); - print $this->serializer->flushContent(); - // Ship data in small chunks (even though browsers often do not display anything - // before the file is complete -- this might be due to syntax highlighting features - // for app/xml). You may want to sleep(1) here for debugging this. - ob_flush(); - flush(); - ob_get_clean(); - } - } - - /** - * This function prints all selected pages, specified as an array of page - * names (strings with namespace identifiers). - * - * @param array $pages list of page names to export - * @param integer $recursion determines how pages are exported recursively: - * "0" means that referenced resources are only declared briefly, "1" means - * that all referenced resources are also exported recursively (propbably - * retrieving the whole wiki). - * @param string $revisiondate filter page list by including only pages - * that have been changed since this date; format "YmdHis" - * - * @todo Consider dropping the $revisiondate filtering and all associated - * functionality. Is anybody using this? - */ - public function printPages( $pages, $recursion = 1, $revisiondate = false ) { - wfProfileIn( "RDF::PrintPages" ); - - $linkCache = LinkCache::singleton(); - $this->prepareSerialization(); - $this->delay_flush = 10; // flush only after (fully) printing 11 objects - - // transform pages into queued short titles - foreach ( $pages as $page ) { - $title = Title::newFromText( $page ); - if ( null === $title ) continue; // invalid title name given - if ( $revisiondate !== '' ) { // filter page list by revision date - $rev = Revision::getTimeStampFromID( $title, $title->getLatestRevID() ); - if ( $rev < $revisiondate ) continue; - } - - $diPage = SMWDIWikiPage::newFromTitle( $title ); - $this->queuePage( $diPage, ( $recursion==1 ? -1 : 1 ) ); - } - - $this->serializer->startSerialization(); - - if ( count( $pages ) == 1 ) { // ensure that ontologies that are retrieved as linked data are not confused with their subject! - $ontologyuri = SMWExporter::expandURI( '&export;' ) . '/' . urlencode( end( $pages ) ); - } else { // use empty URI, i.e. "location" as URI otherwise - $ontologyuri = ''; - } - $this->serializer->serializeExpData( SMWExporter::getOntologyExpData( $ontologyuri ) ); - - while ( count( $this->element_queue ) > 0 ) { - $diPage = reset( $this->element_queue ); - $this->serializePage( $diPage, $diPage->recdepth ); - $this->flush(); - $linkCache->clear(); // avoid potential memory leak - } - $this->serializer->finishSerialization(); - $this->flush( true ); - - wfProfileOut( "RDF::PrintPages" ); - } - - /** - * Exports semantic data for all pages within the wiki and for all elements - * that are referred to a file resource - * - * @since 2.0 - * - * @param string $outfile the output file URI, or false if printing to stdout - * @param mixed $ns_restriction namespace restriction, see fitsNsRestriction() - * @param integer $delay number of microseconds for which to sleep during - * export to reduce server load in long-running operations - * @param integer $delayeach number of pages to process between two sleeps - */ - public function printAllToFile( $outfile, $ns_restriction = false, $delay, $delayeach ) { - - if ( !$this->prepareSerialization( $outfile ) ) { - return; - } - - $this->printAll( $ns_restriction, $delay, $delayeach ); - } - - /** - * Exports semantic data for all pages within the wiki and for all elements - * that are referred to the stdout - * - * @since 2.0 - * - * @param mixed $ns_restriction namespace restriction, see fitsNsRestriction() - * @param integer $delay number of microseconds for which to sleep during - * export to reduce server load in long-running operations - * @param integer $delayeach number of pages to process between two sleeps - */ - public function printAllToOutput( $ns_restriction = false, $delay, $delayeach ) { - $this->prepareSerialization(); - $this->printAll( $ns_restriction, $delay, $delayeach ); - } - - /** - * @since 2.0 made protected; use printAllToFile or printAllToOutput - */ - protected function printAll( $ns_restriction = false, $delay, $delayeach ) { - $linkCache = LinkCache::singleton(); - $db = wfGetDB( DB_SLAVE ); - - $this->delay_flush = 10; - - $this->serializer->startSerialization(); - $this->serializer->serializeExpData( SMWExporter::getOntologyExpData( '' ) ); - - $end = $db->selectField( 'page', 'max(page_id)', false, __METHOD__ ); - $a_count = 0; $d_count = 0; // DEBUG - $delaycount = $delayeach; - - for ( $id = 1; $id <= $end; $id += 1 ) { - $title = Title::newFromID( $id ); - if ( is_null( $title ) || !smwfIsSemanticsProcessed( $title->getNamespace() ) ) continue; - if ( !SMWExportController::fitsNsRestriction( $ns_restriction, $title->getNamespace() ) ) continue; - $a_count += 1; // DEBUG - - $diPage = SMWDIWikiPage::newFromTitle( $title ); - $this->queuePage( $diPage, 1 ); - - while ( count( $this->element_queue ) > 0 ) { - $diPage = reset( $this->element_queue ); - $this->serializePage( $diPage, $diPage->recdepth ); - // resolve dependencies that will otherwise not be printed - foreach ( $this->element_queue as $key => $diaux ) { - if ( !smwfIsSemanticsProcessed( $diaux->getNamespace() ) || - !SMWExportController::fitsNsRestriction( $ns_restriction, $diaux->getNamespace() ) ) { - // Note: we do not need to check the cache to guess if an element was already - // printed. If so, it would not be included in the queue in the first place. - $d_count += 1; // DEBUG - } else { // don't carry values that you do not want to export (yet) - unset( $this->element_queue[$key] ); - } - } - // sleep each $delaycount for $delay µs to be nice to the server - if ( ( $delaycount-- < 0 ) && ( $delayeach != 0 ) ) { - usleep( $delay ); - $delaycount = $delayeach; - } - } - - $this->flush(); - $linkCache->clear(); - } - - $this->serializer->finishSerialization(); - $this->flush( true ); - } - - /** - * Print basic definitions a list of pages ordered by their page id. - * Offset and limit refer to the count of existing pages, not to the - * page id. - * @param integer $offset the number of the first (existing) page to - * serialize a declaration for - * @param integer $limit the number of pages to serialize - */ - public function printPageList( $offset = 0, $limit = 30 ) { - global $smwgNamespacesWithSemanticLinks; - wfProfileIn( "RDF::PrintPageList" ); - - $db = wfGetDB( DB_SLAVE ); - $this->prepareSerialization(); - $this->delay_flush = 35; // don't do intermediate flushes with default parameters - $linkCache = LinkCache::singleton(); - - $this->serializer->startSerialization(); - $this->serializer->serializeExpData( SMWExporter::getOntologyExpData( '' ) ); - - $query = ''; - foreach ( $smwgNamespacesWithSemanticLinks as $ns => $enabled ) { - if ( $enabled ) { - if ( $query !== '' ) $query .= ' OR '; - $query .= 'page_namespace = ' . $db->addQuotes( $ns ); - } - } - $res = $db->select( $db->tableName( 'page' ), - 'page_id,page_title,page_namespace', $query - , 'SMW::RDF::PrintPageList', array( 'ORDER BY' => 'page_id ASC', 'OFFSET' => $offset, 'LIMIT' => $limit ) ); - $foundpages = false; - - foreach ( $res as $row ) { - $foundpages = true; - try { - $diPage = new SMWDIWikiPage( $row->page_title, $row->page_namespace, '' ); - $this->serializePage( $diPage, 0 ); - $this->flush(); - $linkCache->clear(); - } catch ( SMWDataItemException $e ) { - // strange data, who knows, not our DB table, keep calm and carry on - } - } - - if ( $foundpages ) { // add link to next result page - if ( strpos( SMWExporter::expandURI( '&wikiurl;' ), '?' ) === false ) { // check whether we have title as a first parameter or in URL - $nexturl = SMWExporter::expandURI( '&export;?offset=' ) . ( $offset + $limit ); - } else { - $nexturl = SMWExporter::expandURI( '&export;&offset=' ) . ( $offset + $limit ); - } - - $expData = new SMWExpData( new SMWExpResource( $nexturl ) ); - $ed = new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Thing' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdf', 'type' ), $ed ); - $ed = new SMWExpData( new SMWExpResource( $nexturl ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdfs', 'isDefinedBy' ), $ed ); - $this->serializer->serializeExpData( $expData ); - } - - $this->serializer->finishSerialization(); - $this->flush( true ); - - wfProfileOut( "RDF::PrintPageList" ); - } - - - /** - * Print basic information about this site. - */ - public function printWikiInfo() { - wfProfileIn( "RDF::PrintWikiInfo" ); - - global $wgSitename, $wgLanguageCode; - - $this->prepareSerialization(); - $this->delay_flush = 35; // don't do intermediate flushes with default parameters - - // assemble export data: - $expData = new SMWExpData( new SMWExpResource( '&wiki;#wiki' ) ); - $ed = new SMWExpData( SMWExporter::getSpecialNsResource( 'swivt', 'Wikisite' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdf', 'type' ), $ed ); - // basic wiki information - $ed = new SMWExpData( new SMWExpLiteral( $wgSitename ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdfs', 'label' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( $wgSitename, null, 'http://www.w3.org/2001/XMLSchema#string' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'siteName' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( SMWExporter::expandURI( '&wikiurl;' ), null, 'http://www.w3.org/2001/XMLSchema#string' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'pagePrefix' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( SMW_VERSION, null, 'http://www.w3.org/2001/XMLSchema#string' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'smwVersion' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( $wgLanguageCode, null, 'http://www.w3.org/2001/XMLSchema#string' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'langCode' ), $ed ); - $mainpage = Title::newMainPage(); - - if ( !is_null( $mainpage ) ) { - $ed = new SMWExpData( new SMWExpResource( $mainpage->getFullURL() ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'mainPage' ), $ed ); - } - - // statistical information - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::pages(), null, 'http://www.w3.org/2001/XMLSchema#int' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'pageCount' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::articles(), null, 'http://www.w3.org/2001/XMLSchema#int' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'contentPageCount' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::images(), null, 'http://www.w3.org/2001/XMLSchema#int' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'mediaCount' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::edits(), null, 'http://www.w3.org/2001/XMLSchema#int' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'editCount' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::views(), null, 'http://www.w3.org/2001/XMLSchema#int' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'viewCount' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::users(), null, 'http://www.w3.org/2001/XMLSchema#int' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'userCount' ), $ed ); - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::numberingroup( 'sysop' ), null, 'http://www.w3.org/2001/XMLSchema#int' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'swivt', 'adminCount' ), $ed ); - - $this->serializer->startSerialization(); - $this->serializer->serializeExpData( SMWExporter::getOntologyExpData( '' ) ); - $this->serializer->serializeExpData( $expData ); - - // link to list of existing pages: - if ( strpos( SMWExporter::expandURI( '&wikiurl;' ), '?' ) === false ) { // check whether we have title as a first parameter or in URL - $nexturl = SMWExporter::expandURI( '&export;?offset=0' ); - } else { - $nexturl = SMWExporter::expandURI( '&export;&offset=0' ); - } - $expData = new SMWExpData( new SMWExpResource( $nexturl ) ); - $ed = new SMWExpData( SMWExporter::getSpecialNsResource( 'owl', 'Thing' ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdf', 'type' ), $ed ); - $ed = new SMWExpData( new SMWExpResource( $nexturl ) ); - $expData->addPropertyObjectValue( SMWExporter::getSpecialNsResource( 'rdfs', 'isDefinedBy' ), $ed ); - $this->serializer->serializeExpData( $expData ); - - $this->serializer->finishSerialization(); - $this->flush( true ); - - wfProfileOut( "RDF::PrintWikiInfo" ); - } - - /** - * This function checks whether some article fits into a given namespace - * restriction. Restrictions are encoded as follows: a non-negative number - * requires the namespace to be identical to the given number; "-1" - * requires the namespace to be different from Category, Property, and - * Type; "false" means "no restriction". - * @param $res mixed encoding the restriction as described above - * @param $ns integer the namespace constant to be checked - */ - static public function fitsNsRestriction( $res, $ns ) { - if ( $res === false ) return true; - if ( is_array( $res ) ) return in_array( $ns, $res ); - if ( $res >= 0 ) return ( $res == $ns ); - return ( ( $res != NS_CATEGORY ) && ( $res != SMW_NS_PROPERTY ) && ( $res != SMW_NS_TYPE ) ); - } - -} diff --git a/SemanticMediaWiki/includes/export/SMW_Exporter.php b/SemanticMediaWiki/includes/export/SMW_Exporter.php deleted file mode 100644 index c8ec2835..00000000 --- a/SemanticMediaWiki/includes/export/SMW_Exporter.php +++ /dev/null @@ -1,737 +0,0 @@ -<?php - -use SMW\DataTypeRegistry; -use SMW\DataValueFactory; -use SMW\DIProperty; -use SMW\DIWikiPage; - -/** - * SMWExporter is a class for converting internal page-based data (SMWSemanticData) into - * a format for easy serialisation in OWL or RDF. - * - * @author Markus Krötzsch - * @ingroup SMW - */ -class SMWExporter { - - /** - * @var SMWExporter - */ - private static $instance = null; - - static protected $m_exporturl = false; - static protected $m_ent_wiki = false; - static protected $m_ent_property = false; - static protected $m_ent_wikiurl = false; - - /** - * @since 2.0 - * - * @return SMWExporter - */ - public static function getInstance() { - - if ( self::$instance === null ) { - - self::$instance = new self(); - self::$instance->initBaseURIs(); - } - - return self::$instance; - } - - /** - * @since 2.0 - */ - public static function clear() { - self::$instance = null; - } - - /** - * Make sure that necessary base URIs are initialised properly. - */ - static public function initBaseURIs() { - if ( self::$m_exporturl !== false ) return; - global $wgContLang, $wgServer, $wgArticlePath; - - global $smwgNamespace; // complete namespace for URIs (with protocol, usually http://) - if ( '' == $smwgNamespace ) { - $resolver = SpecialPage::getTitleFor( 'URIResolver' ); - $smwgNamespace = $resolver->getFullURL() . '/'; - } elseif ( $smwgNamespace[0] == '.' ) { - $resolver = SpecialPage::getTitleFor( 'URIResolver' ); - $smwgNamespace = "http://" . substr( $smwgNamespace, 1 ) . $resolver->getLocalURL() . '/'; - } - - // The article name must be the last part of wiki URLs for proper OWL/RDF export: - self::$m_ent_wikiurl = $wgServer . str_replace( '$1', '', $wgArticlePath ); - self::$m_ent_wiki = $smwgNamespace; - self::$m_ent_property = self::$m_ent_wiki . self::encodeURI( urlencode( str_replace( ' ', '_', $wgContLang->getNsText( SMW_NS_PROPERTY ) . ':' ) ) ); - $title = SpecialPage::getTitleFor( 'ExportRDF' ); - self::$m_exporturl = self::$m_ent_wikiurl . $title->getPrefixedURL(); - } - - /** - * @since 2.0 - * - * @return string - */ - public function getEncodedPropertyNamespace() { - return $this->encodeURI( urlencode( str_replace( ' ', '_', $GLOBALS['wgContLang']->getNsText( SMW_NS_PROPERTY ) . ':' ) ) ); - } - - /** - * Create exportable data from a given semantic data record. - * - * @param $semdata SMWSemanticData - * @return SMWExpData - */ - static public function makeExportData( SMWSemanticData $semdata ) { - self::initBaseURIs(); - $subject = $semdata->getSubject(); - if ( $subject->getNamespace() == SMW_NS_PROPERTY ) { - $types = $semdata->getPropertyValues( new SMWDIProperty( '_TYPE' ) ); - } else { - $types = array(); - } - $result = self::makeExportDataForSubject( $subject, end( $types ) ); - foreach ( $semdata->getProperties() as $property ) { - self::addPropertyValues( $property, $semdata->getPropertyValues( $property ), $result, $subject ); - } - return $result; - } - - /** - * Make an SMWExpData object for the given page, and include the basic - * properties about this subject that are not directly represented by - * SMW property values. The optional parameter $typevalueforproperty - * can be used to pass a particular SMWTypesValue object that is used - * for determining the OWL type for property pages. - * - * @todo Take into account whether the wiki page belongs to a builtin property, and ensure URI alignment/type declaration in this case. - * - * @param $diWikiPage SMWDIWikiPage - * @param $typesvalueforproperty mixed either an SMWTypesValue or null - * @param $addStubData boolean to indicate if additional data should be added to make a stub entry for this page - * @return SMWExpData - */ - static public function makeExportDataForSubject( SMWDIWikiPage $diWikiPage, $typesvalueforproperty = null, $addStubData = false ) { - global $wgContLang; - $wikiPageExpElement = self::getDataItemExpElement( $diWikiPage ); - $result = new SMWExpData( $wikiPageExpElement ); - - if ( $diWikiPage->getSubobjectName() !== '' ) { - $result->addPropertyObjectValue( self::getSpecialNsResource( 'rdf', 'type' ), self::getSpecialNsResource( 'swivt', 'Subject' ) ); - $masterPage = new SMWDIWikiPage( $diWikiPage->getDBkey(), $diWikiPage->getNamespace(), $diWikiPage->getInterwiki() ); - $masterExpElement = self::getDataItemExpElement( $masterPage ); - $result->addPropertyObjectValue( self::getSpecialNsResource( 'swivt', 'masterPage' ), $masterExpElement ); - // Add a sortkey: subobjects do not get this during parsing (they are no pages), - // but it is needed to query for them (e.g., to get a defined order for result pages) - $subObjectLabel = $diWikiPage->getDBkey() . '#' . $diWikiPage->getSubobjectName(); - $sortkey = new SMWExpLiteral( str_replace( '_', ' ', $subObjectLabel ) ); - $result->addPropertyObjectValue( self::getSpecialPropertyResource( '_SKEY' ), $sortkey ); - } else { - $pageTitle = str_replace( '_', ' ', $diWikiPage->getDBkey() ); - if ( $diWikiPage->getNamespace() !== 0 ) { - $prefixedSubjectTitle = $wgContLang->getNsText( $diWikiPage->getNamespace()) . ":" . $pageTitle; - } else { - $prefixedSubjectTitle = $pageTitle; - } - $prefixedSubjectUrl = wfUrlencode( str_replace( ' ', '_', $prefixedSubjectTitle ) ); - - switch ( $diWikiPage->getNamespace() ) { - case NS_CATEGORY: case SMW_NS_CONCEPT: - $maintype_pe = self::getSpecialNsResource( 'owl', 'Class' ); - $label = $pageTitle; - break; - case SMW_NS_PROPERTY: - if ( $typesvalueforproperty == null ) { - $types = \SMW\StoreFactory::getStore()->getPropertyValues( $diWikiPage, new SMWDIProperty( '_TYPE' ) ); - $typesvalueforproperty = end( $types ); - } - $maintype_pe = self::getSpecialNsResource( 'owl', self::getOWLPropertyType( $typesvalueforproperty ) ); - $label = $pageTitle; - break; - default: - $label = $prefixedSubjectTitle; - $maintype_pe = self::getSpecialNsResource( 'swivt', 'Subject' ); - } - - $result->addPropertyObjectValue( self::getSpecialNsResource( 'rdf', 'type' ), $maintype_pe ); - - if ( !$wikiPageExpElement->isBlankNode() ) { - $ed = new SMWExpLiteral( $label ); - $result->addPropertyObjectValue( self::getSpecialNsResource( 'rdfs', 'label' ), $ed ); - $ed = new SMWExpResource( self::getNamespaceUri( 'wikiurl' ) . $prefixedSubjectUrl ); - $result->addPropertyObjectValue( self::getSpecialNsResource( 'swivt', 'page' ), $ed ); - $ed = new SMWExpResource( self::$m_exporturl . '/' . $prefixedSubjectUrl ); - $result->addPropertyObjectValue( self::getSpecialNsResource( 'rdfs', 'isDefinedBy' ), $ed ); - $ed = new SMWExpLiteral( strval( $diWikiPage->getNamespace() ), 'http://www.w3.org/2001/XMLSchema#integer' ); - $result->addPropertyObjectValue( self::getSpecialNsResource( 'swivt', 'wikiNamespace' ), $ed ); - if ( $addStubData ) { - // Add a default sort key; for pages that exist in the wiki, - // this is set during parsing - $defaultSortkey = new SMWExpLiteral( str_replace( '_', ' ', $diWikiPage->getDBkey() ) ); - $result->addPropertyObjectValue( self::getSpecialPropertyResource( '_SKEY' ), $defaultSortkey ); - } - } - } - - return $result; - } - - /** - * Extend a given SMWExpData element by adding export data for the - * specified property data itme. This method is called when - * constructing export data structures from SMWSemanticData objects. - * - * @param $property SMWDIProperty - * @param $dataItems array of SMWDataItem objects for the given property - * @param $data SMWExpData to add the data to - */ - static public function addPropertyValues( SMWDIProperty $property, array $dataItems, SMWExpData &$expData ) { - if ( $property->isUserDefined() ) { - $pe = self::getResourceElementForProperty( $property ); - $peHelper = self::getResourceElementForProperty( $property, true ); - - foreach ( $dataItems as $dataItem ) { - $ed = self::getDataItemExpElement( $dataItem ); - if ( !is_null( $ed ) ) { - $expData->addPropertyObjectValue( $pe, $ed ); - } - - $edHelper = self::getDataItemHelperExpElement( $dataItem ); - if ( !is_null( $edHelper ) ) { - $expData->addPropertyObjectValue( $peHelper, $edHelper ); - } - } - } else { // pre-defined property, only exported if known - $diSubject = $expData->getSubject()->getDataItem(); - // subject wikipage required for disambiguating special properties: - if ( is_null( $diSubject ) || - $diSubject->getDIType() != SMWDataItem::TYPE_WIKIPAGE ) { - return; - } - - $pe = self::getSpecialPropertyResource( $property->getKey(), $diSubject->getNamespace() ); - if ( is_null( $pe ) ) return; // unknown special property, not exported - // have helper property ready before entering the for loop, even if not needed: - $peHelper = self::getResourceElementForProperty( $property, true ); - - $filterNamespace = ( $property->getKey() == '_REDI' || $property->getKey() == '_URI' ); - - foreach ( $dataItems as $dataItem ) { - // Basic namespace filtering to ensure that types match for redirects etc. - /// TODO: currently no full check for avoiding OWL DL illegal redirects is done (OWL property type ignored) - if ( $filterNamespace && !( $dataItem instanceof SMWDIUri ) && - ( !( $dataItem instanceof SMWDIWikiPage ) || - ( $dataItem->getNamespace() != $diSubject->getNamespace() ) ) ) { - continue; - } - - $ed = self::getDataItemExpElement( $dataItem ); - - if ( !is_null( $ed ) ) { - if ( $property->getKey() == '_CONC' && - $ed->getSubject()->getUri() === '' ) { - // equivalent to anonymous class -> simplify description - foreach ( $ed->getProperties() as $subp ) { - if ( $subp->getUri() != self::getSpecialNsResource( 'rdf', 'type' )->getUri() ) { - foreach ( $ed->getValues( $subp ) as $subval ) { - $expData->addPropertyObjectValue( $subp, $subval ); - } - } - } - } elseif ( $property->getKey() == '_REDI' ) { - $expData->addPropertyObjectValue( $pe, $ed ); - $peUri = self::getSpecialPropertyResource( '_URI' ); - $expData->addPropertyObjectValue( $peUri, $ed ); - } elseif ( !$property->isUserDefined() && !self::hasSpecialPropertyResource( $property ) ) { - $expData->addPropertyObjectValue( - self::getResourceElementForWikiPage( $property->getDiWikiPage(), 'aux' ), - $ed - ); - } else { - $expData->addPropertyObjectValue( $pe, $ed ); - } - } - - $edHelper = self::getDataItemHelperExpElement( $dataItem ); - if ( !is_null( $edHelper ) ) { - $expData->addPropertyObjectValue( $peHelper, $edHelper ); - } - } - } - } - - /** - * Create an SMWExpElement for some internal resource, given by an - * SMWDIProperty object. - * This code is only applied to user-defined properties, since the - * code for special properties in - * SMWExporter::getSpecialPropertyResource() may require information - * about the namespace in which some special property is used. - * - * @param $diProperty SMWDIProperty - * @param $helperProperty boolean determines if an auxiliary property resource to store a helper value (see SMWExporter::getDataItemHelperExpElement()) should be generated - * @return SMWExpResource - */ - static public function getResourceElementForProperty( SMWDIProperty $diProperty, $helperProperty = false ) { - $diWikiPage = $diProperty->getDiWikiPage(); - if ( is_null( $diWikiPage ) ) { - throw new Exception( 'SMWExporter::getResourceElementForProperty() can only be used for non-inverse, user-defined properties.' ); - } elseif ( $helperProperty ) { - return self::getResourceElementForWikiPage( $diWikiPage, 'aux' ); - } else { - return self::getResourceElementForWikiPage( $diWikiPage ); - } - } - - /** - * Create an SMWExpElement for some internal resource, given by an - * SMWDIWikiPage object. This is the one place in the code where URIs - * of wiki pages and user-defined properties are determined. A modifier - * can be given to make variants of a URI, typically done for - * auxiliary properties. In this case, the URI is modiied by appending - * "-23$modifier" where "-23" is the URI encoding of "#" (a symbol not - * occuring in MW titles). - * - * @param $diWikiPage SMWDIWikiPage or SMWDIProperty - * @param $modifier string, using only Latin letters and numbers - * @return SMWExpResource - */ - static public function getResourceElementForWikiPage( SMWDIWikiPage $diWikiPage, $modifier = '' ) { - global $wgContLang; - - if ( $diWikiPage->getNamespace() == NS_MEDIA ) { // special handling for linking media files directly (object only) - $title = Title::makeTitle( $diWikiPage->getNamespace(), $diWikiPage->getDBkey() ) ; - $file = wfFindFile( $title ); - if ( $file !== false ) { - return new SMWExpResource( $file->getFullURL() ); - } // else: Medialink to non-existing file :-/ fall through - } - - if ( $diWikiPage->getSubobjectName() !== '' ) { - $modifier = $diWikiPage->getSubobjectName(); - } - - if ( $modifier === '' ) { - $importProperty = new SMWDIProperty( '_IMPO' ); - $importDis = \SMW\StoreFactory::getStore()->getPropertyValues( $diWikiPage, $importProperty ); - $importURI = ( count( $importDis ) > 0 ); - } else { - $importURI = false; - } - - if ( $importURI ) { - $importValue = DataValueFactory::getInstance()->newDataItemValue( current( $importDis ), $importProperty ); - $namespace = $importValue->getNS(); - $namespaceId = $importValue->getNSID(); - $localName = $importValue->getLocalName(); - } else { - $localName = ''; - - if ( $diWikiPage->getNamespace() == SMW_NS_PROPERTY ) { - $namespace = self::getNamespaceUri( 'property' ); - $namespaceId = 'property'; - $localName = self::encodeURI( rawurlencode( $diWikiPage->getDBkey() ) ); - } - - if ( ( $localName === '' ) || - ( in_array( $localName{0}, array( '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ) ) ) ) { - $namespace = self::getNamespaceUri( 'wiki' ); - $namespaceId = 'wiki'; - $localName = self::getEncodedPageName( $diWikiPage ); - } - - if ( $modifier !== '' ) { - $localName .= '-23' . $modifier; - } - } - - return new SMWExpNsResource( $localName, $namespace, $namespaceId, $diWikiPage ); - } - - /** - * Try to find an SMWDataItem that the given SMWExpElement might - * represent. Returns null if this attempt failed. - * - * @param SMWExpElement $expElement - * @return SMWDataItem or null - */ - static public function findDataItemForExpElement( SMWExpElement $expElement ) { - global $wgContLang; - - $dataItem = null; - if ( $expElement instanceof SMWExpResource ) { - $uri = $expElement->getUri(); - $wikiNamespace = self::getNamespaceUri( 'wiki' ); - - if ( strpos( $uri, $wikiNamespace ) === 0 ) { - $localName = substr( $uri, strlen( $wikiNamespace ) ); - $dbKey = rawurldecode( self::decodeURI( $localName ) ); - - $parts = explode( '#', $dbKey, 2 ); - if ( count( $parts ) == 2 ) { - $dbKey = $parts[0]; - $subobjectname = $parts[1]; - } else { - $subobjectname = ''; - } - - $parts = explode( ':', $dbKey, 2 ); - if ( count( $parts ) == 1 ) { - $dataItem = new SMWDIWikiPage( $dbKey, NS_MAIN, '', $subobjectname ); - } else { - // try the by far most common cases directly before using Title - $namespaceName = str_replace( '_', ' ', $parts[0] ); - $namespaceId = -1; - foreach ( array( SMW_NS_PROPERTY, NS_CATEGORY, NS_USER, NS_HELP ) as $nsId ) { - if ( $namespaceName == $wgContLang->getNsText( $nsId ) ) { - $namespaceId = $nsId; - break; - } - } - - if ( $namespaceId != -1 ) { - $dataItem = new SMWDIWikiPage( $parts[1], $namespaceId, '', $subobjectname ); - } else { - $title = Title::newFromDBkey( $dbKey ); - - if ( !is_null( $title ) ) { - $dataItem = new SMWDIWikiPage( $title->getDBkey(), $title->getNamespace(), $title->getInterwiki(), $subobjectname ); - } - } - } - } // else: not in wiki namespace -- TODO: this could be an imported URI - } else { - // TODO (currently not needed, but will be useful for displaying external SPARQL results) - } - return $dataItem; - } - - /** - * Determine what kind of OWL property some SMW property should be exported as. - * The input is an SMWTypesValue object, a typeid string, or empty (use default) - * @todo An improved mechanism for selecting property types here is needed. - */ - static public function getOWLPropertyType( $type = '' ) { - if ( $type instanceof SMWDIWikiPage ) { - $type = DataTypeRegistry::getInstance()->findTypeId( str_replace( '_', ' ', $type->getDBkey() ) ); - } elseif ( $type == false ) { - $type = ''; - } // else keep $type - switch ( $type ) { - case '_anu': return 'AnnotationProperty'; - case '': case '_wpg': case '_wpp': case '_wpc': case '_wpf': - case '_uri': case '_ema': case '_tel': case '_rec': case '__typ': - case '__red': case '__spf': case '__spu': - return 'ObjectProperty'; - default: return 'DatatypeProperty'; - } - } - - /** - * Get an SMWExpNsResource for a special property of SMW, or null if - * no resource is assigned to the given property key. The optional - * namespace is used to select the proper resource for properties that - * must take the type of the annotated object into account for some - * reason. - * - * @param $propertyKey string the Id of the special property - * @param $forNamespace integer the namespace of the page which has a value for this property - * @return SMWExpNsResource or null - */ - static public function getSpecialPropertyResource( $propertyKey, $forNamespace = NS_MAIN ) { - switch ( $propertyKey ) { - case '_INST': - return self::getSpecialNsResource( 'rdf', 'type' ); - case '_SUBC': - return self::getSpecialNsResource( 'rdfs', 'subClassOf' ); - case '_CONC': - return self::getSpecialNsResource( 'owl', 'equivalentClass' ); - case '_URI': - if ( $forNamespace == NS_CATEGORY || $forNamespace == SMW_NS_CONCEPT ) { - return self::getSpecialNsResource( 'owl', 'equivalentClass' ); - } elseif ( $forNamespace == SMW_NS_PROPERTY ) { - return self::getSpecialNsResource( 'owl', 'equivalentProperty' ); - } else { - return self::getSpecialNsResource( 'owl', 'sameAs' ); - } - case '_REDI': - return self::getSpecialNsResource( 'swivt', 'redirectsTo' ); - case '_SUBP': - if ( $forNamespace == SMW_NS_PROPERTY ) { - return self::getSpecialNsResource( 'rdfs', 'subPropertyOf' ); - } else { - return null; - } - case '_MDAT': - return self::getSpecialNsResource( 'swivt', 'wikiPageModificationDate' ); - case '_CDAT': - return self::getSpecialNsResource( 'swivt', 'wikiPageCreationDate' ); - case '_LEDT': - return self::getSpecialNsResource( 'swivt', 'wikiPageLastEditor' ); - case '_NEWP': - return self::getSpecialNsResource( 'swivt', 'wikiPageIsNew' ); - case '_SKEY': - return self::getSpecialNsResource( 'swivt', 'wikiPageSortKey' ); - case '_TYPE': - return self::getSpecialNsResource( 'swivt', 'type' ); - case '_IMPO': - return self::getSpecialNsResource( 'swivt', 'specialImportedFrom' ); - default: - return self::getSpecialNsResource( 'swivt', 'specialProperty' . $propertyKey ); - } - } - - - /** - * Create an SMWExpNsResource for some special element that belongs to - * a known vocabulary. An exception is generated when given parameters - * that do not fit any known vocabulary. - * - * @param $namespaceId string (e.g. "rdf") - * @param $localName string (e.g. "type") - * @return SMWExpNsResource - */ - static public function getSpecialNsResource( $namespaceId, $localName ) { - $namespace = self::getNamespaceUri( $namespaceId ); - if ( $namespace !== '' ) { - return new SMWExpNsResource( $localName, $namespace, $namespaceId ); - } else { - throw new InvalidArgumentException( "The vocabulary '$namespaceId' is not a known special vocabulary." ); - } - } - - /** - * This function escapes symbols that might be problematic in XML in a uniform - * and injective way. It is used to encode URIs. - */ - static public function encodeURI( $uri ) { - $uri = str_replace( '-', '-2D', $uri ); - // $uri = str_replace( '_', '-5F', $uri); //not necessary - $uri = str_replace( array( ':', '"', '#', '&', "'", '+', '!', '%' ), - array( '-3A', '-22', '-23', '-26', '-27', '-2B', '-21', '-' ), - $uri ); - return $uri; - } - - /** - * This function unescapes URIs generated with SMWExporter::encodeURI. This - * allows services that receive a URI to extract e.g. the according wiki page. - */ - static public function decodeURI( $uri ) { - $uri = str_replace( array( '-3A', '-22', '-23', '-26', '-27', '-2B', '-21', '-' ), - array( ':', '"', '#', '&', "'", '+', '!', '%' ), - $uri ); - $uri = str_replace( '%2D', '-', $uri ); - return $uri; - } - - /** - * This function expands standard XML entities used in some generated - * URIs. Given a string with such entities, it returns a string with - * all entities properly replaced. - * - * @note The function SMWExporter::getNamespaceUri() is often more - * suitable. This XML-specific method might become obsolete. - * - * @param $uri string of the URI to be expanded - * @return string of the expanded URI - */ - static public function expandURI( $uri ) { - self::initBaseURIs(); - $uri = str_replace( array( '&wiki;', '&wikiurl;', '&property;', '&owl;', '&rdf;', '&rdfs;', '&swivt;', '&export;' ), - array( self::$m_ent_wiki, self::$m_ent_wikiurl, self::$m_ent_property, 'http://www.w3.org/2002/07/owl#', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'http://www.w3.org/2000/01/rdf-schema#', 'http://semantic-mediawiki.org/swivt/1.0#', - self::$m_exporturl ), - $uri ); - return $uri; - } - - /** - * Get the URI of a standard namespace prefix used in SMW, or the empty - * string if the prefix is not known. - * - * @param $shortName string id (prefix) of the namespace - * @return string of the expanded URI - */ - static public function getNamespaceUri( $shortName ) { - self::initBaseURIs(); - switch ( $shortName ) { - case 'wiki': return self::$m_ent_wiki; - case 'wikiurl': return self::$m_ent_wikiurl; - case 'property': return self::$m_ent_property; - case 'export': return self::$m_exporturl; - case 'owl': return 'http://www.w3.org/2002/07/owl#'; - case 'rdf': return 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; - case 'rdfs': return 'http://www.w3.org/2000/01/rdf-schema#'; - case 'swivt': return 'http://semantic-mediawiki.org/swivt/1.0#'; - case 'xsd': return 'http://www.w3.org/2001/XMLSchema#'; - default: return ''; - } - } - - /** - * Create an SMWExpData container that encodes the ontology header for an - * SMW exported OWL file. - * - * @param string $ontologyuri specifying the URI of the ontology, possibly - * empty - */ - static public function getOntologyExpData( $ontologyuri ) { - $data = new SMWExpData( new SMWExpResource( $ontologyuri ) ); - $ed = self::getSpecialNsResource( 'owl', 'Ontology' ); - $data->addPropertyObjectValue( self::getSpecialNsResource( 'rdf', 'type' ), $ed ); - $ed = new SMWExpLiteral( date( DATE_W3C ), 'http://www.w3.org/2001/XMLSchema#dateTime' ); - $data->addPropertyObjectValue( self::getSpecialNsResource( 'swivt', 'creationDate' ), $ed ); - $ed = new SMWExpResource( 'http://semantic-mediawiki.org/swivt/1.0' ); - $data->addPropertyObjectValue( self::getSpecialNsResource( 'owl', 'imports' ), $ed ); - return $data; - } - - /** - * Create an SWMExpElement that encodes the data of the given - * dataitem object. This method is meant to be used when exporting a - * dataitem as a subject or object. To get the URI of a property, use - * SMWExporter::getResourceElementForProperty() or - * SMWExporter::getSpecialPropertyResource(). - * - * @param $dataItem SMWDataItem - * @return SMWExpElement - */ - static public function getDataItemExpElement( SMWDataItem $dataItem ) { - switch ( $dataItem->getDIType() ) { - case SMWDataItem::TYPE_NUMBER: - $lit = new SMWExpLiteral( strval( $dataItem->getNumber() ), 'http://www.w3.org/2001/XMLSchema#double', $dataItem ); - return $lit; - case SMWDataItem::TYPE_BLOB: - $lit = new SMWExpLiteral( smwfHTMLtoUTF8( $dataItem->getString() ), 'http://www.w3.org/2001/XMLSchema#string', $dataItem ); - return $lit; - case SMWDataItem::TYPE_BOOLEAN: - $xsdvalue = $dataItem->getBoolean() ? 'true' : 'false'; - $lit = new SMWExpLiteral( $xsdvalue, 'http://www.w3.org/2001/XMLSchema#boolean', $dataItem ); - return $lit; - case SMWDataItem::TYPE_URI: - $res = new SMWExpResource( $dataItem->getURI(), $dataItem ); - return $res; - case SMWDataItem::TYPE_TIME: - $gregorianTime = $dataItem->getForCalendarModel( SMWDITime::CM_GREGORIAN ); - if ( $gregorianTime->getYear() > 0 ) { - $xsdvalue = str_pad( $gregorianTime->getYear(), 4, "0", STR_PAD_LEFT ); - } else { - $xsdvalue = '-' . str_pad( 1 - $gregorianTime->getYear(), 4, "0", STR_PAD_LEFT ); - } - $xsdtype = 'http://www.w3.org/2001/XMLSchema#gYear'; - if ( $gregorianTime->getPrecision() >= SMWDITime::PREC_YM ) { - $xsdtype = 'http://www.w3.org/2001/XMLSchema#gYearMonth'; - $xsdvalue .= '-' . str_pad( $gregorianTime->getMonth(), 2, "0", STR_PAD_LEFT ); - if ( $gregorianTime->getPrecision() >= SMWDITime::PREC_YMD ) { - $xsdtype = 'http://www.w3.org/2001/XMLSchema#date'; - $xsdvalue .= '-' . str_pad( $gregorianTime->getDay(), 2, "0", STR_PAD_LEFT ); - if ( $gregorianTime->getPrecision() == SMWDITime::PREC_YMDT ) { - $xsdtype = 'http://www.w3.org/2001/XMLSchema#dateTime'; - $xsdvalue .= 'T' . - sprintf( "%02d", $gregorianTime->getHour() ) . ':' . - sprintf( "%02d", $gregorianTime->getMinute()) . ':' . - sprintf( "%02d", $gregorianTime->getSecond() ); - } - } - } - $xsdvalue .= 'Z'; - $lit = new SMWExpLiteral( $xsdvalue, $xsdtype, $gregorianTime ); - return $lit; - case SMWDataItem::TYPE_GEO: - /// TODO - return null; - case SMWDataItem::TYPE_CONTAINER: - return self::makeExportData( $dataItem->getSemanticData() ); - case SMWDataItem::TYPE_WIKIPAGE: - return self::getResourceElementForWikiPage( $dataItem ); - case SMWDataItem::TYPE_CONCEPT: - /// TODO - return null; - case SMWDataItem::TYPE_PROPERTY: - return self::getResourceElementForProperty( $dataItem ); - } - } - - /** - * Create an SWMExpElement that encodes auxiliary data for representing - * values of the specified dataitem object in a simplified fashion. - * This is done for types of dataitems that are not supported very well - * in current systems, or that do not match a standard datatype in RDF. - * For example, time points (DITime) are encoded as numbers. The number - * can replace the actual time for all query and ordering purposes (the - * order in either case is linear and maps to the real number line). - * Only data retrieval should better use the real values to avoid that - * rounding errors lead to unfaithful recovery of data. Note that the - * helper values do not maintain any association with their original - * values -- they are a fully redundant alternative representation, not - * an additional piece of information for the main values. Even if - * decoding is difficult, they must be in one-to-one correspondence to - * the original value. - * - * For dataitems that do not have such a simplification, the method - * returns null. - * - * @note If a helper element is used, then it must be the same as - * getDataItemHelperExpElement( $dataItem->getSortKeyDataItem() ). - * Query conditions like ">" use sortkeys for values, and helper - * elements are always preferred in query answering. - * - * @param $dataItem SMWDataItem - * @return SMWExpElement or null - */ - static public function getDataItemHelperExpElement( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_TIME ) { - $lit = new SMWExpLiteral( (string)$dataItem->getSortKey(), 'http://www.w3.org/2001/XMLSchema#double', $dataItem ); - return $lit; - } else { - return null; - } - } - - /** - * Check whether the values of a given type of dataitem have helper - * values in the sense of SMWExporter::getDataItemHelperExpElement(). - * - * @param DIProperty $property - * - * @return boolean - */ - static public function hasHelperExpElement( DIProperty $property ) { - return ( $property->findPropertyTypeID() === '_dat' ) || ( !$property->isUserDefined() && !self::hasSpecialPropertyResource( $property ) ); - } - - static protected function hasSpecialPropertyResource( DIProperty $property ) { - return $property->getKey() === '_SKEY' || - $property->getKey() === '_INST' || - $property->getKey() === '_MDAT' || - $property->getKey() === '_SUBC' || - $property->getKey() === '_SUBP' || - $property->getKey() === '_TYPE' || - $property->getKey() === '_IMPO' || - $property->getKey() === '_URI'; - } - - /** - * @since 2.0 - * - * @param DIWikiPage $diWikiPage - * @return string - */ - static public function getEncodedPageName( DIWikiPage $diWikiPage ) { - - $localName = ''; - - if ( $diWikiPage->getNamespace() !== 0 ) { - $localName = str_replace( ' ', '_', $GLOBALS['wgContLang']->getNSText( $diWikiPage->getNamespace() ) ) . ':' . $diWikiPage->getDBkey(); - } else { - $localName = $diWikiPage->getDBkey(); - } - - return self::encodeURI( wfUrlencode( $localName ) ); - } - -} diff --git a/SemanticMediaWiki/includes/export/SMW_Serializer.php b/SemanticMediaWiki/includes/export/SMW_Serializer.php deleted file mode 100644 index fdf6bde6..00000000 --- a/SemanticMediaWiki/includes/export/SMW_Serializer.php +++ /dev/null @@ -1,318 +0,0 @@ -<?php - -/** - * File holding the SMWSerializer class that provides basic functions for - * serialising data in OWL and RDF syntaxes. - * - * @file SMW_Serializer.php - * @ingroup SMW - * - * @author Markus Krötzsch - */ - -define( 'SMW_SERIALIZER_DECL_CLASS', 1 ); -define( 'SMW_SERIALIZER_DECL_OPROP', 2 ); -define( 'SMW_SERIALIZER_DECL_APROP', 4 ); - -/** - * Abstract class for serializing exported data (encoded as SMWExpData object) - * in a concrete syntactic format such as Turtle or RDF/XML. The serializer - * adds object serialisations to an internal string that can be retrieved for - * pushing it to an output. This abstract class does not define this string as - * implementations may want to use their own scheme (e.g. using two buffers as - * in the case of SMWRDFXMLSerializer). The function flushContent() returns the - * string serialized so far so as to enable incremental serialization. - * - * RDF and OWL have two types of dependencies that are managed by this class: - * namespaces (and similar abbreviation schemes) and element declarations. - * The former need to be defined before being used, while the latter can occur - * at some later point in the serialization. Declarations are relevant to the - * OWL data model, being one of Class, DatatypeProperty, and ObjectProperty - * (only the latter two are mutually exclusive). This class determines the - * required declaration from the context in which an element is used. - * - * @ingroup SMW - */ -abstract class SMWSerializer { - /** - * The current working string is obtained by concatenating the strings - * $pre_ns_buffer and $post_ns_buffer. The split between the two is such - * that one can append additional namespace declarations to $pre_ns_buffer - * so that they affect all current elements. The buffers are flushed during - * output in order to achieve "streaming" RDF export for larger files. - * @var string - */ - protected $pre_ns_buffer; - /** - * See documentation for $pre_ns_buffer. - * @var string - */ - protected $post_ns_buffer; - /** - * Array for recording required declarations; format: - * resourcename => decl-flag, where decl-flag is a sum of flags - * SMW_SERIALIZER_DECL_CLASS, SMW_SERIALIZER_DECL_OPROP, - * SMW_SERIALIZER_DECL_APROP. - * @var array of integer - */ - protected $decl_todo; - /** - * Array for recording previous declarations; format: - * resourcename => decl-flag, where decl-flag is a sum of flags - * SMW_SERIALIZER_DECL_CLASS, SMW_SERIALIZER_DECL_OPROP, - * SMW_SERIALIZER_DECL_APROP. - * @var array of integer - */ - protected $decl_done; - /** - * Array of additional namespaces (abbreviation => URI), flushed on - * closing the current namespace tag. Since we export in a streamed - * way, it is not always possible to embed additional namespaces into - * a syntactic block (e.g. an RDF/XML tag) which might have been sent to - * the client already. But we wait with printing the current block so that - * extra namespaces from this array can still be printed (note that one - * never know which extra namespaces you encounter during export). - * @var array of string - */ - protected $extra_namespaces; - /** - * Array of namespaces that have been declared globally already. Contains - * entries of format 'namespace abbreviation' => true, assuming that the - * same abbreviation always refers to the same URI. - * @var array of string - */ - protected $global_namespaces; - - /** - * Constructor. - */ - public function __construct() { - $this->clear(); - } - - /** - * Clear internal states to start a new serialization. - */ - public function clear() { - $this->pre_ns_buffer = ''; - $this->post_ns_buffer = ''; - $this->decl_todo = array(); - $this->decl_done = array(); - $this->global_namespaces = array(); - $this->extra_namespaces = array(); - } - - /** - * Start a new serialization, resetting all internal data and serializing - * necessary header elements. - */ - public function startSerialization() { - $this->clear(); - $this->serializeHeader(); - } - - /** - * Complete the serialization so that calling flushContent() will return - * the final part of the output, leading to a complete serialization with - * all necessary declarations. No further serialization functions must be - * called after this. - */ - public function finishSerialization() { - $this->serializeDeclarations(); - $this->serializeFooter(); - } - - /** - * Serialize the header (i.e. write it to the internal buffer). May - * include standard syntax to start output but also declare some common - * namespaces globally. - */ - abstract protected function serializeHeader(); - - /** - * Serialise the footer (i.e. write it to the internal buffer). - */ - abstract protected function serializeFooter(); - - /** - * Serialize any declarations that have been found to be missing while - * serializing other elements. - */ - public function serializeDeclarations() { - foreach ( $this->decl_todo as $name => $flag ) { - $types = array(); - if ( $flag & SMW_SERIALIZER_DECL_CLASS ) $types[] = 'owl:Class'; - if ( $flag & SMW_SERIALIZER_DECL_OPROP ) $types[] = 'owl:ObjectProperty'; - if ( $flag & SMW_SERIALIZER_DECL_APROP ) $types[] = 'owl:DatatypeProperty'; - foreach ( $types as $typename ) { - $this->serializeDeclaration( $name, $typename ); - } - $curdone = array_key_exists( $name, $this->decl_done ) ? $this->decl_done[$name] : 0; - $this->decl_done[$name] = $curdone | $flag; - } - $this->decl_todo = array(); // reset all - } - - /** - * Serialize a single declaration for the given $uri (expanded) and type - * (given as a QName). - * @param $uri string URI of the thing to declare - * @param $typename string one of owl:Class, owl:ObjectProperty, and - * owl:datatypeProperty - */ - abstract public function serializeDeclaration( $uri, $typename ); - - /** - * Serialise the given SMWExpData object. The method must not assume that - * the exported data refers to wiki pages or other SMW data, and it must - * ensure that all required auxiliary declarations for obtaining proper OWL - * are included in any case (this can be done using requireDeclaration()). - * - * @param $data SMWExpData containing the data to be serialised. - */ - abstract public function serializeExpData( SMWExpData $data ); - - /** - * Get the string that has been serialized so far. This function also - * resets the internal buffers for serilized strings and namespaces - * (what is flushed is gone). - */ - public function flushContent() { - if ( ( $this->pre_ns_buffer === '' ) && ( $this->post_ns_buffer === '' ) ) return ''; - $this->serializeNamespaces(); - $result = $this->pre_ns_buffer . $this->post_ns_buffer; - $this->pre_ns_buffer = ''; - $this->post_ns_buffer = ''; - return $result; - } - - /** - * Include collected namespace information into the serialization. - */ - protected function serializeNamespaces() { - foreach ( $this->extra_namespaces as $nsshort => $nsuri ) { - $this->serializeNamespace( $nsshort, $nsuri ); - } - $this->extra_namespaces = array(); - } - - /** - * Serialize a single namespace. - * Namespaces that were serialized in such a way that they remain - * available for all following output should be added to - * $global_namespaces. - * @param $shortname string abbreviation/prefix to declare - * @param $uri string URI prefix that the namespace encodes - */ - abstract protected function serializeNamespace( $shortname, $uri ); - - /** - * Require an additional namespace to be declared in the serialization. - * The function checks whether the required namespace is available globally - * and add it to the list of required namespaces otherwise. - */ - protected function requireNamespace( $nsshort, $nsuri ) { - if ( !array_key_exists( $nsshort, $this->global_namespaces ) ) { - $this->extra_namespaces[$nsshort] = $nsuri; - } - } - - /** - * State that a certain declaration is needed. The method checks if the - * declaration is already available, and records a todo otherwise. - */ - protected function requireDeclaration( SMWExpResource $resource, $decltype ) { - // Do not declare predefined OWL language constructs: - if ( $resource instanceof SMWExpNsResource ) { - $nsId = $resource->getNamespaceId(); - if ( ( $nsId == 'owl' ) || ( $nsId == 'rdf' ) || ( $nsId == 'rdfs' ) ) { - return; - } - } - // Do not declare blank nodes: - if ( $resource->isBlankNode() ) return; - - $name = $resource->getUri(); - if ( array_key_exists( $name, $this->decl_done ) && ( $this->decl_done[$name] & $decltype ) ) { - return; - } - if ( !array_key_exists( $name, $this->decl_todo ) ) { - $this->decl_todo[$name] = $decltype; - } else { - $this->decl_todo[$name] = $this->decl_todo[$name] | $decltype; - } - } - - /** - * Update the declaration "todo" and "done" lists for the case that the - * given data has been serialized with the type information it provides. - * - * @param $expData specifying the type data upon which declarations are based - */ - protected function recordDeclarationTypes( SMWExpData $expData ) { - foreach ( $expData->getSpecialValues( 'rdf', 'type') as $typeresource ) { - if ( $typeresource instanceof SMWExpNsResource ) { - switch ( $typeresource->getQName() ) { - case 'owl:Class': $typeflag = SMW_SERIALIZER_DECL_CLASS; break; - case 'owl:ObjectProperty': $typeflag = SMW_SERIALIZER_DECL_OPROP; break; - case 'owl:DatatypeProperty': $typeflag = SMW_SERIALIZER_DECL_APROP; break; - default: $typeflag = 0; - } - if ( $typeflag != 0 ) { - $this->declarationDone( $expData->getSubject(), $typeflag ); - } - } - } - } - - /** - * Update the declaration "todo" and "done" lists to reflect the fact that - * the given element has been declared to has the given type. - * - * @param $element SMWExpResource specifying the element to update - * @param $typeflag integer specifying the type (e.g. SMW_SERIALIZER_DECL_CLASS) - */ - protected function declarationDone( SMWExpResource $element, $typeflag ) { - $name = $element->getUri(); - $curdone = array_key_exists( $name, $this->decl_done ) ? $this->decl_done[$name] : 0; - $this->decl_done[$name] = $curdone | $typeflag; - if ( array_key_exists( $name, $this->decl_todo ) ) { - $this->decl_todo[$name] = $this->decl_todo[$name] & ( ~$typeflag ); - if ( $this->decl_todo[$name] == 0 ) { - unset( $this->decl_todo[$name] ); - } - } - } - - /** - * Check if the given property is one of the special properties of the OWL - * language that require their values to be classes or RDF lists of - * classes. In these cases, it is necessary to declare this in the exported - * data. - * - * @note The list of properties checked here is not complete for the OWL - * language but covers what is used in SMW. - * @note OWL 2 allows URIs to refer to both classes and individual elements - * in different contexts. We only need declarations for classes that are - * used as such, hence it is enough to check the property. Moreover, we do - * not use OWL Datatypes in SMW, so rdf:type, rdfs:domain, etc. always - * refer to classes. - * @param SMWExpNsResource $property - */ - protected function isOWLClassTypeProperty( SMWExpNsResource $property ) { - $locname = $property->getLocalName(); - if ( $property->getNamespaceID() == 'rdf' ) { - return ( $locname == 'type' ); - } elseif ( $property->getNamespaceID() == 'owl' ) { - return ( $locname == 'intersectionOf' ) || ( $locname == 'unionOf' ) || - ( $locname == 'equivalentClass' ) || - ( $locname == 'complementOf' ) || ( $locname == 'someValuesFrom' ) || - ( $locname == 'allValuesFrom' ) || ( $locname == 'onClass' ); - } elseif ( $property->getNamespaceID() == 'rdfs' ) { - return ( $locname == 'subClassOf' ) || ( $locname == 'range' ) || ( $locname == 'domain' ); - } else { - return false; - } - } - -} diff --git a/SemanticMediaWiki/includes/export/SMW_Serializer_RDFXML.php b/SemanticMediaWiki/includes/export/SMW_Serializer_RDFXML.php deleted file mode 100644 index a8082bf5..00000000 --- a/SemanticMediaWiki/includes/export/SMW_Serializer_RDFXML.php +++ /dev/null @@ -1,267 +0,0 @@ -<?php - -/** - * File holding the SMWRDFXMLSerializer class that provides basic functions for - * serialising OWL data in RDF/XML syntax. - * - * @file SMW_Serializer.php - * @ingroup SMW - * - * @author Markus Krötzsch - */ - -/** - * Class for serializing exported data (encoded as SMWExpData object) in - * RDF/XML. - * - * @ingroup SMW - */ -class SMWRDFXMLSerializer extends SMWSerializer{ - /** - * True if the $pre_ns_buffer contains the beginning of a namespace - * declaration block to which further declarations for the current - * context can be appended. - */ - protected $namespace_block_started; - /** - * True if the namespaces that are added at the current serialization stage - * become global, i.e. remain available for all later contexts. This is the - * case in RDF/XML only as long as the header has not been streamed to the - * client (reflected herein by calling flushContent()). Later, namespaces - * can only be added locally to individual elements, thus requiring them to - * be re-added multiple times if used in many elements. - */ - protected $namespaces_are_global; - - public function clear() { - parent::clear(); - $this->namespaces_are_global = false; - $this->namespace_block_started = false; - } - - protected function serializeHeader() { - $this->namespaces_are_global = true; - $this->namespace_block_started = true; - $this->pre_ns_buffer = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" . - "<!DOCTYPE rdf:RDF[\n" . - "\t<!ENTITY rdf " . $this->makeValueEntityString( SMWExporter::expandURI( '&rdf;' ) ) . ">\n" . - "\t<!ENTITY rdfs " . $this->makeValueEntityString( SMWExporter::expandURI( '&rdfs;' ) ) . ">\n" . - "\t<!ENTITY owl " . $this->makeValueEntityString( SMWExporter::expandURI( '&owl;' ) ) . ">\n" . - "\t<!ENTITY swivt " . $this->makeValueEntityString( SMWExporter::expandURI( '&swivt;' ) ) . ">\n" . - // A note on "wiki": this namespace is crucial as a fallback when it would be illegal to start e.g. with a number. - // In this case, one can always use wiki:... followed by "_" and possibly some namespace, since _ is legal as a first character. - "\t<!ENTITY wiki " . $this->makeValueEntityString( SMWExporter::expandURI( '&wiki;' ) ) . ">\n" . - "\t<!ENTITY property " . $this->makeValueEntityString( SMWExporter::expandURI( '&property;' ) ) . ">\n" . - "\t<!ENTITY wikiurl " . $this->makeValueEntityString( SMWExporter::expandURI( '&wikiurl;' ) ) . ">\n" . - "]>\n\n" . - "<rdf:RDF\n" . - "\txmlns:rdf=\"&rdf;\"\n" . - "\txmlns:rdfs=\"&rdfs;\"\n" . - "\txmlns:owl =\"&owl;\"\n" . - "\txmlns:swivt=\"&swivt;\"\n" . - "\txmlns:wiki=\"&wiki;\"\n" . - "\txmlns:property=\"&property;\""; - $this->global_namespaces = array( 'rdf' => true, 'rdfs' => true, 'owl' => true, 'swivt' => true, 'wiki' => true, 'property' => true ); - $this->post_ns_buffer .= ">\n\n"; - } - - protected function serializeFooter() { - $this->post_ns_buffer .= "\t<!-- Created by Semantic MediaWiki, http://semantic-mediawiki.org/ -->\n"; - $this->post_ns_buffer .= '</rdf:RDF>'; - } - - public function serializeDeclaration( $uri, $typename ) { - $this->post_ns_buffer .= "\t<$typename rdf:about=\"$uri\" />\n"; - } - - public function serializeExpData( SMWExpData $expData ) { - $this->serializeNestedExpData( $expData, '' ); - $this->serializeNamespaces(); - if ( !$this->namespaces_are_global ) { - $this->pre_ns_buffer .= $this->post_ns_buffer; - $this->post_ns_buffer = ''; - $this->namespace_block_started = false; - } - } - - public function flushContent() { - $result = parent::flushContent(); - $this->namespaces_are_global = false; // must not be done before calling the parent method (which may declare namespaces) - $this->namespace_block_started = false; - return $result; - } - - protected function serializeNamespace( $shortname, $uri ) { - if ( $this->namespaces_are_global ) { - $this->global_namespaces[$shortname] = true; - $this->pre_ns_buffer .= "\n\t"; - } else { - $this->pre_ns_buffer .= ' '; - } - $this->pre_ns_buffer .= "xmlns:$shortname=\"$uri\""; - } - - /** - * Serialize the given SMWExpData object, possibly recursively with - * increased indentation. - * - * @param $expData SMWExpData containing the data to be serialised. - * @param $indent string specifying a prefix for indentation (usually a sequence of tabs) - */ - protected function serializeNestedExpData( SMWExpData $expData, $indent ) { - $this->recordDeclarationTypes( $expData ); - - $type = $expData->extractMainType()->getQName(); - if ( !$this->namespace_block_started ) { // start new ns block - $this->pre_ns_buffer .= "\t$indent<$type"; - $this->namespace_block_started = true; - } else { // continue running block - $this->post_ns_buffer .= "\t$indent<$type"; - } - - if ( ( $expData->getSubject() instanceof SMWExpResource ) && - !$expData->getSubject()->isBlankNode() ) { - $this->post_ns_buffer .= ' rdf:about="' . $expData->getSubject()->getUri() . '"'; - } // else: blank node, no "rdf:about" - - if ( count( $expData->getProperties() ) == 0 ) { // nothing else to export - $this->post_ns_buffer .= " />\n"; - } else { // process data - $this->post_ns_buffer .= ">\n"; - - foreach ( $expData->getProperties() as $property ) { - $prop_decl_queued = false; - $isClassTypeProp = $this->isOWLClassTypeProperty( $property ); - - foreach ( $expData->getValues( $property ) as $valueElement ) { - $this->requireNamespace( $property->getNamespaceID(), $property->getNamespace() ); - - if ( $valueElement instanceof SMWExpLiteral ) { - $prop_decl_type = SMW_SERIALIZER_DECL_APROP; - $this->serializeExpLiteral( $property, $valueElement, "\t\t$indent" ); - } elseif ( $valueElement instanceof SMWExpResource ) { - $prop_decl_type = SMW_SERIALIZER_DECL_OPROP; - $this->serializeExpResource( $property, $valueElement, "\t\t$indent", $isClassTypeProp ); - } elseif ( $valueElement instanceof SMWExpData ) { - $prop_decl_type = SMW_SERIALIZER_DECL_OPROP; - - $collection = $valueElement->getCollection(); - if ( $collection !== false ) { // RDF-style collection (list) - $this->serializeExpCollection( $property, $collection, "\t\t$indent", $isClassTypeProp ); - } elseif ( count( $valueElement->getProperties() ) > 0 ) { // resource with data - $this->post_ns_buffer .= "\t\t$indent<" . $property->getQName() . ">\n"; - $this->serializeNestedExpData( $valueElement, "\t\t$indent" ); - $this->post_ns_buffer .= "\t\t$indent</" . $property->getQName() . ">\n"; - } else { // resource without data - $this->serializeExpResource( $property, $valueElement->getSubject(), "\t\t$indent", $isClassTypeProp ); - } - } // else: no other types of export elements - - if ( !$prop_decl_queued ) { - $this->requireDeclaration( $property, $prop_decl_type ); - $prop_decl_queued = true; - } - } - } - $this->post_ns_buffer .= "\t$indent</" . $type . ">\n"; - } - } - - /** - * Add to the output a serialization of a property assignment where an - * SMWExpLiteral is the object. It is assumed that a suitable subject - * block has already been openend. - * - * @param $expResourceProperty SMWExpNsResource the property to use - * @param $expLiteral SMWExpLiteral the data value to use - * @param $indent string specifying a prefix for indentation (usually a sequence of tabs) - */ - protected function serializeExpLiteral( SMWExpNsResource $expResourceProperty, SMWExpLiteral $expLiteral, $indent ) { - $this->post_ns_buffer .= $indent . '<' . $expResourceProperty->getQName(); - if ( $expLiteral->getDatatype() !== '' ) { - $this->post_ns_buffer .= ' rdf:datatype="' . $expLiteral->getDatatype() . '"'; - } - $this->post_ns_buffer .= '>' . $this->makeAttributeValueString( $expLiteral->getLexicalForm() ) . - '</' . $expResourceProperty->getQName() . ">\n"; - } - - /** - * Add to the output a serialization of a property assignment where an - * SMWExpResource is the object. It is assumed that a suitable subject - * block has already been openend. - * - * @param $expResourceProperty SMWExpNsResource the property to use - * @param $expResource SMWExpResource the data value to use - * @param $indent string specifying a prefix for indentation (usually a sequence of tabs) - * @param $isClassTypeProp boolean whether the resource must be declared as a class - */ - protected function serializeExpResource( SMWExpNsResource $expResourceProperty, SMWExpResource $expResource, $indent, $isClassTypeProp ) { - $this->post_ns_buffer .= $indent . '<' . $expResourceProperty->getQName(); - if ( !$expResource->isBlankNode() ) { - if ( ( $expResource instanceof SMWExpNsResource ) && ( $expResource->getNamespaceID() == 'wiki' ) ) { - // very common case, reduce bandwidth - $this->post_ns_buffer .= ' rdf:resource="&wiki;' . $expResource->getLocalName() . '"'; - } else { - $uriValue = $this->makeAttributeValueString( $expResource->getUri() ); - $this->post_ns_buffer .= ' rdf:resource="' . $uriValue . '"'; - } - } - $this->post_ns_buffer .= "/>\n"; - if ( $isClassTypeProp ) { - $this->requireDeclaration( $expResource, SMW_SERIALIZER_DECL_CLASS ); - } - } - - /** - * Add a serialization of the given SMWExpResource to the output, - * assuming that an opening property tag is alerady there. - * - * @param $expResourceProperty SMWExpNsResource the property to use - * @param $expResource array of (SMWExpResource or SMWExpData) - * @param $indent string specifying a prefix for indentation (usually a sequence of tabs) - * @param $isClassTypeProp boolean whether the resource must be declared as a class - * - * @bug The $isClassTypeProp parameter is not properly taken into account. - * @bug Individual resources are not serialised properly. - */ - protected function serializeExpCollection( SMWExpNsResource $expResourceProperty, array $collection, $indent, $isClassTypeProp ) { - $this->post_ns_buffer .= $indent . '<' . $expResourceProperty->getQName() . " rdf:parseType=\"Collection\">\n"; - foreach ( $collection as $expElement ) { - if ( $expElement instanceof SMWExpData ) { - $this->serializeNestedExpData( $expElement, $indent ); - } else { - // FIXME: the below is not the right thing to do here - //$this->serializeExpResource( $expResourceProperty, $expElement, $indent ); - } - if ( $isClassTypeProp ) { - // FIXME: $expResource is undefined - //$this->requireDeclaration( $expResource, SMW_SERIALIZER_DECL_CLASS ); - } - } - $this->post_ns_buffer .= "$indent</" . $expResourceProperty->getQName() . ">\n"; - } - - /** - * Escape a string in the special form that is required for values in - * DTD entity declarations in XML. Namely, this require the percent sign - * to be replaced. - * - * @param $string string to be escaped - * @return string - */ - protected function makeValueEntityString( $string ) { - return "'" . str_replace( '%','%',$string ) . "'"; - } - - /** - * Escape a string as required for using it in XML attribute values. - * - * @param $string string to be escaped - * @return string - */ - protected function makeAttributeValueString( $string ) { - return str_replace( array( '&', '>', '<' ), array( '&', '>', '<' ), $string ); - } - -} diff --git a/SemanticMediaWiki/includes/export/SMW_Serializer_Turtle.php b/SemanticMediaWiki/includes/export/SMW_Serializer_Turtle.php deleted file mode 100644 index ba0636f7..00000000 --- a/SemanticMediaWiki/includes/export/SMW_Serializer_Turtle.php +++ /dev/null @@ -1,248 +0,0 @@ -<?php - -/** - * File holding the SMWTurtleSerializer class that provides basic functions for - * serialising OWL data in Turtle syntax. - * - * @file SMW_Serializer.php - * @ingroup SMW - * - * @author Markus Krötzsch - */ - -/** - * Class for serializing exported data (encoded as SMWExpData object) in - * Turtle syntax. - * - * @ingroup SMW - */ -class SMWTurtleSerializer extends SMWSerializer{ - /** - * Array of non-trivial sub-SMWExpData elements that cannot be nested while - * serializing some SMWExpData. The elements of the array are serialized - * later during the same serialization step (so this is not like another - * queue for declarations or the like; it just unfolds an SMWExpData - * object). - * - * @var array of SMWExpData - */ - protected $subexpdata; - - /** - * If true, do not serialize namespace declarations and record them in - * $sparql_namespaces instead for later retrieval. - * @var boolean - */ - protected $sparqlmode; - - /** - * Array of retrieved namespaces (abbreviation => URI) for later use. - * @var array of string - */ - protected $sparql_namespaces; - - public function __construct( $sparqlMode = false ) { - parent::__construct(); - $this->sparqlmode = $sparqlMode; - } - - public function clear() { - parent::clear(); - $this->sparql_namespaces = array(); - } - - /** - * Get an array of namespace prefixes used in SPARQL mode. - * Namespaces are not serialized among triples in SPARQL mode but are - * collected separately. This method returns the prefixes and empties - * the collected list afterwards. - * - * @return array shortName => namespace URI - */ - public function flushSparqlPrefixes() { - $result = $this->sparql_namespaces; - $this->sparql_namespaces = array(); - return $result; - } - - protected function serializeHeader() { - if ( $this->sparqlmode ) { - $this->pre_ns_buffer = ''; - $this->sparql_namespaces = array( - "rdf" => SMWExporter::expandURI( '&rdf;' ), - "rdfs" => SMWExporter::expandURI( '&rdfs;' ), - "owl" => SMWExporter::expandURI( '&owl;' ), - "swivt" => SMWExporter::expandURI( '&swivt;' ), - "wiki" => SMWExporter::expandURI( '&wiki;' ), - "property" => SMWExporter::expandURI( '&property;' ), - "xsd" => "http://www.w3.org/2001/XMLSchema#" , - "wikiurl" => SMWExporter::expandURI( '&wikiurl;' ) - ); - } else { - $this->pre_ns_buffer = - "@prefix rdf: <" . SMWExporter::expandURI( '&rdf;' ) . "> .\n" . - "@prefix rdfs: <" . SMWExporter::expandURI( '&rdfs;' ) . "> .\n" . - "@prefix owl: <" . SMWExporter::expandURI( '&owl;' ) . "> .\n" . - "@prefix swivt: <" . SMWExporter::expandURI( '&swivt;' ) . "> .\n" . - // A note on "wiki": this namespace is crucial as a fallback when it would be illegal to start e.g. with a number. - // In this case, one can always use wiki:... followed by "_" and possibly some namespace, since _ is legal as a first character. - "@prefix wiki: <" . SMWExporter::expandURI( '&wiki;' ) . "> .\n" . - "@prefix property: <" . SMWExporter::expandURI( '&property;' ) . "> .\n" . - "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" . // note that this XSD URI is hardcoded below (its unlikely to change, of course) - "@prefix wikiurl: <" . SMWExporter::expandURI( '&wikiurl;' ) . "> .\n"; - } - $this->global_namespaces = array( 'rdf' => true, 'rdfs' => true, 'owl' => true, 'swivt' => true, 'wiki' => true, 'property' => true ); - $this->post_ns_buffer = "\n"; - } - - protected function serializeFooter() { - if ( !$this->sparqlmode ) { - $this->post_ns_buffer .= "\n# Created by Semantic MediaWiki, http://semantic-mediawiki.org/\n"; - } - } - - public function serializeDeclaration( $uri, $typename ) { - $this->post_ns_buffer .= "<" . SMWExporter::expandURI( $uri ) . "> rdf:type $typename .\n"; - } - - public function serializeExpData( SMWExpData $data ) { - $this->subexpdata = array( $data ); - while ( count( $this->subexpdata ) > 0 ) { - $this->serializeNestedExpData( array_pop( $this->subexpdata ), '' ); - } - $this->serializeNamespaces(); - } - - protected function serializeNamespace( $shortname, $uri ) { - $this->global_namespaces[$shortname] = true; - if ( $this->sparqlmode ) { - $this->sparql_namespaces[$shortname] = $uri; - } else { - $this->pre_ns_buffer .= "@prefix $shortname: <$uri> .\n"; - } - } - - /** - * Serialize the given SMWExpData object, possibly recursively with - * increased indentation. - * - * @param $data SMWExpData containing the data to be serialised. - * @param $indent string specifying a prefix for indentation (usually a sequence of tabs) - */ - protected function serializeNestedExpData( SMWExpData $data, $indent ) { - if ( count( $data->getProperties() ) == 0 ) return; // nothing to export - $this->recordDeclarationTypes( $data ); - - $bnode = false; - $this->post_ns_buffer .= $indent; - if ( !$data->getSubject()->isBlankNode() ) { - $this->serializeExpResource( $data->getSubject() ); - } else { // blank node - $bnode = true; - $this->post_ns_buffer .= "["; - } - - if ( ( $indent !== '' ) && ( !$bnode ) ) { // called to generate a nested descripion; but Turtle cannot nest non-bnode descriptions, do this later - $this->subexpdata[] = $data; - return; - } elseif ( !$bnode ) { - $this->post_ns_buffer .= "\n "; - } - - $firstproperty = true; - foreach ( $data->getProperties() as $property ) { - $this->post_ns_buffer .= $firstproperty ? "\t" : " ;\n $indent\t"; - $firstproperty = false; - $prop_decl_queued = false; - $class_type_prop = $this->isOWLClassTypeProperty( $property ); - $this->serializeExpResource( $property ); - $firstvalue = true; - - foreach ( $data->getValues( $property ) as $value ) { - $this->post_ns_buffer .= $firstvalue ? ' ' : ' , '; - $firstvalue = false; - - if ( $value instanceof SMWExpLiteral ) { - $prop_decl_type = SMW_SERIALIZER_DECL_APROP; - $this->serializeExpLiteral( $value ); - } elseif ( $value instanceof SMWExpResource ) { - $prop_decl_type = SMW_SERIALIZER_DECL_OPROP; - $this->serializeExpResource( $value ); - } elseif ( $value instanceof SMWExpData ) { // resource (maybe blank node), could have subdescriptions - $prop_decl_type = SMW_SERIALIZER_DECL_OPROP; - $collection = $value->getCollection(); - if ( $collection !== false ) { // RDF-style collection (list) - $this->post_ns_buffer .= "( "; - foreach ( $collection as $subvalue ) { - $this->serializeNestedExpData( $subvalue, $indent . "\t\t" ); - if ( $class_type_prop ) { - $this->requireDeclaration( $subvalue, SMW_SERIALIZER_DECL_CLASS ); - } - } - $this->post_ns_buffer .= " )"; - } else { - if ( $class_type_prop ) { - $this->requireDeclaration( $value->getSubject(), SMW_SERIALIZER_DECL_CLASS ); - } - if ( count( $value->getProperties() ) > 0 ) { // resource with data: serialise - $this->post_ns_buffer .= "\n"; - $this->serializeNestedExpData( $value, $indent . "\t\t" ); - } else { // resource without data: may need to be queued - $this->serializeExpResource( $value->getSubject() ); - } - } - } - - if ( !$prop_decl_queued ) { - $this->requireDeclaration( $property, $prop_decl_type ); - $prop_decl_queued = true; - } - } - } - $this->post_ns_buffer .= ( $bnode ? " ]" : " ." ) . ( $indent === '' ? "\n\n" : '' ); - } - - protected function serializeExpLiteral( SMWExpLiteral $element ) { - $this->post_ns_buffer .= self::getTurtleNameForExpElement( $element ); - } - - protected function serializeExpResource( SMWExpResource $element ) { - if ( $element instanceof SMWExpNsResource ) { - $this->requireNamespace( $element->getNamespaceID(), $element->getNamespace() ); - } - $this->post_ns_buffer .= self::getTurtleNameForExpElement( $element ); - } - - /** - * Get the Turtle serialization string for the given SMWExpElement. The - * method just computes a name, and does not serialize triples, so the - * parameter must be an SMWExpResource or SMWExpLiteral, no SMWExpData. - * - * @param $expElement SMWExpElement being SMWExpLiteral or SMWExpResource - * @return string - */ - public static function getTurtleNameForExpElement( SMWExpElement $expElement ) { - if ( $expElement instanceof SMWExpResource ) { - if ( $expElement->isBlankNode() ) { - return '[]'; - } elseif ( ( $expElement instanceof SMWExpNsResource ) && ( $expElement->hasAllowedLocalName() ) ) { - return $expElement->getQName(); - } else { - return '<' . str_replace( '>', '\>', SMWExporter::expandURI( $expElement->getUri() ) ) . '>'; - } - } elseif ( $expElement instanceof SMWExpLiteral ) { - $lexicalForm = '"' . str_replace( array( '\\', "\n", '"' ), array( '\\\\', "\\n", '\"' ), $expElement->getLexicalForm() ) . '"'; - $dt = $expElement->getDatatype(); - if ( ( $dt !== '' ) && ( $dt != 'http://www.w3.org/2001/XMLSchema#string' ) ) { - $count = 0; - $newdt = str_replace( 'http://www.w3.org/2001/XMLSchema#', 'xsd:', $dt, $count ); - return ( $count == 1 ) ? "$lexicalForm^^$newdt" : "$lexicalForm^^<$dt>"; - } else { - return $lexicalForm; - } - } else { - throw new InvalidArgumentException( 'The method can only serialize atomic elements of type SMWExpResource or SMWExpLiteral.' ); - } - } - -} diff --git a/SemanticMediaWiki/includes/formatters/ArrayFormatter.php b/SemanticMediaWiki/includes/formatters/ArrayFormatter.php deleted file mode 100644 index bfa01631..00000000 --- a/SemanticMediaWiki/includes/formatters/ArrayFormatter.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface related to classes responsible for array formatting - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Interface related to classes responsible for array formatting - * - * @ingroup Formatter - * @codeCoverageIgnore - */ -abstract class ArrayFormatter { - - /** @var array */ - protected $errors = array(); - - /** - * Returns collected errors - * - * @since 1.9 - * - * @return array - */ - public function getErrors() { - return $this->errors; - } - - /** - * Adds an error - * - * @since 1.9 - * - * @param mixed $error - */ - public function addError( $error ) { - $this->errors = array_merge( (array)$error === $error ? $error : array( $error ), $this->errors ); - } - - /** - * Returns a formatted array - * - * @since 1.9 - * - * Implementation is carried out by a subclasses - */ - abstract public function toArray(); -} diff --git a/SemanticMediaWiki/includes/formatters/MessageFormatter.php b/SemanticMediaWiki/includes/formatters/MessageFormatter.php deleted file mode 100644 index b5f720b7..00000000 --- a/SemanticMediaWiki/includes/formatters/MessageFormatter.php +++ /dev/null @@ -1,286 +0,0 @@ -<?php - -namespace SMW; - -use Html; -use Message; -use Language; - -/** - * Class implementing message output formatting - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * This class is implementing message output formatting to avoid having - * classes to invoke a language object that is not a direct dependency (which - * means that context relevant information is mostly missing from the invoking - * class) therefore it is more appropriate to collect Message objects from the - * source and initiate an output formatting only when necessary and requested. - * - * @ingroup Formatter - */ -class MessageFormatter { - - /** @var array */ - protected $messages = array(); - - /** @var string */ - protected $type = 'warning'; - - /** @var string */ - protected $separator = ' <!--br-->'; - - /** @var boolean */ - protected $escape = true; - - /** - * @since 1.9 - * - * @param Language $language - */ - public function __construct( Language $language ) { - $this->language = $language; - } - - /** - * Convenience factory method to invoke a message array together with - * a language object - * - * @par Example: - * @code - * MessageFormatter::newFromArray( $language, array( 'Foo' ) )->getHtml(); - * @endcode - * - * @since 1.9 - * - * @param Language $language - * @param array|null $messages - * - * @return MessageFormatter - */ - public static function newFromArray( Language $language, array $messages = array () ) { - $instance = new self( $language ); - return $instance->addFromArray( $messages ); - } - - /** - * Creates a Message object from a key and adds it to an internal array - * - * @since 1.9 - * - * @param string $key message key - * - * @return MessageFormatter - */ - public function addFromKey( $key /*...*/ ) { - $params = func_get_args(); - array_shift( $params ); - $this->addFromArray( array( new Message( $key, $params ) ) ); - return $this; - } - - /** - * Adds an arbitrary array of messages which can either contain text - * or/and Message objects - * - * @par Example: - * @code - * $msgFormatter = new MessageFormatter( $language ); - * $msgFormatter->addFromArray( array( 'Foo', new Message( 'Bar' ) ) )->getHtml() - * @endcode - * - * @since 1.9 - * - * @param array $messages - * - * @return MessageFormatter - */ - public function addFromArray( array $messages ) { - $this->messages = array_merge ( $messages, $this->messages ); - return $this; - } - - /** - * Returns unformatted invoked messages - * - * @since 1.9 - * - * @return array - */ - public function getMessages() { - return $this->messages; - } - - /** - * Used in connection with the html output to invoke a specific display - * type - * - * @see Highlighter::getTypeId - * - * @since 1.9 - * - * @return MessageFormatter - */ - public function setType( $type ) { - $this->type = $type; - return $this; - } - - /** - * Enables/disables escaping for the output representation - * - * @note Escaping is generally enabled but in cases of special pages or - * with messages already being escaped this option can be circumvent by - * invoking escape( false ) - * - * @since 1.9 - * - * @param boolean $escape - * - * @return MessageFormatter - */ - public function escape( $escape ) { - $this->escape = (bool)$escape; - return $this; - } - - /** - * Clears the internal message array - * - * @since 1.9 - * - * @return MessageFormatter - */ - public function clear() { - $this->messages = array(); - return $this; - } - - /** - * Returns if the internal message array does contain messages - * - * @since 1.9 - * - * @return boolean - */ - public function exists() { - return $this->messages !== array(); - } - - /** - * Overrides invoked language object - * - * @since 1.9 - * - * @param Language $language - * - * @return MessageFormatter - */ - public function setLanguage( Language $language ) { - $this->language = $language; - return $this; - } - - /** - * Formatting and normalization of an array - * - * @note The array is being recursively resolved in order to ensure that - * the returning representation is a 1-n array where duplicate entries - * have been eliminated already while Message objects being transformed - * into a simple text representation using the invoked language - * - * @since 1.9 - * - * @param array $messages - * - * @return array - */ - protected function doFormat( array $messages ) { - $newArray = array(); - - foreach ( $messages as $msg ) { - - if ( $msg instanceof Message ) { - $newArray[] = $msg->inLanguage( $this->language )->text(); - } else if ( (array)$msg === $msg ) { - foreach ( $this->doFormat( $msg ) as $m ) { - $newArray[] = $m; - } - } else if ( (string)$msg === $msg ) { - $newArray[] = $msg; - } - } - - return array_unique( $newArray ); - } - - /** - * Converts the message array into a string representation - * - * @since 1.9 - * - * @param boolean $escape - * @param boolean $html - * - * @return string - */ - protected function getString( $html = true ) { - - if ( $this->escape ) { - $messages = array_map( 'htmlspecialchars', $this->doFormat( $this->messages ) ); - } else { - $messages = $this->doFormat( $this->messages ); - } - - if ( count( $messages ) == 1 ) { - $messageString = $messages[0]; - } else { - foreach ( $messages as &$message ) { - $message = $html ? Html::rawElement( 'li' , array(), $message ) : $message ; - } - - $messageString = implode( $this->separator, $messages ); - $messageString = $html ? Html::rawElement( 'ul' , array(), $messageString ) : $messageString; - } - - return $messageString; - } - - /** - * Returns html representation of the formatted messages - * - * @since 1.9 - * - * @return string - */ - public function getHtml() { - - if ( $this->exists() ) { - - $highlighter = Highlighter::factory( $this->type ); - $highlighter->setContent( array( 'content' => $this->getString( true ) ) ); - - return $highlighter->getHtml(); - } - - return ''; - } - - /** - * Returns plain text representation of the formatted messages - * - * @since 1.9 - * - * @return string - */ - public function getPlain() { - return $this->exists() ? $this->getString( false ) : ''; - } -} diff --git a/SemanticMediaWiki/includes/formatters/ParameterFormatterFactory.php b/SemanticMediaWiki/includes/formatters/ParameterFormatterFactory.php deleted file mode 100644 index e816ff4f..00000000 --- a/SemanticMediaWiki/includes/formatters/ParameterFormatterFactory.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -namespace SMW; - -/** - * Factory class handling parameter formatting instances - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Factory class handling parameter formatting instances - * - * @ingroup Formatter - */ -class ParameterFormatterFactory { - - /** - * Returns an ArrayFormatter instance - * - * @since 1.9 - * - * @param array $rawParams - * - * @return ArrayFormatter - */ - public static function newFromArray( array $rawParams ) { - - if ( isset( $rawParams[0] ) && is_object( $rawParams[0] ) ) { - array_shift( $rawParams ); - } - - //$formatter = JsonParameterFormatter::newFromArray( $rawParams ); - - //if ( $formatter->isJson() ) { - // $instance = $formatter; - //} else { - // $instance = new ParserParameterFormatter( $rawParams ); - //} - - $instance = new ParserParameterFormatter( $rawParams ); - - return $instance; - } -} diff --git a/SemanticMediaWiki/includes/formatters/ParserParameterFormatter.php b/SemanticMediaWiki/includes/formatters/ParserParameterFormatter.php deleted file mode 100644 index c9b7504d..00000000 --- a/SemanticMediaWiki/includes/formatters/ParserParameterFormatter.php +++ /dev/null @@ -1,174 +0,0 @@ -<?php - -namespace SMW; - -/** - * Class handling parser parameter formatting - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Handling raw parameters from the parser hook - * - * @ingroup Formatter - */ -class ParserParameterFormatter extends ArrayFormatter { - - /** @var string */ - protected $defaultSeparator = ','; - - /** @var array */ - protected $rawParameters; - - /** @var array */ - protected $parameters; - - /** @var string */ - protected $first = null; - - /** - * @since 1.9 - * - * @param array $parameters - */ - public function __construct( array $parameters ) { - $this->rawParameters = $parameters; - $this->parameters = $this->format( $this->rawParameters ); - } - - /** - * Returns first available parameter - * - * @since 1.9 - * - * @return string - */ - public function getFirst() { - return $this->first; - } - - /** - * Returns raw parameters - * - * @since 1.9 - * - * @return string - */ - public function getRaw() { - return $this->rawParameters; - } - - /** - * Returns remapped parameters - * - * @since 1.9 - * - * @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 - */ - protected function format( array $params ) { - $results = array(); - $previousProperty = null; - - while ( key( $params ) !== null ) { - $separator = ''; - $values = array(); - - // 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 - if( next( $params ) ) { - $nextElement = explode( '=', trim( current( $params ) ), 2 ); - - if ( $nextElement !== array() ) { - // This allows assignments of type |Has property=Test1,Test2|+sep=, - // 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 ); - } - } - } - - // 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 multiple values with the same preceding property - if ( count( $currentElement ) == 1 && $previousProperty !== null ) { - $currentElement[1] = $currentElement[0]; - $currentElement[0] = $previousProperty; - } else { - $previousProperty = $currentElement[0]; - } - - // Reassign values - if ( $separator !== '' && isset( $currentElement[1] ) ) { - $values = explode( $separator, $currentElement[1] ); - } elseif ( isset( $currentElement[1] ) ) { - $values[] = $currentElement[1]; - } - - // Remap properties and values to output a simple array - foreach ( $values as $value ) { - if ( $value !== '' ){ - $results[ $currentElement[0] ][] = $value; - } - } - } - - return $results; - } -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/formatters/TableFormatter.php b/SemanticMediaWiki/includes/formatters/TableFormatter.php deleted file mode 100644 index a1ce5c09..00000000 --- a/SemanticMediaWiki/includes/formatters/TableFormatter.php +++ /dev/null @@ -1,319 +0,0 @@ -<?php - -namespace SMW; - -use Html; - -/** - * Class handling Html table formatting - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Class handling Html table formatting - * - * @ingroup Formatter - */ -class TableFormatter { - - /** @var array */ - protected $headerItems = array(); - - /** @var array */ - protected $tableRows = array(); - protected $rawRows = array(); - - /** @var array */ - protected $tableHeaders = array(); - protected $rawHeaders = array(); - - /** @var array */ - protected $tableCells = array(); - - /** @var boolean */ - protected $transpose = false; - - /** - * @par Example: - * @code - * $tableFormatter = new SMW\TableFormatter(); - * - * // Setup the header - * $tableFormatter->addTableHeader( 'Foo' ) - * $tableFormatter->addTableHeader( 'Bar' ) - * - * // Add row - * $tableFormatter->addTableCell( 'Lula' ) - * $tableFormatter->addTableCell( 'Lala' ) - * $tableFormatter->addTableRow() - * ... - * - * // Get table - * $tableFormatter->getTable() // Standard table - * $tableFormatter->transpose()->getTable() // Transposed table - * $tableFormatter->transpose( false )->getTable() // Standard table - * @endcode - * - * @since 1.9 - * - * @param boolean $htmlContext - */ - public function __construct( $htmlContext = false ) { - $this->htmlContext = $htmlContext; - } - - /** - * Sets if the table should be transposed - * - * @since 1.9 - * - * @param boolean $transpose - * - * @return TableFormatter - */ - public function transpose( $transpose = true ) { - $this->transpose = $transpose; - return $this; - } - - /** - * Adds an arbitrary header item to an internal array - * - * @since 1.9 - * - * @param string $element - * @param string $content - * @param array $attributes - * - * @return string - */ - public function addHeaderItem( $element, $content = '', $attributes = array() ) { - $this->headerItems[] = Html::rawElement( $element, $attributes, $content ); - } - - /** - * Returns concatenated header items - * - * @since 1.9 - * - * @return string - */ - public function getHeaderItems() { - return implode( '', $this->headerItems ); - } - - /** - * Collects and adds table cells - * - * @since 1.9 - * - * @param string $content - * @param array $attributes - * - * @return TableFormatter - */ - public function addTableCell( $content = '', $attributes = array() ) { - if ( $content !== '' ) { - $this->tableCells[] = $this->getCell( $content, $attributes ); - } - return $this; - } - - /** - * Collects and adds table headers - * - * @since 1.9 - * - * @param string $content - * @param array $attributes - * - * @return TableFormatter - */ - public function addTableHeader( $content = '', $attributes = array() ) { - if ( $content !== '' ) { - $this->rawHeaders[] = array( 'content' => $content, 'attributes' => $attributes ); - } - return $this; - } - - /** - * Build a row from invoked cells, copy them into a new associated array - * and delete those cells as they are now part of a row - * - * @par Example: - * @code - * ... - * $tableFormatter->addTableCell( 'Lula' )->addTableCell( 'Lala' )->addTableRow() - * ... - * @endcode - * - * @since 1.9 - * - * @param array $attributes - * - * @return TableFormatter - */ - public function addTableRow( $attributes = array() ) { - if ( $this->tableCells !== array() ) { - $this->rawRows[] = array( 'cells' => $this->tableCells, 'attributes' => $attributes ); - $this->tableCells = array(); - } - return $this; - } - - /** - * Internal method for returning a table row definition - * - * @since 1.9 - * - * @param string $content - * @param array $attributes - * - * @return string - */ - protected function getRow( $content = '', $attributes = array() ) { - $alternate = count( $this->tableRows ) % 2 == 0 ? 'row-odd' : 'row-even'; - - if ( isset( $attributes['class'] ) ) { - $attributes['class'] = $attributes['class'] . ' ' . $alternate; - } else { - $attributes['class'] = $alternate; - } - - return Html::rawElement( 'tr', $attributes , $content ); - } - - /** - * Internal method for returning a table cell definition - * - * @since 1.9 - * - * @param string $content - * @param array $attributes - * - * @return string - */ - protected function getCell( $content = '', $attributes = array() ) { - return Html::rawElement( 'td', $attributes, $content ); - } - - /** - * Internal method for returning a table header definition - * - * @since 1.9 - * - * @param string $content - * @param array $attributes - * - * @return string - */ - protected function getHeader( $content = '', $attributes = array() ) { - return Html::rawElement( 'th', $attributes, $content ); - } - - /** - * Returns table headers as concatenated string - * - * @since 1.9 - * - * @return string - */ - protected function getTableHeader() { - return $this->htmlContext ? Html::rawElement( 'thead', array(), implode( '', $this->tableHeaders ) ) : implode( '', $this->tableHeaders ); - } - - /** - * Returns table rows as concatenated string - * - * @since 1.9 - * - * @return string - */ - protected function getTableRows() { - return $this->htmlContext ? Html::rawElement( 'tbody', array(), implode( '', $this->tableRows ) ) : implode( '', $this->tableRows ); - } - - /** - * Returns a standard table - * - * @since 1.9 - * - * @return string - */ - protected function getStandardTable() { - $this->tableHeaders = array(); - $this->tableRows = array(); - - foreach( $this->rawHeaders as $i => $header ) { - $this->tableHeaders[] = $this->getHeader( $header['content'], $header['attributes'] ); - } - - foreach( $this->rawRows as $row ) { - $this->tableRows[] = $this->getRow( implode( '', $row['cells'] ), $row['attributes'] ); - } - - return $this->getTableHeader() . $this->getTableRows(); - } - - /** - * Returns a transposed table - * - * @note A table will only be transposed if header elements are available - * - * @since 1.9 - * - * @return string - */ - protected function getTransposedTable() { - $this->tableRows = array(); - - foreach( $this->rawHeaders as $hIndex => $header ) { - $cells = array(); - $headerItem = $this->getHeader( $header['content'], $header['attributes'] ); - - foreach( $this->rawRows as $rIndex => $row ) { - $cells[] = isset( $row['cells'][$hIndex] ) ? $row['cells'][$hIndex] : $this->getCell( '' ); - } - - // Collect new rows - $this->tableRows[] = $this->getRow( $headerItem . implode( '', $cells ) ); - } - - return $this->getTableHeader() . $this->getTableRows(); - } - - /** - * Returns a table - * - * @par Example: - * @code - * ... - * $tableFormatter->getTable() // Standard table - * $tableFormatter->transpose()->getTable() // Transposed table - * $tableFormatter->transpose( false )->getTable() // Standard table - * ... - * @endcode - * - * @since 1.9 - * - * @param array $attributes - * - * @return string - */ - public function getTable( $attributes = array() ) { - - $table = $this->transpose ? $this->getTransposedTable() : $this->getStandardTable(); - - if ( $table !== '' ) { - return Html::rawElement( 'table', $attributes, $table ); - } - - return ''; - } -} diff --git a/SemanticMediaWiki/includes/interfaces/DBConnectionProvider.php b/SemanticMediaWiki/includes/interfaces/DBConnectionProvider.php deleted file mode 100644 index 6607aae2..00000000 --- a/SemanticMediaWiki/includes/interfaces/DBConnectionProvider.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface for database connection providers. - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -interface DBConnectionProvider { - - /** - * Returns the database connection. - * Initialization of this connection is done if it was not already initialized. - * - * @since 0.1 - * - * @return DatabaseBase - */ - public function getConnection(); - - /** - * Releases the connection if doing so makes any sense resource wise. - * - * @since 0.1 - */ - public function releaseConnection(); - -} diff --git a/SemanticMediaWiki/includes/interfaces/IdGenerator.php b/SemanticMediaWiki/includes/interfaces/IdGenerator.php deleted file mode 100644 index 3326574e..00000000 --- a/SemanticMediaWiki/includes/interfaces/IdGenerator.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface describing a Id generrator - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface IdGenerator { - - /** - * Generates an id - * - * @since 1.9 - * - * @return string - */ - public function generateId(); - -} diff --git a/SemanticMediaWiki/includes/interfaces/ObjectDictionary.php b/SemanticMediaWiki/includes/interfaces/ObjectDictionary.php deleted file mode 100644 index ef8aa310..00000000 --- a/SemanticMediaWiki/includes/interfaces/ObjectDictionary.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface specifying methods for an accessible object - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface Accessible { - - /** - * Returns whether a specific element is accessible - * - * @since 1.9 - * - * @param mixed $key specific key - * - * @return boolean - */ - public function has( $key ); - - /** - * Returns a element for a specific key - * - * @since 1.9 - * - * @param mixed $key specific key - * - * @return mixed - */ - public function get( $key ); - -} - -/** - * Interface specifying methods for a changeable object - * - * @ingroup Utility - */ -interface Changeable { - - /** - * Adds an new element (key, value pair) to an existing collection - * - * @since 1.9 - * - * @param mixed $key - * @param mixed $value - */ - public function set( $key, $value ); - - /** - * Removes an element from a collection - * - * @since 1.9 - * - * @param mixed $key specific key - */ - public function remove( $key ); - -} - -/** - * Interface specifying methods for a combinable object - * - * @ingroup Utility - */ -interface Combinable { - - /** - * Returns an array - * - * @since 1.9 - * - * @return array - */ - public function toArray(); - - /** - * Merges elements of one or more arrays together - * - * @since 1.9 - * - * @param array $mergeable - */ - public function merge( array $mergeable ); - -} - -/** - * Interface specifying an object dictionary - * - * @ingroup Utility - */ -interface ObjectDictionary extends Accessible, Changeable, Combinable {} diff --git a/SemanticMediaWiki/includes/interfaces/Observable.php b/SemanticMediaWiki/includes/interfaces/Observable.php deleted file mode 100644 index c09c1769..00000000 --- a/SemanticMediaWiki/includes/interfaces/Observable.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -namespace SMW; - -/** - * Extended Publisher interface specifying access to - * source and state changes - * - * @ingroup Observer - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface Observable { - - /** - * Attaches a Subscriber - * - * @since 1.9 - * - * @param Observer $observer - */ - public function attach( Observer $observer ); - - /** - * Detaches a Subscriber - * - * @since 1.9 - * - * @param Observer $observer - */ - public function detach( Observer $observer ); - - /** - * Notifies attached Subscribers - * - * @since 1.9 - */ - public function notify(); - - /** - * Returns the invoked state change - * - * @since 1.9 - */ - public function getState(); - - /** - * Registers a state change - * - * @since 1.9 - */ - public function setState( $state ); - - /** - * Returns the emitter of the state change - * - * @since 1.9 - */ - public function getSubject(); - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/interfaces/Observer.php b/SemanticMediaWiki/includes/interfaces/Observer.php deleted file mode 100644 index facb4c41..00000000 --- a/SemanticMediaWiki/includes/interfaces/Observer.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface describing a Observer - * - * @ingroup Observer - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface Observer { - - /** - * Receives update task from a publishable source - * - * @since 1.9 - * - * @param Observable $observable - */ - public function update( Observable $observable ); - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/interfaces/ResultCollector.php b/SemanticMediaWiki/includes/interfaces/ResultCollector.php deleted file mode 100644 index 718ed486..00000000 --- a/SemanticMediaWiki/includes/interfaces/ResultCollector.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface for items of groups of individuals to be sampled into a - * collection of values - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface ResultCollector { - - /** - * Intiates collection of items - * - * @since 1.9 - * - * @return array - */ - public function runCollector(); - - /** - * Returns collected items - * - * @since 1.9 - * - * @return array - */ - public function getResults(); - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/params/SMW_ParamFormat.php b/SemanticMediaWiki/includes/params/SMW_ParamFormat.php deleted file mode 100644 index 68248c89..00000000 --- a/SemanticMediaWiki/includes/params/SMW_ParamFormat.php +++ /dev/null @@ -1,155 +0,0 @@ -<?php - -use ParamProcessor\Definition\StringParam; -use ParamProcessor\IParam; - -/** - * Definition for the format parameter. - * - * @since 1.6.2 - * @deprecated since 1.9 - * - * @file - * @ingroup SMW - * @ingroup ParamDefinition - * - * @licence GNU GPL v2+ - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class SMWParamFormat extends StringParam { - - /** - * List of the queries print requests, used to determine the format - * when it's not provided. Set with setPrintRequests before passing - * to Validator. - * - * @since 1.6.2 - * - * @var SMWPrintRequest[] - */ - protected $printRequests = array(); - - /** - * Takes a format name, which can be an alias and returns a format name - * which will be valid for sure. Aliases are resolved. If the given - * format name is invalid, the predefined default format will be returned. - * - * @since 1.6.2 - * - * @param string $value - * - * @return string - */ - protected function getValidFormatName( $value ) { - global $smwgResultFormats; - - $value = strtolower( trim( $value ) ); - - if ( !array_key_exists( $value, $smwgResultFormats ) ) { - $isAlias = self::resolveFormatAliases( $value ); - - if ( !$isAlias ) { - $value = $this->getDefaultFormat(); - self::resolveFormatAliases( $value ); - } - } - - return $value; - } - - /** - * Turns format aliases into main formats. - * - * @since 1.6.2 - * - * @param string $format - * - * @return boolean Indicates if the passed format was an alias, and thus was changed. - */ - public static function resolveFormatAliases( &$format ) { - global $smwgResultAliases; - - $isAlias = false; - - foreach ( $smwgResultAliases as $mainFormat => $aliases ) { - if ( in_array( $format, $aliases ) ) { - $format = $mainFormat; - $isAlias = true; - break; - } - } - - return $isAlias; - } - - /** - * Determines and returns the default format, based on the queries print - * requests, if provided. - * - * @since 1.6.2 - * - * @return string Array key in $smwgResultFormats - */ - protected function getDefaultFormat() { - if ( empty( $this->printRequests ) ) { - return 'table'; - } - else { - $format = false; - - /** - * This hook allows extensions to override SMWs implementation of default result - * format handling. - * - * @since 1.5.2 - */ - wfRunHooks( 'SMWResultFormat', array( &$format, $this->printRequests, array() ) ); - - // If no default was set by an extension, use a table or list, depending on the column count. - if ( $format === false ) { - $format = count( $this->printRequests ) == 1 ? 'list' : 'table'; - } - - return $format; - } - } - - /** - * Sets the print requests of the query, used for determining - * the default format if none is provided. - * - * @since 1.6.2 - * - * @param SMWPrintRequest[] $printRequests - */ - public function setPrintRequests( array $printRequests ) { - $this->printRequests = $printRequests; - } - - /** - * Formats the parameter value to it's final result. - * - * @since 1.8 - * - * @param mixed $value - * @param IParam $param - * @param IParamDefinition[] $definitions - * @param IParam[] $params - * - * @return mixed - */ - protected function formatValue( $value, IParam $param, array &$definitions, array $params ) { - $value = parent::formatValue( $value, $param, $definitions, $params ); - - // Make sure the format value is valid. - $value = self::getValidFormatName( $value ); - - // Add the formats parameters to the parameter list. - $queryPrinter = SMWQueryProcessor::getResultPrinter( $value ); - - $definitions = $queryPrinter->getParamDefinitions( $definitions ); - - return $value; - } - -} diff --git a/SemanticMediaWiki/includes/parserhooks/AskParserFunction.php b/SemanticMediaWiki/includes/parserhooks/AskParserFunction.php deleted file mode 100644 index cc93f455..00000000 --- a/SemanticMediaWiki/includes/parserhooks/AskParserFunction.php +++ /dev/null @@ -1,160 +0,0 @@ -<?php - -namespace SMW; - -use Parser; -use SMWQueryProcessor; - -/** - * Provides the {{#ask}} parser function - * - * @see http://www.semantic-mediawiki.org/wiki/Help:Ask - * - * @ingroup ParserFunction - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author mwjames - */ -class AskParserFunction { - - /** @var ParserData */ - protected $parserData; - - /** @var ContextResource */ - protected $context; - - /** @var boolean */ - protected $showMode = false; - - /** - * @since 1.9 - * - * @param ParserData $parserData - * @param ContextResource $context - */ - public function __construct( ParserData $parserData, ContextResource $context ) { - $this->parserData = $parserData; - $this->context = $context; - } - - /** - * Enable showMode (normally only invoked by {{#show}}) - * - * @since 1.9 - * - * @return AskParserFunction - */ - public function setShowMode( $mode ) { - $this->showMode = $mode; - return $this; - } - - /** - * Parse parameters, return results from the query printer and update the - * ParserOutput with meta data from the query - * - * FIXME $rawParams use IParameterFormatter -> QueryParameterFormatter class - * Parse parameters and return query results to the ParserOutput - * object and output result data from the SMWQueryProcessor - * - * @todo $rawParams should be of IParameterFormatter - * QueryParameterFormatter class - * - * @since 1.9 - * - * @param array $params - * - * @return string|null - */ - public function parse( array $rawParams ) { - - // Counter for what? Where and for what is it used? - global $smwgIQRunningNumber; - $smwgIQRunningNumber++; - - // Remove parser object from parameters array - if( isset( $rawParams[0] ) && $rawParams[0] instanceof Parser ) { - array_shift( $rawParams ); - } - - $this->runQueryProcessor( $rawParams ); - $this->runQueryProfiler( $rawParams ); - - $this->parserData->updateOutput(); - - return $this->result; - } - - /** - * {{#ask}} is disabled (see $smwgQEnabled) - * - * @since 1.9 - * - * @return string|null - */ - public function isQueryDisabled() { - return $this->context->getDependencyBuilder() - ->newObject( 'MessageFormatter' ) - ->addFromKey( 'smw_iq_disabled' ) - ->getHtml(); - } - - /** - * @since 1.9 - */ - private function runQueryProcessor( array $rawParams ) { - - // FIXME QueryDuration should be a property of the QueryProcessor or - // QueryEngine but since we don't want to open the pandora's box and - // increase issues within the current QueryProcessor implementation - // we will track the time outside of the actual execution framework - $this->queryDuration = 0; - $start = microtime( true ); - - list( $this->query, $this->params ) = SMWQueryProcessor::getQueryAndParamsFromFunctionParams( - $rawParams, - SMW_OUTPUT_WIKI, - SMWQueryProcessor::INLINE_QUERY, - $this->showMode - ); - - $this->result = SMWQueryProcessor::getResultFromQuery( - $this->query, - $this->params, - SMW_OUTPUT_WIKI, - SMWQueryProcessor::INLINE_QUERY - ); - - if ( $this->context->getSettings()->get( 'smwgQueryDurationEnabled' ) ) { - $this->queryDuration = microtime( true ) - $start; - } - - } - - /** - * @since 1.9 - */ - private function runQueryProfiler( array $rawParams ) { - - $profiler = $this->context->getDependencyBuilder()->newObject( 'QueryProfiler', array( - 'QueryDescription' => $this->query->getDescription(), - 'QueryParameters' => $rawParams, - 'QueryFormat' => $this->params['format']->getValue(), - 'QueryDuration' => $this->queryDuration, - 'Title' => $this->parserData->getTitle(), - ) ); - - $profiler->addAnnotation(); - - $this->parserData->getData()->addPropertyObjectValue( - $profiler->getProperty(), - $profiler->getContainer() - ); - - } - -} diff --git a/SemanticMediaWiki/includes/parserhooks/ConceptParserFunction.php b/SemanticMediaWiki/includes/parserhooks/ConceptParserFunction.php deleted file mode 100644 index 6ba9e74d..00000000 --- a/SemanticMediaWiki/includes/parserhooks/ConceptParserFunction.php +++ /dev/null @@ -1,186 +0,0 @@ -<?php - -namespace SMW; - -use Parser; -use Html; -use Title; - -use SMWDIProperty; -use SMWInfolink; -use SMWQueryProcessor; - -/** - * Class that provides the {{#concept}} parser function - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author mwjames - */ - -/** - * Class that provides the {{#concept}} parser function - * - * @ingroup ParserFunction - */ -class ConceptParserFunction { - - /** @var ParserData */ - protected $parserData; - - /** @var MessageFormatter */ - protected $msgFormatter; - - /** - * @since 1.9 - * - * @param ParserData $parserData - * @param MessageFormatter $msgFormatter - */ - public function __construct( ParserData $parserData, MessageFormatter $msgFormatter ) { - $this->parserData = $parserData; - $this->msgFormatter = $msgFormatter; - } - - /** - * Returns RDF link - * - * @since 1.9 - * - * @param Title $title - * - * @return string - */ - protected function getRDFLink( Title $title ) { - return SMWInfolink::newInternalLink( - wfMessage( 'smw_viewasrdf' )->inContentLanguage()->text(), - $title->getPageLanguage()->getNsText( NS_SPECIAL ) . ':ExportRDF/' . $title->getPrefixedText(), 'rdflink' - ); - } - - /** - * Returns a concept information box as html - * - * @since 1.9 - * - * @param Title $title - * @param $queryString - * @param $documentation - * - * @return string - */ - protected function getHtml( Title $title, $queryString, $documentation ) { - return Html::rawElement( 'div', array( 'class' => 'smwfact' ), - Html::rawElement( 'span', array( 'class' => 'smwfactboxhead' ), - wfMessage( 'smw_concept_description', $title->getText() )->inContentLanguage()->text() ) . - Html::rawElement( 'span', array( 'class' => 'smwrdflink' ), $this->getRDFLink( $title )->getWikiText() ) . - Html::element( 'br', array() ) . - Html::element( 'p', array(), $documentation ? $documentation : '' ) . - Html::rawElement( 'pre', array(), str_replace( '[', '[', $queryString ) ) . - Html::element( 'br', array() ) - ); - } - - /** - * After some discussion IQueryProcessor/QueryProcessor is not being - * used in 1.9 and instead rely on SMWQueryProcessor - * - * @todo Static class SMWQueryProcessor, please fixme - */ - private function initQueryProcessor( array $rawParams, $showMode = false ) { - list( $this->query, $this->params ) = SMWQueryProcessor::getQueryAndParamsFromFunctionParams( - $rawParams, - SMW_OUTPUT_WIKI, - SMWQueryProcessor::INLINE_QUERY, - $showMode - ); - - $this->result = SMWQueryProcessor::getResultFromQuery( - $this->query, - $this->params, - SMW_OUTPUT_WIKI, - SMWQueryProcessor::INLINE_QUERY - ); - } - - /** - * Parse parameters, return concept information box and update the - * ParserOutput with the concept object - * - * @since 1.9 - * - * @param array $params - * - * @return string|null - */ - public function parse( array $rawParams ) { - $this->parserData->getOutput()->addModules( 'ext.smw.style' ); - - $title = $this->parserData->getTitle(); - $property = new SMWDIProperty( '_CONC' ); - - if ( !( $title->getNamespace() === SMW_NS_CONCEPT ) ) { - return $this->msgFormatter->addFromKey( 'smw_no_concept_namespace' )->getHtml(); - } elseif ( count( $this->parserData->getData()->getPropertyValues( $property ) ) > 0 ) { - return $this->msgFormatter->addFromKey( 'smw_multiple_concepts' )->getHtml(); - } - - // Remove parser object from parameters array - if( isset( $rawParams[0] ) && $rawParams[0] instanceof Parser ) { - array_shift( $rawParams ); - } - - // Use first parameter as concept (query) string - $conceptQuery = array_shift( $rawParams ); - - // Use second parameter, if any as a description - $conceptDocu = array_shift( $rawParams ); - - // Query processor - $this->initQueryProcessor( array( $conceptQuery ) ); - - $conceptQueryString = $this->query->getDescription()->getQueryString(); - - // Store query data to the semantic data instance - $this->parserData->getData()->addPropertyObjectValue( - $property, - new DIConcept( - $conceptQueryString, - $conceptDocu, - $this->query->getDescription()->getQueryFeatures(), - $this->query->getDescription()->getSize(), - $this->query->getDescription()->getDepth() - ) - ); - - // Collect possible errors - $this->msgFormatter->addFromArray( $this->query->getErrors() )->addFromArray( $this->parserData->getErrors() ); - - // Update ParserOutput - $this->parserData->updateOutput(); - - return $this->msgFormatter->exists() ? $this->msgFormatter->getHtml() : $this->getHtml( $title, $conceptQueryString, $conceptDocu ); - } - - /** - * Parser::setFunctionHook {{#concept}} handler method - * - * @since 1.9 - * - * @param Parser $parser - * - * @return string - */ - public static function render( Parser &$parser ) { - $concept = new self( - new ParserData( $parser->getTitle(), $parser->getOutput() ), - new MessageFormatter( $parser->getTargetLanguage() ) - ); - return $concept->parse( func_get_args() ); - } -} diff --git a/SemanticMediaWiki/includes/parserhooks/DeclareParserFunction.php b/SemanticMediaWiki/includes/parserhooks/DeclareParserFunction.php deleted file mode 100644 index 963c16fe..00000000 --- a/SemanticMediaWiki/includes/parserhooks/DeclareParserFunction.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -namespace SMW; - -use Parser; -use SMWOutputs; - -/** - * Class that provides the {{#declare}} parser function - * - * @see http://semantic-mediawiki.org/wiki/Help:Argument_declaration_in_templates - * - * @file - * - * @license GNU GPL v2+ - * @since 1.5.3 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - */ - -/** - * Class that provides the {{#declare}} parser function - * - * @ingroup ParserFunction - */ -class DeclareParserFunction { - - /** - * Method for handling the declare parser function. - * - * @since 1.5.3 - * - * @param Parser $parser - * @param \PPFrame $frame - * @param array $args - */ - public static function render( Parser &$parser, \PPFrame $frame, array $args ) { - if ( $frame->isTemplate() ) { - - $parserData = new ParserData( $parser->getTitle(), $parser->getOutput() ); - $subject = $parserData->getSemanticData()->getSubject(); - - foreach ( $args as $arg ) - if ( trim( $arg ) !== '' ) { - $expanded = trim( $frame->expand( $arg ) ); - $parts = explode( '=', $expanded, 2 ); - - if ( count( $parts ) == 1 ) { - $propertystring = $expanded; - $argumentname = $expanded; - } else { - $propertystring = $parts[0]; - $argumentname = $parts[1]; - } - - $property = \SMWPropertyValue::makeUserProperty( $propertystring ); - $argument = $frame->getArgument( $argumentname ); - $valuestring = $frame->expand( $argument ); - - if ( $property->isValid() ) { - $type = $property->getPropertyTypeID(); - - if ( $type == '_wpg' ) { - $matches = array(); - preg_match_all( '/\[\[([^\[\]]*)\]\]/u', $valuestring, $matches ); - $objects = $matches[1]; - - if ( count( $objects ) == 0 ) { - if ( trim( $valuestring ) !== '' ) { - $dataValue = DataValueFactory::getInstance()->newPropertyValue( - $propertystring, - $valuestring, - false, - $subject - ); - - $parserData->addDataValue( $dataValue ); - } - } else { - foreach ( $objects as $object ) { - $dataValue = DataValueFactory::getInstance()->newPropertyValue( - $propertystring, - $object, - false, - $subject - ); - - $parserData->addDataValue( $dataValue ); - } - } - } elseif ( trim( $valuestring ) !== '' ) { - - $dataValue = DataValueFactory::getInstance()->newPropertyValue( - $propertystring, - $valuestring, - false, - $subject - ); - - $parserData->addDataValue( $dataValue ); - } - - // $value = \SMW\DataValueFactory::getInstance()->newPropertyObjectValue( $property->getDataItem(), $valuestring ); - // if (!$value->isValid()) continue; - } - } - - $parserData->updateOutput(); - } else { - // @todo Save as metadata - } - - global $wgTitle; - if ( !is_null( $wgTitle ) && $wgTitle->isSpecialPage() ) { - global $wgOut; - SMWOutputs::commitToOutputPage( $wgOut ); - } - else { - SMWOutputs::commitToParser( $parser ); - } - - return ''; - } -} diff --git a/SemanticMediaWiki/includes/parserhooks/DocumentationParserFunction.php b/SemanticMediaWiki/includes/parserhooks/DocumentationParserFunction.php deleted file mode 100644 index a3237df6..00000000 --- a/SemanticMediaWiki/includes/parserhooks/DocumentationParserFunction.php +++ /dev/null @@ -1,248 +0,0 @@ -<?php - -namespace SMW; - -use ParamProcessor\ParamDefinition; -use Parser; -use SMWQueryProcessor; - -/** - * Class that provides the {{#smwdoc}} parser function, which displays parameter - * documentation for a specified result format. - * - * @ingroup ParserFunction - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class DocumentationParserFunction extends \ParserHook { - - /** - * Field to store the value of the language parameter. - * - * @since 1.6.1 - * - * @var string - */ - protected $language; - - /** - * No LSB in pre-5.3 PHP *sigh*. - * This is to be refactored as soon as php >=5.3 becomes acceptable. - */ - public static function staticInit( Parser &$parser ) { - $instance = new self; - return $instance->init( $parser ); - } - - /** - * Gets the name of the parser hook. - * @see ParserHook::getName - * - * @since 1.6 - * - * @return string - */ - protected function getName() { - return 'smwdoc'; - } - - /** - * Returns an array containing the parameter info. - * @see ParserHook::getParameterInfo - * - * @since 1.6 - * - * @param $type - * - * @return array - */ - protected function getParameterInfo( $type ) { - return array( - array( - 'name' => 'format', - 'message' => 'smw-smwdoc-par-format', - 'values' => array_keys( $GLOBALS['smwgResultFormats'] ), - ), - array( - 'name' => 'language', - 'message' => 'smw-smwdoc-par-language', - 'default' => $GLOBALS['wgLanguageCode'], - ), - array( - 'name' => 'parameters', - 'message' => 'smw-smwdoc-par-parameters', - 'values' => array( 'all', 'specific', 'base' ), - 'default' => 'specific', - ), - ); - } - - /** - * Returns the list of default parameters. - * @see ParserHook::getDefaultParameters - * - * @since 1.6 - * - * @param $type - * - * @return array - */ - protected function getDefaultParameters( $type ) { - return array( 'format', 'language', 'parameters' ); - } - - /** - * Renders and returns the output. - * @see ParserHook::render - * - * @since 1.0 - * - * @param array $parameters - * - * @return string - */ - public function render( array $parameters ) { - $this->language = $parameters['language']; - - $params = $this->getFormatParameters( $parameters['format'] ); - - if ( $parameters['parameters'] === 'specific' ) { - foreach ( array_keys( SMWQueryProcessor::getParameters() ) as $name ) { - unset( $params[$name] ); - } - } - elseif ( $parameters['parameters'] === 'base' ) { - foreach ( array_diff_key( $params, SMWQueryProcessor::getParameters() ) as $param ) { - unset( $params[$param->getName()] ); - } - } - - return $this->parseWikitext( $this->getParameterTable( $params ) ); - } - - /** - * Returns the wikitext for a table listing the provided parameters. - * - * @since 1.6 - * - * @param $paramDefinitions array of IParamDefinition - * - * @return string - */ - protected function getParameterTable( array $paramDefinitions ) { - $tableRows = array(); - $hasAliases = false; - - foreach ( $paramDefinitions as $parameter ) { - $hasAliases = count( $parameter->getAliases() ) != 0; - if ( $hasAliases ) break; - } - - foreach ( $paramDefinitions as $parameter ) { - if ( $parameter->getName() != 'format' ) { - $tableRows[] = $this->getDescriptionRow( $parameter, $hasAliases ); - } - } - - $table = ''; - - if ( count( $tableRows ) > 0 ) { - $tableRows = array_merge( array( - '!' . $this->msg( 'validator-describe-header-parameter' ) ."\n" . - ( $hasAliases ? '!' . $this->msg( 'validator-describe-header-aliases' ) ."\n" : '' ) . - '!' . $this->msg( 'validator-describe-header-type' ) ."\n" . - '!' . $this->msg( 'validator-describe-header-default' ) ."\n" . - '!' . $this->msg( 'validator-describe-header-description' ) - ), $tableRows ); - - $table = implode( "\n|-\n", $tableRows ); - - $table = - '{| class="wikitable sortable"' . "\n" . - $table . - "\n|}"; - } - - return $table; - } - - /** - * Returns the wikitext for a table row describing a single parameter. - * - * @since 1.6 - * - * @param ParamDefinition $parameter - * @param boolean $hasAliases - * - * @return string - */ - protected function getDescriptionRow( ParamDefinition $parameter, $hasAliases ) { - if ( $hasAliases ) { - $aliases = $parameter->getAliases(); - $aliases = count( $aliases ) > 0 ? implode( ', ', $aliases ) : '-'; - } - - $description = $this->msg( $parameter->getMessage() ); - - $type = $this->msg( $parameter->getTypeMessage() ); - - $default = $parameter->isRequired() ? "''" . $this->msg( 'validator-describe-required' ) . "''" : $parameter->getDefault(); - if ( is_array( $default ) ) { - $default = implode( ', ', $default ); - } - elseif ( is_bool( $default ) ) { - $default = $default ? 'yes' : 'no'; - } - - if ( $default === '' ) $default = "''" . $this->msg( 'validator-describe-empty' ) . "''"; - - return "| {$parameter->getName()}\n" -. ( $hasAliases ? '| ' . $aliases . "\n" : '' ) . -<<<EOT -| {$type} -| {$default} -| {$description} -EOT; - } - - /** - * @param string $format - * - * @return array of IParamDefinition - */ - protected function getFormatParameters( $format ) { - if ( array_key_exists( $format, $GLOBALS['smwgResultFormats'] ) ) { - return ParamDefinition::getCleanDefinitions( - SMWQueryProcessor::getResultPrinter( $format )->getParamDefinitions( SMWQueryProcessor::getParameters() ) - ); - } - else { - return array(); - } - } - - /** - * @see ParserHook::getMessage() - * - * @since 1.6.1 - */ - public function getMessage() { - return 'smw-smwdoc-description'; - } - - /** - * Message function that takes into account the language parameter. - * - * @since 1.6.1 - * - * @param string $key - * @param array $args - * - * @return string - */ - protected function msg( $key ) { - $args = func_get_args(); - $key = array_shift( $args ); - return wfMessage( $key )->params( $args )->useDatabase( true )->inLanguage( $this->language )->text(); - } -} diff --git a/SemanticMediaWiki/includes/parserhooks/InfoParserFunction.php b/SemanticMediaWiki/includes/parserhooks/InfoParserFunction.php deleted file mode 100644 index 323bab6f..00000000 --- a/SemanticMediaWiki/includes/parserhooks/InfoParserFunction.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php - -namespace SMW; - -use Parser; -use SMWOutputs; - -/** - * Class that provides the {{#info}} parser function - * - * @ingroup ParserFunction - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - */ -class InfoParserFunction extends \ParserHook { - - /** - * Renders and returns the output. - * @see ParserHook::render - * - * @since 1.7 - * - * @param array $parameters - * - * @return string - */ - public function render( array $parameters ) { - /** - * Non-escaping is safe bacause a user's message is passed through parser, which will - * handle unsafe HTM elements. - */ - $result = smwfEncodeMessages( - array( $parameters['message'] ), - $parameters['icon'], - ' <!--br-->', - false // No escaping. - ); - - if ( !is_null( $this->parser->getTitle() ) && $this->parser->getTitle()->isSpecialPage() ) { - global $wgOut; - SMWOutputs::commitToOutputPage( $wgOut ); - } - else { - SMWOutputs::commitToParser( $this->parser ); - } - - return $result; - } - - /** - * No LSB in pre-5.3 PHP *sigh*. - * This is to be refactored as soon as php >=5.3 becomes acceptable. - */ - public static function staticInit( Parser &$parser ) { - $instance = new self; - return $instance->init( $parser ); - } - - /** - * Gets the name of the parser hook. - * @see ParserHook::getName - * - * @since 1.7 - * - * @return string - */ - protected function getName() { - return 'info'; - } - - /** - * Returns the list of default parameters. - * @see ParserHook::getDefaultParameters - * - * @since 1.6 - * - * @return array - */ - protected function getDefaultParameters( $type ) { - return array( 'message', 'icon' ); - } - - /** - * Returns an array containing the parameter info. - * @see ParserHook::getParameterInfo - * - * @since 1.7 - * - * @return array - */ - protected function getParameterInfo( $type ) { - return array( - array( - 'name' => 'message', - 'message' => 'smw-info-par-message', - ), - array( - 'name' => 'icon', - 'message' => 'smw-info-par-icon', - 'default' => 'info', - 'values' => array( 'info', 'warning', 'note' ), - ), - ); - } -} diff --git a/SemanticMediaWiki/includes/parserhooks/ParserFunctionFactory.php b/SemanticMediaWiki/includes/parserhooks/ParserFunctionFactory.php deleted file mode 100644 index bc737a16..00000000 --- a/SemanticMediaWiki/includes/parserhooks/ParserFunctionFactory.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -namespace SMW; - -use Parser; - -/** - * Factory class for convenience parser function instantiation - * - * @see http://www.semantic-mediawiki.org/wiki/Help:ParserFunction - * - * @ingroup ParserFunction - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class ParserFunctionFactory implements ContextAware { - - /** @var Parser */ - protected $parser; - - /** @var ContextResource */ - protected $context = null; - - /** - * @since 1.9 - * - * @param Parser $parser - * @param ContextResource|null $context - */ - public function __construct( Parser $parser, ContextResource $context = null ) { - $this->parser = $parser; - $this->context = $context; - } - - /** - * Convenience instantiation of a ParserFunctionFactory object - * - * @since 1.9 - * - * @param Parser $parser - * - * @return ParserFunctionFactory - */ - public static function newFromParser( Parser $parser ) { - return new self( $parser ); - } - - /** - * @see ContextAware::withContext - * - * @since 1.9 - * - * @return ContextResource - */ - public function withContext() { - - if ( $this->context === null ) { - $this->context = new ExtensionContext(); - } - - return $this->context; - } - - /** - * Convenience instantiation of a SubobjectParserFunction object - * - * @since 1.9 - * - * @return SubobjectParserFunction - */ - public function getSubobjectParser() { - return $this->withContext()->getDependencyBuilder()->newObject( 'SubobjectParserFunction', array( 'Parser' => $this->parser ) ); - } - - /** - * Convenience instantiation of a RecurringEventsParserFunction object - * - * @since 1.9 - * - * @return RecurringEventsParserFunction - */ - public function getRecurringEventsParser() { - return new RecurringEventsParserFunction( - new ParserData( $this->parser->getTitle(), $this->parser->getOutput() ), - new Subobject( $this->parser->getTitle() ), - new MessageFormatter( $this->parser->getTargetLanguage() ), - Settings::newFromGlobals() - ); - } -} diff --git a/SemanticMediaWiki/includes/parserhooks/RecurringEventsParserFunction.php b/SemanticMediaWiki/includes/parserhooks/RecurringEventsParserFunction.php deleted file mode 100644 index 101e4b09..00000000 --- a/SemanticMediaWiki/includes/parserhooks/RecurringEventsParserFunction.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -namespace SMW; - -use Parser; - -/** - * Class that provides the {{#set_recurring_event}} parser function - * - * @see http://semantic-mediawiki.org/wiki/Help:Recurring_events - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class RecurringEventsParserFunction extends SubobjectParserFunction { - - /** @var Settings */ - protected $settings; - - /** @var RecurringEvents */ - protected $events; - - /** - * @since 1.9 - * - * @param ParserData $parserData - * @param Subobject $subobject - * @param MessageFormatter $messageFormatter - * @param Settings $settings - */ - public function __construct( - ParserData $parserData, - Subobject $subobject, - MessageFormatter $messageFormatter, - Settings $settings - ) { - parent::__construct ( $parserData, $subobject, $messageFormatter ); - $this->settings = $settings; - } - - /** - * Parse parameters, and update the ParserOutput with data from the - * RecurringEvents object - * - * @since 1.9 - * - * @param ArrayFormatter $parameters - * - * @return string|null - */ - public function parse( ArrayFormatter $parameters ) { - - $this->setFirstElementAsProperty( true ); - - // Get recurring events - $this->events = new RecurringEvents( $parameters->toArray(), $this->settings ); - $this->messageFormatter->addFromArray( $this->events->getErrors() ); - - foreach ( $this->events->getDates() as $date_str ) { - - // Override existing parameters array with the returned - // pre-processed parameters array from recurring events - $parameters->setParameters( $this->events->getParameters() ); - - // Add the date string as individual property / value parameter - $parameters->addParameter( $this->events->getProperty(), $date_str ); - - // @see SubobjectParserFunction::addSubobjectValues - $this->addDataValuesToSubobject( $parameters ); - - // Each new $parameters set will add an additional subobject - // to the instance - $this->parserData->getSemanticData()->addPropertyObjectValue( - $this->subobject->getProperty(), - $this->subobject->getContainer() - ); - - // Collect errors that occurred during processing - $this->messageFormatter->addFromArray( $this->subobject->getErrors() ); - } - - // Update ParserOutput - $this->parserData->updateOutput(); - - return $this->messageFormatter->getHtml(); - } - - /** - * Parser::setFunctionHook {{#set_recurring_event}} handler method - * - * @param Parser $parser - * - * @return string|null - */ - public static function render( Parser &$parser ) { - $instance = new self( - new ParserData( $parser->getTitle(), $parser->getOutput() ), - new Subobject( $parser->getTitle() ), - new MessageFormatter( $parser->getTargetLanguage() ), - Settings::newFromGlobals() - ); - - return $instance->parse( new ParserParameterFormatter( func_get_args() ) ); - } -} diff --git a/SemanticMediaWiki/includes/parserhooks/SetParserFunction.php b/SemanticMediaWiki/includes/parserhooks/SetParserFunction.php deleted file mode 100644 index 11dd7126..00000000 --- a/SemanticMediaWiki/includes/parserhooks/SetParserFunction.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php - -namespace SMW; - -use Parser; - -/** - * Class that provides the {{#set}} parser function - * - * @see http://semantic-mediawiki.org/wiki/Help:Properties_and_types#Silent_annotations_using_.23set - * @see http://www.semantic-mediawiki.org/wiki/Help:Setting_values - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author mwjames - */ - -/** - * Class that provides the {{#set}} parser function - * - * @ingroup ParserFunction - */ -class SetParserFunction { - - /** @var ParserDate */ - protected $parserData; - - /** @var MessageFormatter */ - protected $msgFormatter; - - /** - * @since 1.9 - * - * @param ParserData $parserData - * @param MessageFormatter $msgFormatter - */ - public function __construct( ParserData $parserData, MessageFormatter $msgFormatter ) { - $this->parserData = $parserData; - $this->msgFormatter = $msgFormatter; - } - - /** - * Parse parameters and store its results to the ParserOutput object - * - * @since 1.9 - * - * @param ArrayFormatter $parameters - * - * @return string|null - */ - public function parse( ArrayFormatter $parameters ) { - - $subject = $this->parserData->getSemanticData()->getSubject(); - - foreach ( $parameters->toArray() as $property => $values ){ - foreach ( $values as $value ) { - - $dataValue = DataValueFactory::getInstance()->newPropertyValue( - $property, - $value, - false, - $subject - ); - - $this->parserData->addDataValue( $dataValue ); - } - } - - // Update ParserOutput - $this->parserData->updateOutput(); - - return $this->msgFormatter->addFromArray( $this->parserData->getErrors() ) - ->addFromArray( $parameters->getErrors() ) - ->getHtml(); - } - - /** - * Parser::setFunctionHook {{#set}} handler method - * - * @param Parser $parser - * - * @return string|null - */ - public static function render( Parser &$parser ) { - $set = new self( - new ParserData( $parser->getTitle(), $parser->getOutput() ), - new MessageFormatter( $parser->getTargetLanguage() ) - ); - return $set->parse( ParameterFormatterFactory::newFromArray( func_get_args() ) ); - } -} diff --git a/SemanticMediaWiki/includes/parserhooks/ShowParserFunction.php b/SemanticMediaWiki/includes/parserhooks/ShowParserFunction.php deleted file mode 100644 index 6a0853fc..00000000 --- a/SemanticMediaWiki/includes/parserhooks/ShowParserFunction.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -namespace SMW; - -/** - * Class that provides the {{#show}} parser function - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class ShowParserFunction { - - /** @var ParserData */ - protected $parserData; - - /** @var ContextResource */ - protected $context; - - /** - * @since 1.9 - * - * @param ParserData $parserData - * @param ContextResource $context - */ - public function __construct( ParserData $parserData, ContextResource $context ) { - $this->parserData = $parserData; - $this->context = $context; - } - - /** - * Parse parameters, return results from the query printer and update the - * ParserOutput with meta data from the query - * - * @note The {{#show}} parser function internally uses the AskParserFunction - * and while an extra ShowParserFunction constructor is not really necessary - * it allows for separate unit testing - * - * @since 1.9 - * - * @param array $params - * - * @return string|null - */ - public function parse( array $rawParams ) { - $ask = new AskParserFunction( $this->parserData, $this->context ); - return $ask->setShowMode( true )->parse( $rawParams ); - } - - /** - * Returns a message about inline queries being disabled - * @see $smwgQEnabled - * - * @since 1.9 - * - * @return string|null - */ - public function isQueryDisabled() { - return $this->context->getDependencyBuilder() - ->newObject( 'MessageFormatter' ) - ->addFromKey( 'smw_iq_disabled' ) - ->getHtml(); - } - -} diff --git a/SemanticMediaWiki/includes/parserhooks/SubobjectParserFunction.php b/SemanticMediaWiki/includes/parserhooks/SubobjectParserFunction.php deleted file mode 100644 index 27df8ca3..00000000 --- a/SemanticMediaWiki/includes/parserhooks/SubobjectParserFunction.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php - -namespace SMW; - -use Parser; - -/** - * Provides the {{#subobject}} parser function - * - * @see http://www.semantic-mediawiki.org/wiki/Help:ParserFunction - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SubobjectParserFunction { - - const PARAM_SORTKEY = '@sortkey'; - - /** @var ParserData */ - protected $parserData; - - /** @var Subobject */ - protected $subobject; - - /** @var MessageFormatter */ - protected $messageFormatter; - - /** @var boolean */ - protected $firstElementAsProperty = false; - - /** - * @since 1.9 - * - * @param ParserData $parserData - * @param Subobject $subobject - * @param MessageFormatter $messageFormatter - */ - public function __construct( ParserData $parserData, Subobject $subobject, MessageFormatter $messageFormatter ) { - $this->parserData = $parserData; - $this->subobject = $subobject; - $this->messageFormatter = $messageFormatter; - } - - /** - * @since 1.9 - * - * @param boolean $firstElementAsProperty - * - * @return SubobjectParserFunction - */ - public function setFirstElementAsProperty( $firstElementAsProperty = true ) { - $this->firstElementAsProperty = (bool)$firstElementAsProperty; - return $this; - } - - /** - * @since 1.9 - * - * @param ArrayFormatter $params - * - * @return string|null - */ - public function parse( ArrayFormatter $parameters ) { - - $this->addDataValuesToSubobject( $parameters ); - - $this->parserData->getSemanticData()->addPropertyObjectValue( - $this->subobject->getProperty(), - $this->subobject->getContainer() - ); - - $this->parserData->updateOutput(); - - return $this->messageFormatter - ->addFromArray( $this->subobject->getErrors() ) - ->addFromArray( $this->parserData->getErrors() ) - ->addFromArray( $parameters->getErrors() ) - ->getHtml(); - } - - protected function addDataValuesToSubobject( ArrayFormatter $parameters ) { - - $subject = $this->parserData->getSemanticData()->getSubject(); - - $this->subobject->setEmptySemanticDataForId( $this->createSubobjectId( $parameters ) ); - - foreach ( $this->transformParametersToArray( $parameters ) as $property => $values ) { - - if ( $property === self::PARAM_SORTKEY ) { - $property = DIProperty::TYPE_SORTKEY; - } - - foreach ( $values as $value ) { - - $dataValue = DataValueFactory::getInstance()->newPropertyValue( - $property, - $value, - false, - $subject - ); - - $this->subobject->addDataValue( $dataValue ); - } - } - } - - protected function createSubobjectId( ArrayFormatter $parameters ) { - - $isAnonymous = in_array( $parameters->getFirst(), array( null, '' ,'-' ) ); - - $this->firstElementAsProperty = $this->firstElementAsProperty && !$isAnonymous; - - if ( $this->firstElementAsProperty || $isAnonymous ) { - return $this->subobject->generateId( new HashIdGenerator( $parameters->toArray(), '_' ) ); - } - - return $parameters->getFirst(); - } - - protected function transformParametersToArray( ArrayFormatter $parameters ) { - - if ( $this->firstElementAsProperty ) { - $parameters->addParameter( - $parameters->getFirst(), - $this->parserData->getTitle()->getPrefixedText() - ); - } - - return $parameters->toArray(); - } - -} diff --git a/SemanticMediaWiki/includes/query/SMW_Description.php b/SemanticMediaWiki/includes/query/SMW_Description.php deleted file mode 100644 index 35fb88b9..00000000 --- a/SemanticMediaWiki/includes/query/SMW_Description.php +++ /dev/null @@ -1,876 +0,0 @@ -<?php -/** - * This file contains basic classes for representing (query) descriptions in - * the SMW API. - * - * @file - * @ingroup SMWQuery - * - * @author Markus Krötzsch - */ - - -/** - * Abstract base class for all descriptions. - * @ingroup SMWQuery - */ -abstract class SMWDescription { - - /** - * @var SMWPrintRequest[] - */ - protected $m_printreqs = array(); - - /** - * Get the (possibly empty) array of all print requests that - * exist for the entities that fit this description. - * - * @return array of SMWPrintRequest - */ - public function getPrintRequests() { - return $this->m_printreqs; - } - - /** - * Set the array of print requests completely. - * - * @param SMWPrintRequest[] $printRequests - */ - public function setPrintRequests( array $printRequests ) { - $this->m_printreqs = $printRequests; - } - - /** - * Add a single SMWPrintRequest. - * - * @param SMWPrintRequest $printRequest - */ - public function addPrintRequest( SMWPrintRequest $printRequest ) { - $this->m_printreqs[] = $printRequest; - } - - /** - * Add a new print request, but at the beginning of the list of requests - * (thus it will be printed first). - * - * @param SMWPrintRequest $printRequest - */ - public function prependPrintRequest( SMWPrintRequest $printRequest ) { - array_unshift( $this->m_printreqs, $printRequest ); - } - - /** - * Return a string expressing this query. - * Some descriptions have different syntax in property value positions. The - * parameter $asvalue specifies whether the serialisation should take that into - * account. - * - * Example: The SMWValueDescription [[Paris]] returns the single result "Paris" - * but can also be used as value in [[has location::Paris]] which is preferred - * over the canonical [[has location::\<q\>[[Paris]]\</q\>]]. - * - * The result should be a plain query string that SMW is able to parse, - * without any kind of HTML escape sequences. - * - * @param boolean $asValue - * - * @return string - */ - abstract public function getQueryString( $asValue = false ); - - /** - * Return true if the description is required to encompass at most a single - * result, independently of the knowledge base. - * - * @return boolean - */ - abstract public function isSingleton(); - - /** - * Compute the size of the description. Default is 1. - * - * @return integer - */ - public function getSize() { - return 1; - } - - /** - * Compute the depth of the description. Default is 0. - * - * @return integer - */ - public function getDepth() { - return 0; - } - - /** - * Report on query features used in description. Return values are (sums of) - * query feature constants such as SMW_PROPERTY_QUERY. - */ - public function getQueryFeatures() { - return 0; - } - - /** - * Recursively restrict query to a maximal size and depth as given. - * Returns a possibly changed description that should be used as a replacement. - * Reduce values of parameters to account for the returned descriptions size. - * Default implementation for non-nested descriptions of size 1. - * The parameter $log contains a list of all pruned conditions, updated when some - * description was reduced. - * - * @note Objects must not do changes on $this during pruning, since $this can be - * reused in multiple places of one or many queries. Make new objects to reflect - * changes! - */ - public function prune( &$maxsize, &$maxDepth, &$log ) { - if ( ( $maxsize < $this->getSize() ) || ( $maxDepth < $this->getDepth() ) ) { - $log[] = $this->getQueryString(); - - $result = new SMWThingDescription(); - $result->setPrintRequests( $this->getPrintRequests() ); - - return $result; - } else { - // TODO: the below is not doing much? - $maxsize = $maxsize - $this->getSize(); - $maxDepth = $maxDepth - $this->getDepth(); - - return $this; - } - } - -} - -/** - * A dummy description that describes any object. Corresponds to - * owl:thing, the class of all abstract objects. Note that it is - * not used for datavalues of attributes in order to support type - * hinting in the API: descriptions of data are always - * SMWValueDescription objects. - * @ingroup SMWQuery - */ -class SMWThingDescription extends SMWDescription { - - public function getQueryString( $asValue = false ) { - return $asValue ? '+' : ''; - } - - public function isSingleton() { - return false; - } - - public function getSize() { - return 0; // no real condition, no size or depth - } - - public function prune( &$maxsize, &$maxdepth, &$log ) { - return $this; - } - -} - -/** - * Description of a single class as given by a wiki category, or of a - * disjunction of such classes. Corresponds to (disjunctions of) atomic classes - * in OWL and to (unions of) classes in RDF. - * @ingroup SMWQuery - */ -class SMWClassDescription extends SMWDescription { - - /** - * @var array of SMWDIWikiPage - */ - protected $m_diWikiPages; - - /** - * Constructor. - * - * @param mixed $content SMWDIWikiPage or array of SMWDIWikiPage - * - * @throws Exception - */ - public function __construct( $content ) { - if ( $content instanceof SMWDIWikiPage ) { - $this->m_diWikiPages = array( $content ); - } elseif ( is_array( $content ) ) { - $this->m_diWikiPages = $content; - } else { - throw new Exception( "SMWClassDescription::__construct(): parameter must be an SMWDIWikiPage object or an array of such objects." ); - } - } - - /** - * @param SMWClassDescription $description - */ - public function addDescription( SMWClassDescription $description ) { - $this->m_diWikiPages = array_merge( $this->m_diWikiPages, $description->getCategories() ); - } - - /** - * @return array of SMWDIWikiPage - */ - public function getCategories() { - return $this->m_diWikiPages; - } - - public function getQueryString( $asValue = false ) { - $first = true; - foreach ( $this->m_diWikiPages as $wikiPage ) { - $wikiValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $wikiPage, null ); - if ( $first ) { - $result = '[[' . $wikiValue->getPrefixedText(); - $first = false; - } else { - $result .= '||' . $wikiValue->getText(); - } - } - - $result .= ']]'; - - if ( $asValue ) { - return ' <q>' . $result . '</q> '; - } else { - return $result; - } - } - - public function isSingleton() { - return false; - } - - public function getSize() { - global $smwgQSubcategoryDepth; - - if ( $smwgQSubcategoryDepth > 0 ) { - return 1; // disj. of cats should not cause much effort if we compute cat-hierarchies anyway! - } else { - return count( $this->m_diWikiPages ); - } - } - - public function getQueryFeatures() { - if ( count( $this->m_diWikiPages ) > 1 ) { - return SMW_CATEGORY_QUERY | SMW_DISJUNCTION_QUERY; - } else { - return SMW_CATEGORY_QUERY; - } - } - - public function prune( &$maxsize, &$maxdepth, &$log ) { - if ( $maxsize >= $this->getSize() ) { - $maxsize = $maxsize - $this->getSize(); - return $this; - } elseif ( $maxsize <= 0 ) { - $log[] = $this->getQueryString(); - $result = new SMWThingDescription(); - } else { - $result = new SMWClassDescription( array_slice( $this->m_diWikiPages, 0, $maxsize ) ); - $rest = new SMWClassDescription( array_slice( $this->m_diWikiPages, $maxsize ) ); - - $log[] = $rest->getQueryString(); - $maxsize = 0; - } - - $result->setPrintRequests( $this->getPrintRequests() ); - return $result; - } - -} - - -/** - * Description of a single class as described by a concept page in the wiki. - * Corresponds to classes in (the EL fragment of) OWL DL, and to some extent to - * tree-shaped queries in SPARQL. - * @ingroup SMWQuery - */ -class SMWConceptDescription extends SMWDescription { - - /** - * @var SMWDIWikiPage - */ - protected $m_concept; - - /** - * Constructor. - * - * @param SMWDIWikiPage $concept - */ - public function __construct( SMWDIWikiPage $concept ) { - $this->m_concept = $concept; - } - - /** - * @return SMWDIWikiPage - */ - public function getConcept() { - return $this->m_concept; - } - - public function getQueryString( $asValue = false ) { - $pageValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $this->m_concept, null ); - $result = '[[' . $pageValue->getPrefixedText() . ']]'; - if ( $asValue ) { - return ' <q>' . $result . '</q> '; - } else { - return $result; - } - } - - public function isSingleton() { - return false; - } - - public function getQueryFeatures() { - return SMW_CONCEPT_QUERY; - } - - ///NOTE: getSize and getDepth /could/ query the store to find the real size - /// of the concept. But it is not clear if this is desirable anyway, given that - /// caching structures may be established for retrieving concepts more quickly. - /// Inspecting those would require future requests to the store, and be very - /// store specific. -} - - -/** - * Description of all pages within a given wiki namespace, given by a numerical - * constant. Corresponds to a class restriction with a special class that - * characterises the given namespace (or at least that is how one could map - * this to OWL etc.). - * @ingroup SMWQuery - */ -class SMWNamespaceDescription extends SMWDescription { - - /** - * @var integer - */ - protected $m_namespace; - - /** - * Constructor. - * - * @param integer $namespace The namespace index - */ - public function __construct( $namespace ) { - $this->m_namespace = $namespace; - } - - /** - * @return integer - */ - public function getNamespace() { - return $this->m_namespace; - } - - public function getQueryString( $asValue = false ) { - global $wgContLang; - - $prefix = $this->m_namespace == NS_CATEGORY ? ':' : ''; - - if ( $asValue ) { - return ' <q>[[' . $prefix . $wgContLang->getNSText( $this->m_namespace ) . ':+]]</q> '; - } else { - return '[[' . $prefix . $wgContLang->getNSText( $this->m_namespace ) . ':+]]'; - } - } - - public function isSingleton() { - return false; - } - - public function getQueryFeatures() { - return SMW_NAMESPACE_QUERY; - } - -} - -/** - * Description of one data value, or of a range of data values. - * - * Technically this usually corresponds to nominal predicates or to unary - * concrete domain predicates in OWL which are parametrised by one constant - * from the concrete domain. - * In RDF, concrete domain predicates that define ranges (like "greater or - * equal to") are not directly available. - * @ingroup SMWQuery - */ -class SMWValueDescription extends SMWDescription { - - /** - * @var SMWDataItem - */ - protected $m_dataItem; - - /** - * @var integer element in the SMW_CMP_ enum - */ - protected $m_comparator; - - /** - * @var null|SMWDIProperty - */ - protected $m_property; - - /** - * @param SMWDataItem $dataItem - * @param null|SMWDIProperty $property - * @param integer $comparator - */ - public function __construct( SMWDataItem $dataItem, SMWDIProperty $property = null, $comparator = SMW_CMP_EQ ) { - $this->m_dataItem = $dataItem; - $this->m_comparator = $comparator; - $this->m_property = $property; - } - - /** - * @deprecated Use getDataItem() and \SMW\DataValueFactory::getInstance()->newDataItemValue() if needed. Vanishes before SMW 1.7 - * @return SMWDataItem - */ - public function getDataValue() { - // FIXME: remove - return $this->m_dataItem; - } - - /** - * @return SMWDataItem - */ - public function getDataItem() { - return $this->m_dataItem; - } - - /** - * @return integer - */ - public function getComparator() { - return $this->m_comparator; - } - - /** - * @param bool $asValue - * - * @return string - */ - public function getQueryString( $asValue = false ) { - $comparator = SMWQueryLanguage::getStringForComparator( $this->m_comparator ); - $dataValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $this->m_dataItem, $this->m_property ); - - if ( $asValue ) { - return $comparator . $dataValue->getWikiValue(); - } else { // this only is possible for values of Type:Page - if ( $comparator === '' ) { // some extra care for Category: pages - return '[[:' . $dataValue->getWikiValue() . ']]'; - } else { - return '[[' . $comparator . $dataValue->getWikiValue() . ']]'; - } - } - } - - public function isSingleton() { - return $this->m_comparator == SMW_CMP_EQ; - } - - public function getSize() { - return 1; - } - -} - - -/** - * Description of a collection of many descriptions, all of which - * must be satisfied (AND, conjunction). - * - * Corresponds to conjunction in OWL and SPARQL. Not available in RDFS. - * @ingroup SMWQuery - */ -class SMWConjunction extends SMWDescription { - - /** - * @var SMWDescription[] - */ - protected $m_descriptions; - - public function __construct( array $descriptions = array() ) { - $this->m_descriptions = $descriptions; - } - - public function getDescriptions() { - return $this->m_descriptions; - } - - public function addDescription( SMWDescription $description ) { - if ( ! ( $description instanceof SMWThingDescription ) ) { - if ( $description instanceof SMWConjunction ) { // absorb sub-conjunctions - foreach ( $description->getDescriptions() as $subdesc ) { - $this->m_descriptions[] = $subdesc; - } - } else { - $this->m_descriptions[] = $description; - } - - // move print descriptions downwards - ///TODO: This may not be a good solution, since it does modify $description and since it does not react to future changes - $this->m_printreqs = array_merge( $this->m_printreqs, $description->getPrintRequests() ); - $description->setPrintRequests( array() ); - } - } - - public function getQueryString( $asvalue = false ) { - $result = ''; - - foreach ( $this->m_descriptions as $desc ) { - $result .= ( $result ? ' ' : '' ) . $desc->getQueryString( false ); - } - - if ( $result === '' ) { - return $asvalue ? '+' : ''; - } else { // <q> not needed for stand-alone conjunctions (AND binds stronger than OR) - return $asvalue ? " <q>{$result}</q> " : $result; - } - } - - public function isSingleton() { - foreach ( $this->m_descriptions as $d ) { - if ( $d->isSingleton() ) { - return true; - } - } - return false; - } - - public function getSize() { - $size = 0; - - foreach ( $this->m_descriptions as $desc ) { - $size += $desc->getSize(); - } - - return $size; - } - - public function getDepth() { - $depth = 0; - - foreach ( $this->m_descriptions as $desc ) { - $depth = max( $depth, $desc->getDepth() ); - } - - return $depth; - } - - public function getQueryFeatures() { - $result = SMW_CONJUNCTION_QUERY; - - foreach ( $this->m_descriptions as $desc ) { - $result = $result | $desc->getQueryFeatures(); - } - - return $result; - } - - public function prune( &$maxsize, &$maxdepth, &$log ) { - if ( $maxsize <= 0 ) { - $log[] = $this->getQueryString(); - return new SMWThingDescription(); - } - - $prunelog = array(); - $newdepth = $maxdepth; - $result = new SMWConjunction(); - - foreach ( $this->m_descriptions as $desc ) { - $restdepth = $maxdepth; - $result->addDescription( $desc->prune( $maxsize, $restdepth, $prunelog ) ); - $newdepth = min( $newdepth, $restdepth ); - } - - if ( count( $result->getDescriptions() ) > 0 ) { - $log = array_merge( $log, $prunelog ); - $maxdepth = $newdepth; - - if ( count( $result->getDescriptions() ) == 1 ) { // simplify unary conjunctions! - $descriptions = $result->getDescriptions(); - $result = array_shift( $descriptions ); - } - - $result->setPrintRequests( $this->getPrintRequests() ); - - return $result; - } else { - $log[] = $this->getQueryString(); - - $result = new SMWThingDescription(); - $result->setPrintRequests( $this->getPrintRequests() ); - - return $result; - } - } - -} - -/** - * Description of a collection of many descriptions, at least one of which - * must be satisfied (OR, disjunction). - * - * Corresponds to disjunction in OWL and SPARQL. Not available in RDFS. - * @ingroup SMWQuery - */ -class SMWDisjunction extends SMWDescription { - - /** - * @var SMWDescription[] - */ - protected $m_descriptions; - - /** - * @var null|SMWClassDescription - */ - protected $m_classdesc = null; // contains a single class description if any such disjunct was given; - // disjunctive classes are aggregated therein - - protected $m_true = false; // used if disjunction is trivially true already - - public function __construct( array $descriptions = array() ) { - foreach ( $descriptions as $desc ) { - $this->addDescription( $desc ); - } - } - - public function getDescriptions() { - return $this->m_descriptions; - } - - public function addDescription( SMWDescription $description ) { - if ( $description instanceof SMWThingDescription ) { - $this->m_true = true; - $this->m_descriptions = array(); // no conditions any more - $this->m_classdesc = null; - } - - if ( !$this->m_true ) { - if ( $description instanceof SMWClassDescription ) { // combine class descriptions - if ( is_null( $this->m_classdesc ) ) { // first class description - $this->m_classdesc = $description; - $this->m_descriptions[] = $description; - } else { - $this->m_classdesc->addDescription( $description ); - } - } elseif ( $description instanceof SMWDisjunction ) { // absorb sub-disjunctions - foreach ( $description->getDescriptions() as $subdesc ) { - $this->m_descriptions[] = $subdesc; - } - // } elseif ($description instanceof SMWSomeProperty) { - ///TODO: use subdisjunct. for multiple SMWSomeProperty descs with same property - } else { - $this->m_descriptions[] = $description; - } - } - - // move print descriptions downwards - ///TODO: This may not be a good solution, since it does modify $description and since it does not react to future cahges - $this->m_printreqs = array_merge( $this->m_printreqs, $description->getPrintRequests() ); - $description->setPrintRequests( array() ); - } - - public function getQueryString( $asValue = false ) { - if ( $this->m_true ) { - return '+'; - } - - $result = ''; - $sep = $asValue ? '||':' OR '; - - foreach ( $this->m_descriptions as $desc ) { - $subdesc = $desc->getQueryString( $asValue ); - - if ( $desc instanceof SMWSomeProperty ) { // enclose in <q> for parsing - if ( $asValue ) { - $subdesc = ' <q>[[' . $subdesc . ']]</q> '; - } else { - $subdesc = ' <q>' . $subdesc . '</q> '; - } - } - - $result .= ( $result ? $sep:'' ) . $subdesc; - } - if ( $asValue ) { - return $result; - } else { - return ' <q>' . $result . '</q> '; - } - } - - public function isSingleton() { - /// NOTE: this neglects the unimportant case where several disjuncts describe the same object. - if ( count( $this->m_descriptions ) != 1 ) { - return false; - } else { - return $this->m_descriptions[0]->isSingleton(); - } - } - - public function getSize() { - $size = 0; - - foreach ( $this->m_descriptions as $desc ) { - $size += $desc->getSize(); - } - - return $size; - } - - public function getDepth() { - $depth = 0; - - foreach ( $this->m_descriptions as $desc ) { - $depth = max( $depth, $desc->getDepth() ); - } - - return $depth; - } - - public function getQueryFeatures() { - $result = SMW_DISJUNCTION_QUERY; - - foreach ( $this->m_descriptions as $desc ) { - $result = $result | $desc->getQueryFeatures(); - } - - return $result; - } - - public function prune( &$maxsize, &$maxdepth, &$log ) { - if ( $maxsize <= 0 ) { - $log[] = $this->getQueryString(); - return new SMWThingDescription(); - } - - $prunelog = array(); - $newdepth = $maxdepth; - $result = new SMWDisjunction(); - - foreach ( $this->m_descriptions as $desc ) { - $restdepth = $maxdepth; - $result->addDescription( $desc->prune( $maxsize, $restdepth, $prunelog ) ); - $newdepth = min( $newdepth, $restdepth ); - } - - if ( count( $result->getDescriptions() ) > 0 ) { - $log = array_merge( $log, $prunelog ); - $maxdepth = $newdepth; - - if ( count( $result->getDescriptions() ) == 1 ) { // simplify unary disjunctions! - $descriptions = $result->getDescriptions(); - $result = array_shift( $descriptions ); - } - - $result->setPrintRequests( $this->getPrintRequests() ); - - return $result; - } else { - $log[] = $this->getQueryString(); - - $result = new SMWThingDescription(); - $result->setPrintRequests( $this->getPrintRequests() ); - - return $result; - } - } -} - -/** - * Description of a set of instances that have an attribute with some value - * that fits another (sub)description. - * - * Corresponds to existential quatification ("SomeValuesFrom" restriction) on - * properties in OWL. In conjunctive queries (OWL) and SPARQL (RDF), it is - * represented by using variables in the object part of such properties. - * @ingroup SMWQuery - */ -class SMWSomeProperty extends SMWDescription { - - /** - * @var SMWDescription - */ - protected $m_description; - - /** - * @var SMWDIProperty - */ - protected $m_property; - - public function __construct( SMWDIProperty $property, SMWDescription $description ) { - $this->m_property = $property; - $this->m_description = $description; - } - - /** - * @return SMWDIProperty - */ - public function getProperty() { - return $this->m_property; - } - - /** - * @return SMWDescription - */ - public function getDescription() { - return $this->m_description; - } - - public function getQueryString( $asValue = false ) { - $subdesc = $this->m_description; - $propertyChainString = $this->m_property->getLabel(); - $propertyname = $propertyChainString; - - while ( ( $propertyname !== '' ) && ( $subdesc instanceof SMWSomeProperty ) ) { // try to use property chain syntax - $propertyname = $subdesc->getProperty()->getLabel(); - - if ( $propertyname !== '' ) { - $propertyChainString .= '.' . $propertyname; - $subdesc = $subdesc->getDescription(); - } - } - - if ( $asValue ) { - return '<q>[[' . $propertyChainString . '::' . $subdesc->getQueryString( true ) . ']]</q>'; - } else { - return '[[' . $propertyChainString . '::' . $subdesc->getQueryString( true ) . ']]'; - } - } - - public function isSingleton() { - return false; - } - - public function getSize() { - return 1 + $this->getDescription()->getSize(); - } - - public function getDepth() { - return 1 + $this->getDescription()->getDepth(); - } - - public function getQueryFeatures() { - return SMW_PROPERTY_QUERY | $this->m_description->getQueryFeatures(); - } - - public function prune( &$maxsize, &$maxdepth, &$log ) { - if ( ( $maxsize <= 0 ) || ( $maxdepth <= 0 ) ) { - $log[] = $this->getQueryString(); - return new SMWThingDescription(); - } - - $maxsize--; - $maxdepth--; - - $result = new SMWSomeProperty( $this->m_property, $this->m_description->prune( $maxsize, $maxdepth, $log ) ); - $result->setPrintRequests( $this->getPrintRequests() ); - - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/query/SMW_PrintRequest.php b/SemanticMediaWiki/includes/query/SMW_PrintRequest.php deleted file mode 100644 index 56ea0ba9..00000000 --- a/SemanticMediaWiki/includes/query/SMW_PrintRequest.php +++ /dev/null @@ -1,275 +0,0 @@ -<?php -/** - * This file contains the class for defining "print requests", i.e. requests for output - * informatoin to be included in query results. - * - * @file - * @ingroup SMWQuery - * - * @author Markus Krötzsch - */ - -/** - * Container class for request for printout, as used in queries to - * obtain additional information for the retrieved results. - * - * @ingroup SMWQuery - */ -class SMWPrintRequest { - - /// Query mode to print all direct categories of the current element. - const PRINT_CATS = 0; - /// Query mode to print all property values of a certain attribute of the current element. - const PRINT_PROP = 1; - /// Query mode to print the current element (page in result set). - const PRINT_THIS = 2; - /// Query mode to print whether current element is in given category (Boolean printout). - const PRINT_CCAT = 3; - - protected $m_mode; // type of print request - protected $m_label; // string for labelling results, contains no markup - protected $m_data; // data entries specifyin gwhat was requested (mixed type) - protected $m_typeid = false; // id of the datatype of the printed objects, if applicable - protected $m_outputformat; // output format string for formatting results, if applicable - protected $m_hash = false; // cache your hash (currently useful since SMWQueryResult accesses the hash many times, might be dropped at some point) - protected $m_params = array(); - - /** - * Create a print request. - * @param integer $mode a constant defining what to printout - * @param string $label the string label to describe this printout - * @param mixed $data optional data for specifying some request, might be a property object, title, or something else; interpretation depends on $mode - * @param mixed $outputformat optional string for specifying an output format, e.g. an output unit - * @param array|null $params optional array of further, named parameters for the print request - */ - public function __construct( $mode, $label, $data = null, $outputformat = false, array $params = null ) { - if ( ( ( $mode == self::PRINT_CATS || $mode == self::PRINT_THIS ) && - !is_null( $data ) ) || - ( $mode == self::PRINT_PROP && - ( !( $data instanceof SMWPropertyValue ) || !$data->isValid() ) ) || - ( $mode == self::PRINT_CCAT && - !( $data instanceof Title ) ) ) { - throw new InvalidArgumentException( 'Data provided for print request does not fit the type of printout.' ); - } - - $this->m_mode = $mode; - $this->m_label = $label; - $this->m_data = $data; - $this->m_outputformat = $outputformat; - - if ( $mode == self::PRINT_CCAT && !$outputformat ) { - $this->m_outputformat = 'x'; // changed default for Boolean case - } - - if ( $this->m_data instanceof SMWDataValue ) { - // $this->m_data = clone $data; // we assume that the caller denotes the object ot us; else he needs provide us with a clone - $this->m_data->setCaption( $label ); - } - - if ( $params !== null ) { - $this->m_params = $params; - } - } - - public function getMode() { - return $this->m_mode; - } - - public function getLabel() { - return $this->m_label; - } - - /** - * Obtain an HTML-formatted representation of the label. - * The $linker is a Linker object used for generating hyperlinks. - * If it is NULL, no links will be created. - */ - public function getHTMLText( $linker = null ) { - if ( is_null( $linker ) || ( $this->m_label === '' ) ) { - return htmlspecialchars( $this->m_label ); - } - - switch ( $this->m_mode ) { - case self::PRINT_CATS: - return htmlspecialchars( $this->m_label ); // TODO: link to Special:Categories - case self::PRINT_CCAT: - return $linker->makeLinkObj( $this->m_data, htmlspecialchars( $this->m_label ) ); - case self::PRINT_PROP: - return $this->m_data->getShortHTMLText( $linker ); - case self::PRINT_THIS: default: return htmlspecialchars( $this->m_label ); - } - } - - /** - * Obtain a Wiki-formatted representation of the label. - */ - public function getWikiText( $linked = false ) { - if ( is_null( $linked ) || ( $linked === false ) || ( $this->m_label === '' ) ) { - return $this->m_label; - } else { - switch ( $this->m_mode ) { - case self::PRINT_CATS: - return $this->m_label; // TODO: link to Special:Categories - case self::PRINT_PROP: - return $this->m_data->getShortWikiText( $linked ); - case self::PRINT_CCAT: - return '[[:' . $this->m_data->getPrefixedText() . '|' . $this->m_label . ']]'; - case self::PRINT_THIS: default: - return $this->m_label; - } - } - } - - /** - * Convenience method for accessing the text in either HTML or Wiki format. - */ - public function getText( $outputmode, $linker = null ) { - switch ( $outputmode ) { - case SMW_OUTPUT_WIKI: return $this->getWikiText( $linker ); - case SMW_OUTPUT_HTML: case SMW_OUTPUT_FILE: default: return $this->getHTMLText( $linker ); - } - } - - /** - * Return additional data related to the print request. The result might be - * an object of class SMWPropertyValue or Title, or simply NULL if no data - * is required for the given type of printout. - */ - public function getData() { - return $this->m_data; - } - - public function getOutputFormat() { - return $this->m_outputformat; - } - - /** - * If this print request refers to some property, return the type id of this property. - * Otherwise return '_wpg' since all other types of print request return wiki pages. - * - * @return string - */ - public function getTypeID() { - if ( $this->m_typeid === false ) { - if ( $this->m_mode == self::PRINT_PROP ) { - $this->m_typeid = $this->m_data->getDataItem()->findPropertyTypeID(); - } else { - $this->m_typeid = '_wpg'; - } - } - - return $this->m_typeid; - } - - /** - * Return a hash string that is used to eliminate duplicate - * print requests. The hash also includes the chosen label, - * so it is possible to print the same date with different - * labels. - * - * @return string - */ - public function getHash() { - if ( $this->m_hash === false ) { - $this->m_hash = $this->m_mode . ':' . $this->m_label . ':'; - - if ( $this->m_data instanceof Title ) { - $this->m_hash .= $this->m_data->getPrefixedText() . ':'; - } elseif ( $this->m_data instanceof SMWDataValue ) { - $this->m_hash .= $this->m_data->getHash() . ':'; - } - - $this->m_hash .= $this->m_outputformat . ':' . implode( '|', $this->m_params ); - } - - return $this->m_hash; - } - - /** - * Serialise this object like print requests given in \#ask. - * @param $params boolean that sets if the serialization should - * include the extra print request parameters - */ - public function getSerialisation( $showparams = false ) { - $parameters = ''; - - if ( $showparams ) foreach ( $this->m_params as $key => $value ) { - $parameters .= "|+" . $key . "=" . $value; - } - - switch ( $this->m_mode ) { - case self::PRINT_CATS: - global $wgContLang; - $catlabel = $wgContLang->getNSText( NS_CATEGORY ); - $result = '?' . $catlabel; - if ( $this->m_label != $catlabel ) { - $result .= '=' . $this->m_label; - } - return $result . $parameters; - case self::PRINT_PROP: case self::PRINT_CCAT: - if ( $this->m_mode == self::PRINT_CCAT ) { - $printname = $this->m_data->getPrefixedText(); - $result = '?' . $printname; - - if ( $this->m_outputformat != 'x' ) { - $result .= '#' . $this->m_outputformat; - } - } else { - $printname = $this->m_data->getWikiValue(); - $result = '?' . $printname; - - if ( $this->m_outputformat !== '' ) { - $result .= '#' . $this->m_outputformat; - } - } - if ( $printname != $this->m_label ) { - $result .= '=' . $this->m_label; - } - return $result . $parameters; - case self::PRINT_THIS: - $result = '?'; - - if ( $this->m_label !== '' ) { - $result .= '=' . $this->m_label; - } - - if ( $this->m_outputformat !== '' ) { - $result .= '#' . $this->m_outputformat; - } - - return $result . $parameters; - default: return ''; // no current serialisation - } - } - - /** - * Returns the value of a named parameter. - * - * @param $key string the name of the parameter key - * - * @return string Value of the paramer, if set (else FALSE) - */ - public function getParameter( $key ) { - return array_key_exists( $key, $this->m_params ) ? $this->m_params[$key] : false; - } - - /** - * Returns the array of parameters, where a string is mapped to a string. - * - * @return array Map of parameter names to values. - */ - public function getParameters() { - return $this->m_params; - } - - /** - * Sets a print request parameter. - * - * @param $key string Name of the parameter - * @param $value string Value for the parameter - */ - public function setParameter( $key, $value ) { - $this->m_params[$key] = $value; - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/query/SMW_Query.php b/SemanticMediaWiki/includes/query/SMW_Query.php deleted file mode 100644 index a641d434..00000000 --- a/SemanticMediaWiki/includes/query/SMW_Query.php +++ /dev/null @@ -1,257 +0,0 @@ -<?php -/** - * This file contains the class for representing queries in SMW, each - * consisting of a query description and possible query parameters. - * @file - * @ingroup SMWQuery - * @author Markus Krötzsch - */ - -/** - * This group contains all parts of SMW that relate to processing semantic queries. - * SMW components that relate to plain storage access (for querying or otherwise) - * have their own group. - * @defgroup SMWQuery SMWQuery - * @ingroup SMW - */ - -/** - * Representation of queries in SMW, each consisting of a query - * description and various parameters. Some settings might also lead to - * changes in the query description. - * - * Most additional query parameters (limit, sort, ascending, ...) are - * interpreted as in SMWRequestOptions (though the latter contains some - * additional settings). - * @ingroup SMWQuery - */ -class SMWQuery { - - const MODE_INSTANCES = 1; // normal instance retrieval - const MODE_COUNT = 2; // find result count only - const MODE_DEBUG = 3; // prepare query, but show debug data instead of executing it - const MODE_NONE = 4; // do nothing with the query - - public $sort = false; - public $sortkeys = array(); // format: "Property key" => "ASC" / "DESC" (note: order of entries also matters) - public $querymode = SMWQuery::MODE_INSTANCES; - - protected $m_limit; - protected $m_offset = 0; - protected $m_description; - protected $m_errors = array(); // keep any errors that occurred so far - protected $m_querystring = false; // string (inline query) version (if fixed and known) - protected $m_inline; // query used inline? (required for finding right default parameters) - protected $m_concept; // query used in concept? (required for finding right default parameters) - - /** - * @var SMWPrintRequest[] - */ - protected $m_extraprintouts = array(); // SMWPrintoutRequest objects supplied outside querystring - protected $m_mainlabel = ''; // Since 1.6 - - /** - * Constructor. - * @param $description SMWDescription object describing the query conditions - * @param $inline bool stating whether this query runs in an inline context; used to determine - * proper default parameters (e.g. the default limit) - * @param $concept bool stating whether this query belongs to a concept; used to determine - * proper default parameters (concepts usually have less restrictions) - */ - public function __construct( $description = null, $inline = false, $concept = false ) { - global $smwgQMaxLimit, $smwgQMaxInlineLimit; - $this->m_limit = $inline ? $smwgQMaxInlineLimit : $smwgQMaxLimit; - $this->m_inline = $inline; - $this->m_concept = $concept; - $this->m_description = $description; - $this->applyRestrictions(); - } - - /** - * Sets the mainlabel. - * - * @since 1.6. - * - * @param string $mainlabel - */ - public function setMainLabel( $mainlabel ) { - $this->m_mainlabel = $mainlabel; - } - - /** - * Gets the mainlabel. - * - * @since 1.6. - * - * @return string - */ - public function getMainLabel() { - return $this->m_mainlabel; - } - - public function setDescription( SMWDescription $description ) { - $this->m_description = $description; - foreach ( $this->m_extraprintouts as $printout ) { - $this->m_description->addPrintRequest( $printout ); - } - $this->applyRestrictions(); - } - - public function getDescription() { - return $this->m_description; - } - - public function setExtraPrintouts( $extraprintouts ) { - $this->m_extraprintouts = $extraprintouts; - - if ( !is_null( $this->m_description ) ) { - foreach ( $extraprintouts as $printout ) { - $this->m_description->addPrintRequest( $printout ); - } - } - } - - /** - * @return SMWPrintRequest[] - */ - public function getExtraPrintouts() { - return $this->m_extraprintouts; - } - - public function getErrors() { - return $this->m_errors; - } - - public function addErrors( $errors ) { - $this->m_errors = array_merge( $this->m_errors, $errors ); - } - - public function setQueryString( $querystring ) { - $this->m_querystring = $querystring; - } - - public function getQueryString() { - if ( $this->m_querystring !== false ) { - return $this->m_querystring; - } elseif ( !is_null( $this->m_description ) ) { - return $this->m_description->getQueryString(); - } else { - return ''; - } - } - - public function getOffset() { - return $this->m_offset; - } - - /** - * Set an offset for the returned query results. No offset beyond the maximal query - * limit will be set, and the current query limit might be reduced in order to ensure - * that no results beyond the maximal limit are returned. - * The function returns the chosen offset. - * @todo The function should be extended to take into account whether or not we - * are in inline mode (not critical, since offsets are usually not applicable inline). - */ - public function setOffset( $offset ) { - global $smwgQMaxLimit; - $this->m_offset = min( $smwgQMaxLimit, $offset ); // select integer between 0 and maximal limit; - $this->m_limit = min( $smwgQMaxLimit - $this->m_offset, $this->m_limit ); // note that limit might become 0 here - return $this->m_offset; - } - - public function getLimit() { - return $this->m_limit; - } - - /** - * Set a limit for number of query results. The set limit might be restricted by the - * current offset so as to ensure that the number of the last considered result does not - * exceed the maximum amount of supported results. - * The function returns the chosen limit. - * @note It makes sense to have limit==0, e.g. to only show a link to the search special - */ - public function setLimit( $limit, $restrictinline = true ) { - global $smwgQMaxLimit, $smwgQMaxInlineLimit; - $maxlimit = ( $this->m_inline && $restrictinline ) ? $smwgQMaxInlineLimit : $smwgQMaxLimit; - $this->m_limit = min( $smwgQMaxLimit - $this->m_offset, $limit, $maxlimit ); - return $this->m_limit; - } - - /** - * @note Sets an unbound limit that is independent from GLOBAL settings - * - * @since 2.0 - * - * @param integer $limit - * - * @return Query - */ - public function setUnboundLimit( $limit ) { - $this->m_limit = (int)$limit; - return $this; - } - - /** - * Apply structural restrictions to the current description. - */ - public function applyRestrictions() { - global $smwgQMaxSize, $smwgQMaxDepth, $smwgQConceptMaxSize, $smwgQConceptMaxDepth; - - if ( !is_null( $this->m_description ) ) { - if ( $this->m_concept ) { - $maxsize = $smwgQConceptMaxSize; - $maxdepth = $smwgQConceptMaxDepth; - } else { - $maxsize = $smwgQMaxSize; - $maxdepth = $smwgQMaxDepth; - } - - $log = array(); - $this->m_description = $this->m_description->prune( $maxsize, $maxdepth, $log ); - - if ( count( $log ) > 0 ) { - $this->m_errors[] = wfMessage( - 'smw_querytoolarge', - str_replace( '[', '[', implode( ', ' , $log ) ) - )->inContentLanguage()->text(); - } - } - } - - /** - * Returns serialized query details - * - * The output is following the askargs api module convention - * - * conditions The query conditions (requirements for a subject to be included) - * printouts The query printouts (which properties to show per subject) - * parameters The query parameters (non-condition and non-printout arguments) - * - * @since 1.9 - * - * @return array - */ - public function toArray(){ - $serialized = array(); - - $serialized['conditions'] = $this->m_querystring; - - // This can be extended but for the current use cases that is - // sufficient since most printer related parameters have to be sourced - // in the result printer class - $serialized['parameters'] = array( - 'limit' => $this->m_limit, - 'offset' => $this->m_offset - ); - - foreach ( $this->m_extraprintouts as $printout ) { - $serialization = $printout->getSerialisation(); - if ( $serialization !== '?#' ) { - $serialized['printouts'][] = $serialization; - } - } - - return $serialized; - } - -} diff --git a/SemanticMediaWiki/includes/query/SMW_QueryLanguage.php b/SemanticMediaWiki/includes/query/SMW_QueryLanguage.php deleted file mode 100644 index 0bbcada6..00000000 --- a/SemanticMediaWiki/includes/query/SMW_QueryLanguage.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php - -/** - * Static class for functions related to the SMW query language. - * - * Note: the query language "definition" is located at various places in the SMW codebase. - * SMWQueryParser defines most of the actual query syntax. - * SMWDescription defines the semantic elements of the query language. - * This class is an attempt to gradualy migrate to having all the stuff at one location, - * clearly distinguised from non-language code. - * - * @since 1.5.3 - * - * @file SMW_QueryLanguage.php - * @ingroup SMW - * - * @author Jeroen De Dauw - */ -final class SMWQueryLanguage { - - /** - * Associative array that maps the comparator strings (keys) to - * the SMW_CMP_ enum (values). Call initializeComparators before using. - * - * @since 1.5.3 - * - * @var array - */ - protected static $comparators = array(); - - /** - * Gets an array with all suported comparator strings. - * The string for SMW_CMP_EQ, which is an empty string, is not in this list. - * - * @since 1.5.3 - * - * @return array - */ - public static function getComparatorStrings() { - self::initializeComparators(); - return array_keys( self::$comparators ); - } - - /** - * Gets the SMW_CMP_ for a string comparator, falling back to the - * $defaultComparator when none is found. - * - * @since 1.5.3 - * - * @param string $string - * @param integer $defaultComparator Item of the SMW_CMP_ enum - * - * @return integer Item of the SMW_CMP_ enum - */ - public static function getComparatorFromString( $string, $defaultComparator = SMW_CMP_EQ ) { - self::initializeComparators(); - if ( $string === '' ) return SMW_CMP_EQ; - return array_key_exists( $string, self::$comparators ) ? self::$comparators[$string] : $defaultComparator; - } - - /** - * Gets the comparator string for a comparator. - * - * @since 1.5.3 - * - * @param $comparator - * - * @return string - */ - public static function getStringForComparator( $comparator ) { - self::initializeComparators(); - static $reverseCache = false; - - if ( $reverseCache === false ) { - $reverseCache = array_flip( self::$comparators ); - } - - if ( $comparator == SMW_CMP_EQ ) { - return ''; - } elseif ( array_key_exists( $comparator, $reverseCache ) ) { - return $reverseCache[$comparator]; - } else { - throw new Exception( "Comparator $comparator does not have a string representatation" ); - } - } - - /** - * Initializes the $comparators field. - * - * @since 1.5.3 - */ - protected static function initializeComparators() { - global $smwgQComparators, $smwStrictComparators; - static $initialized = false; - - if ( $initialized ) { - return; - } - - $initialized = true; - - // Note: Comparators that contain other comparators at the beginning of the string need to be at beginning of the array. - $comparators = array( - '!~' => SMW_CMP_NLKE, - '<<' => SMW_CMP_LESS, - '>>' => SMW_CMP_GRTR, - '<' => $smwStrictComparators ? SMW_CMP_LESS : SMW_CMP_LEQ, - '>' => $smwStrictComparators ? SMW_CMP_GRTR : SMW_CMP_GEQ, - '≤' => SMW_CMP_LEQ, - '≥' => SMW_CMP_GEQ, - '!' => SMW_CMP_NEQ, - '~' => SMW_CMP_LIKE, - ); - - $allowedComparators = explode( '|', $smwgQComparators ); - - // Remove the comparators that are not allowed. - foreach ( $comparators as $string => $comparator ) { - if ( !in_array( $string, $allowedComparators ) ) { - unset( $comparators[$string] ); - } - } - - self::$comparators = $comparators; - } - -} diff --git a/SemanticMediaWiki/includes/query/SMW_QueryParser.php b/SemanticMediaWiki/includes/query/SMW_QueryParser.php deleted file mode 100644 index 2fdb2eb2..00000000 --- a/SemanticMediaWiki/includes/query/SMW_QueryParser.php +++ /dev/null @@ -1,663 +0,0 @@ -<?php -/** - * This file contains a class for parsing inline query strings. - * @file - * @ingroup SMWQuery - * @author Markus Krötzsch - */ - -/** - * Objects of this class are in charge of parsing a query string in order - * to create an SMWDescription. The class and methods are not static in order - * to more cleanly store the intermediate state and progress of the parser. - * @ingroup SMWQuery - */ -class SMWQueryParser { - - protected $m_sepstack; // list of open blocks ("parentheses") that need closing at current step - protected $m_curstring; // remaining string to be parsed (parsing eats query string from the front) - protected $m_errors; // empty array if all went right, array of strings otherwise - protected $m_defaultns; // description of the default namespace restriction, or NULL if not used - - protected $m_categoryprefix; // cache label of category namespace . ':' - protected $m_conceptprefix; // cache label of concept namespace . ':' - protected $m_categoryPrefixCannonical; // cache canonnical label of category namespace . ':' - protected $m_conceptPrefixCannonical; // cache canonnical label of concept namespace . ':' - protected $m_queryfeatures; // query features to be supported, format similar to $smwgQFeatures - - public function __construct( $queryFeatures = false ) { - global $wgContLang, $smwgQFeatures; - - $this->m_categoryprefix = $wgContLang->getNsText( NS_CATEGORY ) . ':'; - $this->m_conceptprefix = $wgContLang->getNsText( SMW_NS_CONCEPT ) . ':'; - $this->m_categoryPrefixCannonical = 'Category:'; - $this->m_conceptPrefixCannonical = 'Concept:'; - - $this->m_defaultns = null; - $this->m_queryfeatures = $queryFeatures === false ? $smwgQFeatures : $queryFeatures; - } - - /** - * Provide an array of namespace constants that are used as default restrictions. - * If NULL is given, no such default restrictions will be added (faster). - */ - public function setDefaultNamespaces( $namespaceArray ) { - $this->m_defaultns = null; - - if ( !is_null( $namespaceArray ) ) { - foreach ( $namespaceArray as $ns ) { - $this->m_defaultns = $this->addDescription( - $this->m_defaultns, - new SMWNamespaceDescription( $ns ), - false - ); - } - } - } - - /** - * Compute an SMWDescription from a query string. Returns whatever descriptions could be - * wrestled from the given string (the most general result being SMWThingDescription if - * no meaningful condition was extracted). - * - * @param string $queryString - * - * @return SMWDescription - */ - public function getQueryDescription( $queryString ) { - wfProfileIn( 'SMWQueryParser::getQueryDescription (SMW)' ); - - $this->m_errors = array(); - $this->m_curstring = $queryString; - $this->m_sepstack = array(); - $setNS = false; - $result = $this->getSubqueryDescription( $setNS ); - - if ( !$setNS ) { // add default namespaces if applicable - $result = $this->addDescription( $this->m_defaultns, $result ); - } - - if ( is_null( $result ) ) { // parsing went wrong, no default namespaces - $result = new SMWThingDescription(); - } - - wfProfileOut( 'SMWQueryParser::getQueryDescription (SMW)' ); - - return $result; - } - - /** - * Return array of error messages (possibly empty). - * - * @return array - */ - public function getErrors() { - return $this->m_errors; - } - - /** - * Return error message or empty string if no error occurred. - * - * @return string - */ - public function getErrorString() { - return smwfEncodeMessages( $this->m_errors ); - } - - /** - * Compute an SMWDescription for current part of a query, which should - * be a standalone query (the main query or a subquery enclosed within - * "\<q\>...\</q\>". Recursively calls similar methods and returns NULL upon error. - * - * The call-by-ref parameter $setNS is a boolean. Its input specifies whether - * the query should set the current default namespace if no namespace restrictions - * were given. If false, the calling super-query is happy to set the required - * NS-restrictions by itself if needed. Otherwise the subquery has to impose the defaults. - * This is so, since outermost queries and subqueries of disjunctions will have to set - * their own default restrictions. - * - * The return value of $setNS specifies whether or not the subquery has a namespace - * specification in place. This might happen automatically if the query string imposes - * such restrictions. The return value is important for those callers that otherwise - * set up their own restrictions. - * - * Note that $setNS is no means to switch on or off default namespaces in general, - * but just controls query generation. For general effect, the default namespaces - * should be set to NULL. - * - * @return SMWDescription or null - */ - protected function getSubqueryDescription( &$setNS ) { - $conjunction = null; // used for the current inner conjunction - $disjuncts = array(); // (disjunctive) array of subquery conjunctions - $hasNamespaces = false; // does the current $conjnuction have its own namespace restrictions? - $mustSetNS = $setNS; // must NS restrictions be set? (may become true even if $setNS is false) - - $continue = ( $chunk = $this->readChunk() ) !== ''; // skip empty subquery completely, thorwing an error - - while ( $continue ) { - $setsubNS = false; - - switch ( $chunk ) { - case '[[': // start new link block - $ld = $this->getLinkDescription( $setsubNS ); - - if ( !is_null( $ld ) ) { - $conjunction = $this->addDescription( $conjunction, $ld ); - } - break; - case '<q>': // enter new subquery, currently irrelevant but possible - $this->pushDelimiter( '</q>' ); - $conjunction = $this->addDescription( $conjunction, $this->getSubqueryDescription( $setsubNS ) ); - break; - case 'OR': - case '||': - case '': - case '</q>': // finish disjunction and maybe subquery - if ( !is_null( $this->m_defaultns ) ) { // possibly add namespace restrictions - if ( $hasNamespaces && !$mustSetNS ) { - // add NS restrictions to all earlier conjunctions (all of which did not have them yet) - $mustSetNS = true; // enforce NS restrictions from now on - $newdisjuncts = array(); - - foreach ( $disjuncts as $conj ) { - $newdisjuncts[] = $this->addDescription( $conj, $this->m_defaultns ); - } - - $disjuncts = $newdisjuncts; - } elseif ( !$hasNamespaces && $mustSetNS ) { - // add ns restriction to current result - $conjunction = $this->addDescription( $conjunction, $this->m_defaultns ); - } - } - - $disjuncts[] = $conjunction; - // start anew - $conjunction = null; - $hasNamespaces = false; - - // finish subquery? - if ( $chunk == '</q>' ) { - if ( $this->popDelimiter( '</q>' ) ) { - $continue = false; // leave the loop - } else { - $this->m_errors[] = wfMessage( - 'smw_toomanyclosing', - $chunk - )->inContentLanguage()->text(); - return null; - } - } elseif ( $chunk === '' ) { - $continue = false; - } - break; - case '+': // "... AND true" (ignore) - break; - default: // error: unexpected $chunk - $this->m_errors[] = wfMessage( - 'smw_unexpectedpart', - $chunk - )->inContentLanguage()->text(); - // return null; // Try to go on, it can only get better ... - } - - if ( $setsubNS ) { // namespace restrictions encountered in current conjunct - $hasNamespaces = true; - } - - if ( $continue ) { // read on only if $continue remained true - $chunk = $this->readChunk(); - } - } - - if ( count( $disjuncts ) > 0 ) { // make disjunctive result - $result = null; - - foreach ( $disjuncts as $d ) { - if ( is_null( $d ) ) { - $this->m_errors[] = wfMessage( 'smw_emptysubquery' )->inContentLanguage()->text(); - $setNS = false; - return null; - } else { - $result = $this->addDescription( $result, $d, false ); - } - } - } else { - $this->m_errors[] = wfMessage( 'smw_emptysubquery' )->inContentLanguage()->text(); - $setNS = false; - return null; - } - - $setNS = $mustSetNS; // NOTE: also false if namespaces were given but no default NS descs are available - - return $result; - } - - /** - * Compute an SMWDescription for current part of a query, which should - * be the content of "[[ ... ]]". Returns NULL upon error. - * - * Parameters $setNS has the same use as in getSubqueryDescription(). - */ - protected function getLinkDescription( &$setNS ) { - // This method is called when we encountered an opening '[['. The following - // block could be a Category-statement, fixed object, or property statement. - $chunk = $this->readChunk( '', true, false ); // NOTE: untrimmed, initial " " escapes prop. chains - - if ( in_array( smwfNormalTitleText( $chunk ), - array( $this->m_categoryprefix, $this->m_conceptprefix, $this->m_categoryPrefixCannonical, $this->m_conceptPrefixCannonical ) ) ) { - return $this->getClassDescription( $setNS, ( - smwfNormalTitleText( $chunk ) == $this->m_categoryprefix || smwfNormalTitleText( $chunk ) == $this->m_categoryPrefixCannonical - ) ); - } else { // fixed subject, namespace restriction, property query, or subquery - $sep = $this->readChunk( '', false ); // do not consume hit, "look ahead" - - if ( ( $sep == '::' ) || ( $sep == ':=' ) ) { - if ( $chunk{0} != ':' ) { // property statement - return $this->getPropertyDescription( $chunk, $setNS ); - } else { // escaped article description, read part after :: to get full contents - $chunk .= $this->readChunk( '\[\[|\]\]|\|\||\|' ); - return $this->getArticleDescription( trim( $chunk ), $setNS ); - } - } else { // Fixed article/namespace restriction. $sep should be ]] or || - return $this->getArticleDescription( trim( $chunk ), $setNS ); - } - } - } - - /** - * Parse a category description (the part of an inline query that - * is in between "[[Category:" and the closing "]]" and create a - * suitable description. - */ - protected function getClassDescription( &$setNS, $category = true ) { - // note: no subqueries allowed here, inline disjunction allowed, wildcards allowed - $result = null; - $continue = true; - - while ( $continue ) { - $chunk = $this->readChunk(); - - if ( $chunk == '+' ) { - // wildcard, ignore for categories (semantically meaningless, everything is in some class) - } else { // assume category/concept title - /// NOTE: we add m_c...prefix to prevent problems with, e.g., [[Category:Template:Test]] - $title = Title::newFromText( ( $category ? $this->m_categoryprefix : $this->m_conceptprefix ) . $chunk ); - - if ( !is_null( $title ) ) { - $diWikiPage = new SMWDIWikiPage( $title->getDBkey(), $title->getNameSpace(), '' ); - $desc = $category ? new SMWClassDescription( $diWikiPage ) : new SMWConceptDescription( $diWikiPage ); - $result = $this->addDescription( $result, $desc, false ); - } - } - - $chunk = $this->readChunk(); - $continue = ( $chunk == '||' ) && $category; // disjunctions only for cateories - } - - return $this->finishLinkDescription( $chunk, false, $result, $setNS ); - } - - /** - * Parse a property description (the part of an inline query that - * is in between "[[Some property::" and the closing "]]" and create a - * suitable description. The "::" is the first chunk on the current - * string. - */ - protected function getPropertyDescription( $propertyName, &$setNS ) { - $this->readChunk(); // consume separator ":=" or "::" - - // first process property chain syntax (e.g. "property1.property2::value"), escaped by initial " ": - $propertynames = ( $propertyName{0} == ' ' ) ? array( $propertyName ) : explode( '.', $propertyName ); - $properties = array(); - $typeid = '_wpg'; - $inverse = false; - - foreach ( $propertynames as $name ) { - if ( $typeid !== '_wpg' && $typeid !== '__sob' ) { // non-final property in chain was no wikipage: not allowed - $this->m_errors[] = wfMessage( - 'smw_valuesubquery', - $name - )->inContentLanguage()->text(); - return null; ///TODO: read some more chunks and try to finish [[ ]] - } - - $property = SMWPropertyValue::makeUserProperty( $name ); - - if ( !$property->isValid() ) { // illegal property identifier - $this->m_errors = array_merge( $this->m_errors, $property->getErrors() ); - return null; ///TODO: read some more chunks and try to finish [[ ]] - } - - $typeid = $property->getDataItem()->findPropertyTypeID(); - $inverse = $property->isInverse(); - $properties[] = $property; - } ///NOTE: after iteration, $property and $typeid correspond to last value - - $innerdesc = null; - $continue = true; - - while ( $continue ) { - $chunk = $this->readChunk(); - - switch ( $chunk ) { - case '+': // wildcard, add namespaces for page-type properties - if ( !is_null( $this->m_defaultns ) && ( ( $typeid == '_wpg' ) || $inverse ) ) { - $innerdesc = $this->addDescription( $innerdesc, $this->m_defaultns, false ); - } else { - $innerdesc = $this->addDescription( $innerdesc, new SMWThingDescription(), false ); - } - $chunk = $this->readChunk(); - break; - case '<q>': // subquery, set default namespaces - if ( ( $typeid == '_wpg' ) || $inverse ) { - $this->pushDelimiter( '</q>' ); - $setsubNS = true; - $innerdesc = $this->addDescription( $innerdesc, $this->getSubqueryDescription( $setsubNS ), false ); - } else { // no subqueries allowed for non-pages - $this->m_errors[] = wfMessage( - 'smw_valuesubquery', - end( $propertynames ) - )->inContentLanguage()->text(); - $innerdesc = $this->addDescription( $innerdesc, new SMWThingDescription(), false ); - } - $chunk = $this->readChunk(); - break; - default: // normal object value - // read value(s), possibly with inner [[...]] - $open = 1; - $value = $chunk; - $continue2 = true; - // read value with inner [[, ]], || - while ( ( $open > 0 ) && ( $continue2 ) ) { - $chunk = $this->readChunk( '\[\[|\]\]|\|\||\|' ); - switch ( $chunk ) { - case '[[': // open new [[ ]] - $open++; - break; - case ']]': // close [[ ]] - $open--; - break; - case '|': - case '||': // terminates only outermost [[ ]] - if ( $open == 1 ) { - $open = 0; - } - break; - case '': ///TODO: report error; this is not good right now - $continue2 = false; - break; - } - if ( $open != 0 ) { - $value .= $chunk; - } - } ///NOTE: at this point, we normally already read one more chunk behind the value - - $dv = \SMW\DataValueFactory::getInstance()->newPropertyObjectValue( $property->getDataItem() ); - $vd = $dv->getQueryDescription( $value ); - $innerdesc = $this->addDescription( $innerdesc, $vd, false ); - $this->m_errors = $this->m_errors + $dv->getErrors(); - } - $continue = ( $chunk == '||' ); - } - - if ( is_null( $innerdesc ) ) { // make a wildcard search - $innerdesc = ( !is_null( $this->m_defaultns ) && ( $typeid == '_wpg' ) ) ? - $this->addDescription( $innerdesc, $this->m_defaultns, false ) : - $this->addDescription( $innerdesc, new SMWThingDescription(), false ); - $this->m_errors[] = wfMessage( - 'smw_propvalueproblem', - $property->getWikiValue() - )->inContentLanguage()->text(); - } - - $properties = array_reverse( $properties ); - - foreach ( $properties as $property ) { - $innerdesc = new SMWSomeProperty( $property->getDataItem(), $innerdesc ); - } - - $result = $innerdesc; - - return $this->finishLinkDescription( $chunk, false, $result, $setNS ); - } - - /** - * Parse an article description (the part of an inline query that - * is in between "[[" and the closing "]]" assuming it is not specifying - * a category or property) and create a suitable description. - * The first chunk behind the "[[" has already been read and is - * passed as a parameter. - */ - protected function getArticleDescription( $firstChunk, &$setNS ) { - $chunk = $firstChunk; - $result = null; - $continue = true; - - while ( $continue ) { - if ( $chunk == '<q>' ) { // no subqueries of the form [[<q>...</q>]] (not needed) - $this->m_errors[] = wfMessage( 'smw_misplacedsubquery' )->inContentLanguage()->text(); - return null; - } - - $list = preg_split( '/:/', $chunk, 3 ); // ":Category:Foo" "User:bar" ":baz" ":+" - - if ( ( $list[0] === '' ) && ( count( $list ) == 3 ) ) { - $list = array_slice( $list, 1 ); - } - if ( ( count( $list ) == 2 ) && ( $list[1] == '+' ) ) { // try namespace restriction - global $wgContLang; - - $idx = $wgContLang->getNsIndex( str_replace( ' ', '_', $list[0] ) ); - - if ( $idx !== false ) { - $result = $this->addDescription( $result, new SMWNamespaceDescription( $idx ), false ); - } - } else { - $value = \SMW\DataValueFactory::getInstance()->newTypeIDValue( '_wpg', $chunk ); - if ( $value->isValid() ) { - $result = $this->addDescription( $result, new SMWValueDescription( $value->getDataItem(), null ), false ); - } - } - - $chunk = $this->readChunk( '\[\[|\]\]|\|\||\|' ); - - if ( $chunk == '||' ) { - $chunk = $this->readChunk( '\[\[|\]\]|\|\||\|' ); - $continue = true; - } else { - $continue = false; - } - } - - return $this->finishLinkDescription( $chunk, true, $result, $setNS ); - } - - protected function finishLinkDescription( $chunk, $hasNamespaces, $result, &$setNS ) { - if ( is_null( $result ) ) { // no useful information or concrete error found - $this->m_errors[] = wfMessage( 'smw_badqueryatom' )->inContentLanguage()->text(); - } elseif ( !$hasNamespaces && $setNS && !is_null( $this->m_defaultns ) ) { - $result = $this->addDescription( $result, $this->m_defaultns ); - $hasNamespaces = true; - } - - $setNS = $hasNamespaces; - - if ( $chunk == '|' ) { // skip content after single |, but report a warning - // Note: Using "|label" in query atoms used to be a way to set the mainlabel in SMW <1.0; no longer supported now - $chunk = $this->readChunk( '\]\]' ); - $labelpart = '|'; - if ( $chunk != ']]' ) { - $labelpart .= $chunk; - $chunk = $this->readChunk( '\]\]' ); - } - $this->m_errors[] = wfMessage( - 'smw_unexpectedpart', - $labelpart - )->inContentLanguage()->escaped(); - } - - if ( $chunk != ']]' ) { - // What happended? We found some chunk that could not be processed as - // link content (as in [[Category:Test<q>]]), or the closing ]] are - // just missing entirely. - if ( $chunk !== '' ) { - $this->m_errors[] = wfMessage( - 'smw_misplacedsymbol', - $chunk - )->inContentLanguage()->escaped(); - - // try to find a later closing ]] to finish this misshaped subpart - $chunk = $this->readChunk( '\]\]' ); - - if ( $chunk != ']]' ) { - $chunk = $this->readChunk( '\]\]' ); - } - } - if ( $chunk === '' ) { - $this->m_errors[] = wfMessage( 'smw_noclosingbrackets' )->inContentLanguage()->text(); - } - } - - return $result; - } - - /** - * Get the next unstructured string chunk from the query string. - * Chunks are delimited by any of the special strings used in inline queries - * (such as [[, ]], <q>, ...). If the string starts with such a delimiter, - * this delimiter is returned. Otherwise the first string in front of such a - * delimiter is returned. - * Trailing and initial spaces are ignored if $trim is true, and chunks - * consisting only of spaces are not returned. - * If there is no more qurey string left to process, the empty string is - * returned (and in no other case). - * - * The stoppattern can be used to customise the matching, especially in order to - * overread certain special symbols. - * - * $consume specifies whether the returned chunk should be removed from the - * query string. - */ - protected function readChunk( $stoppattern = '', $consume = true, $trim = true ) { - if ( $stoppattern === '' ) { - $stoppattern = '\[\[|\]\]|::|:=|<q>|<\/q>' . - '|^' . $this->m_categoryprefix . '|^' . $this->m_categoryPrefixCannonical . - '|^' . $this->m_conceptprefix . '|^' . $this->m_conceptPrefixCannonical . - '|\|\||\|'; - } - $chunks = preg_split( '/[\s]*(' . $stoppattern . ')/iu', $this->m_curstring, 2, PREG_SPLIT_DELIM_CAPTURE ); - if ( count( $chunks ) == 1 ) { // no matches anymore, strip spaces and finish - if ( $consume ) { - $this->m_curstring = ''; - } - - return $trim ? trim( $chunks[0] ) : $chunks[0]; - } elseif ( count( $chunks ) == 3 ) { // this should generally happen if count is not 1 - if ( $chunks[0] === '' ) { // string started with delimiter - if ( $consume ) { - $this->m_curstring = $chunks[2]; - } - - return $trim ? trim( $chunks[1] ) : $chunks[1]; - } else { - if ( $consume ) { - $this->m_curstring = $chunks[1] . $chunks[2]; - } - - return $trim ? trim( $chunks[0] ) : $chunks[0]; - } - } else { - return false; - } // should never happen - } - - /** - * Enter a new subblock in the query, which must at some time be terminated by the - * given $endstring delimiter calling popDelimiter(); - */ - protected function pushDelimiter( $endstring ) { - array_push( $this->m_sepstack, $endstring ); - } - - /** - * Exit a subblock in the query ending with the given delimiter. - * If the delimiter does not match the top-most open block, false - * will be returned. Otherwise return true. - */ - protected function popDelimiter( $endstring ) { - $topdelim = array_pop( $this->m_sepstack ); - return ( $topdelim == $endstring ); - } - - /** - * Extend a given description by a new one, either by adding the new description - * (if the old one is a container description) or by creating a new container. - * The parameter $conjunction determines whether the combination of both descriptions - * should be a disjunction or conjunction. - * - * In the special case that the current description is NULL, the new one will just - * replace the current one. - * - * The return value is the expected combined description. The object $curdesc will - * also be changed (if it was non-NULL). - */ - protected function addDescription( $curdesc, $newdesc, $conjunction = true ) { - $notallowedmessage = 'smw_noqueryfeature'; - if ( $newdesc instanceof SMWSomeProperty ) { - $allowed = $this->m_queryfeatures & SMW_PROPERTY_QUERY; - } elseif ( $newdesc instanceof SMWClassDescription ) { - $allowed = $this->m_queryfeatures & SMW_CATEGORY_QUERY; - } elseif ( $newdesc instanceof SMWConceptDescription ) { - $allowed = $this->m_queryfeatures & SMW_CONCEPT_QUERY; - } elseif ( $newdesc instanceof SMWConjunction ) { - $allowed = $this->m_queryfeatures & SMW_CONJUNCTION_QUERY; - $notallowedmessage = 'smw_noconjunctions'; - } elseif ( $newdesc instanceof SMWDisjunction ) { - $allowed = $this->m_queryfeatures & SMW_DISJUNCTION_QUERY; - $notallowedmessage = 'smw_nodisjunctions'; - } else { - $allowed = true; - } - - if ( !$allowed ) { - $this->m_errors[] = wfMessage( - $notallowedmessage, - str_replace( '[', '[', $newdesc->getQueryString() ) - )->inContentLanguage()->text(); - return $curdesc; - } - - if ( is_null( $newdesc ) ) { - return $curdesc; - } elseif ( is_null( $curdesc ) ) { - return $newdesc; - } else { // we already found descriptions - if ( ( ( $conjunction ) && ( $curdesc instanceof SMWConjunction ) ) || - ( ( !$conjunction ) && ( $curdesc instanceof SMWDisjunction ) ) ) { // use existing container - $curdesc->addDescription( $newdesc ); - return $curdesc; - } elseif ( $conjunction ) { // make new conjunction - if ( $this->m_queryfeatures & SMW_CONJUNCTION_QUERY ) { - return new SMWConjunction( array( $curdesc, $newdesc ) ); - } else { - $this->m_errors[] = wfMessage( - 'smw_noconjunctions', - str_replace( '[', '[', $newdesc->getQueryString() ) - )->inContentLanguage()->text(); - return $curdesc; - } - } else { // make new disjunction - if ( $this->m_queryfeatures & SMW_DISJUNCTION_QUERY ) { - return new SMWDisjunction( array( $curdesc, $newdesc ) ); - } else { - $this->m_errors[] = wfMessage( - 'smw_nodisjunctions', - str_replace( '[', '[', $newdesc->getQueryString() ) - )->inContentLanguage()->text(); - return $curdesc; - } - } - } - } -} diff --git a/SemanticMediaWiki/includes/query/SMW_QueryProcessor.php b/SemanticMediaWiki/includes/query/SMW_QueryProcessor.php deleted file mode 100644 index c3e218ae..00000000 --- a/SemanticMediaWiki/includes/query/SMW_QueryProcessor.php +++ /dev/null @@ -1,703 +0,0 @@ -<?php - -use ParamProcessor\Processor; -use ParamProcessor\Options; -use ParamProcessor\ParamDefinition; - -/** - * This file contains a static class for accessing functions to generate and execute - * semantic queries and to serialise their results. - * - * @file - * @ingroup SMWQuery - * @author Markus Krötzsch - */ - -/** - * Static class for accessing functions to generate and execute semantic queries - * and to serialise their results. - * @ingroup SMWQuery - */ -class SMWQueryProcessor { - - // "query contexts" define restrictions during query parsing and - // are used to preconfigure query (e.g. special pages show no further - // results link): - const SPECIAL_PAGE = 0; // query for special page - const INLINE_QUERY = 1; // query for inline use - const CONCEPT_DESC = 2; // query for concept definition - - /** - * Takes an array of unprocessed parameters, processes them using - * Validator, and returns them. - * - * Both input and output arrays are - * param name (string) => param value (mixed) - * - * @since 1.6.2 - * The return value changed in SMW 1.8 from an array with result values - * to an array with IParam objects. - * - * @param array $params - * @param array $printRequests - * @param boolean $unknownInvalid - * - * @return IParam[] - */ - public static function getProcessedParams( array $params, array $printRequests = array(), $unknownInvalid = true ) { - $validator = self::getValidatorForParams( $params, $printRequests, $unknownInvalid ); - $validator->processParameters(); - return $validator->getParameters(); - } - - /** - * Takes an array of unprocessed parameters, - * and sets them on a new Validator object, - * which is returned and ready to process the parameters. - * - * @since 1.8 - * - * @param array $params - * @param array $printRequests - * @param boolean $unknownInvalid - * - * @return Processor - */ - public static function getValidatorForParams( array $params, array $printRequests = array(), $unknownInvalid = true ) { - $paramDefinitions = self::getParameters(); - - $paramDefinitions['format']->setPrintRequests( $printRequests ); - - $processorOptions = new Options(); - $processorOptions->setUnknownInvalid( $unknownInvalid ); - - $validator = Processor::newFromOptions( $processorOptions ); - - $validator->setParameters( $params, $paramDefinitions, false ); - - return $validator; - } - - /** - * Parse a query string given in SMW's query language to create - * an SMWQuery. Parameters are given as key-value-pairs in the - * given array. The parameter $context defines in what context the - * query is used, which affects ceretain general settings. - * An object of type SMWQuery is returned. - * - * The format string is used to specify the output format if already - * known. Otherwise it will be determined from the parameters when - * needed. This parameter is just for optimisation in a common case. - * - * @param string $queryString - * @param array $params These need to be the result of a list fed to getProcessedParams - * @param $context - * @param string $format - * @param array $extraPrintouts - * - * @return SMWQuery - */ - static public function createQuery( $queryString, array $params, $context = self::INLINE_QUERY, $format = '', array $extraPrintouts = array() ) { - global $smwgQDefaultNamespaces, $smwgQFeatures, $smwgQConceptFeatures; - - // parse query: - $queryfeatures = ( $context == self::CONCEPT_DESC ) ? $smwgQConceptFeatures : $smwgQFeatures; - $qp = new SMWQueryParser( $queryfeatures ); - $qp->setDefaultNamespaces( $smwgQDefaultNamespaces ); - $desc = $qp->getQueryDescription( $queryString ); - - if ( $format === '' || is_null( $format ) ) { - $format = $params['format']->getValue(); - } - - if ( $format == 'count' ) { - $querymode = SMWQuery::MODE_COUNT; - } elseif ( $format == 'debug' ) { - $querymode = SMWQuery::MODE_DEBUG; - } else { - $printer = self::getResultPrinter( $format, $context ); - $querymode = $printer->getQueryMode( $context ); - } - - $query = new SMWQuery( $desc, ( $context != self::SPECIAL_PAGE ), ( $context == self::CONCEPT_DESC ) ); - $query->setQueryString( $queryString ); - $query->setExtraPrintouts( $extraPrintouts ); - $query->setMainLabel( $params['mainlabel']->getValue() ); - $query->addErrors( $qp->getErrors() ); // keep parsing errors for later output - - // set mode, limit, and offset: - $query->querymode = $querymode; - if ( ( array_key_exists( 'offset', $params ) ) && ( is_int( $params['offset']->getValue() + 0 ) ) ) { - $query->setOffset( max( 0, trim( $params['offset']->getValue() ) + 0 ) ); - } - - if ( $query->querymode == SMWQuery::MODE_COUNT ) { // largest possible limit for "count", even inline - global $smwgQMaxLimit; - $query->setOffset( 0 ); - $query->setLimit( $smwgQMaxLimit, false ); - } else { - if ( ( array_key_exists( 'limit', $params ) ) && ( is_int( trim( $params['limit']->getValue() ) + 0 ) ) ) { - $query->setLimit( max( 0, trim( $params['limit']->getValue() ) + 0 ) ); - if ( ( trim( $params['limit']->getValue() ) + 0 ) < 0 ) { // limit < 0: always show further results link only - $query->querymode = SMWQuery::MODE_NONE; - } - } else { - global $smwgQDefaultLimit; - $query->setLimit( $smwgQDefaultLimit ); - } - } - - $defaultSort = $format === 'rss' ? 'DESC' : 'ASC'; - $sort = self::getSortKeys( $params['sort']->getValue(), $params['order']->getValue(), $defaultSort ); - - $query->sortkeys = $sort['keys']; - $query->addErrors( $sort['errors'] ); - $query->sort = count( $query->sortkeys ) > 0; // TODO: Why would we do this here? - - return $query; - } - - /** - * Takes the sort and order parameters and returns a list of sort keys and a list of errors. - * - * @since 1.7 - * - * @param array $sortParam - * @param array $orders - * @param string $defaultSort - * - * @return array ( keys => array(), errors => array() ) - */ - protected static function getSortKeys( array $sortParam, array $orderParam, $defaultSort ) { - $orders = array(); - $sortKeys = array(); - $sortErros = array(); - - foreach ( $orderParam as $key => $order ) { - $order = strtolower( trim( $order ) ); - if ( ( $order == 'descending' ) || ( $order == 'reverse' ) || ( $order == 'desc' ) ) { - $orders[$key] = 'DESC'; - } elseif ( ( $order == 'random' ) || ( $order == 'rand' ) ) { - $orders[$key] = 'RANDOM'; - } else { - $orders[$key] = 'ASC'; - } - } - - foreach ( $sortParam as $sort ) { - $sortKey = false; - - // An empty string indicates we mean the page, such as element 0 on the next line. - // sort=,Some property - if ( trim( $sort ) === '' ) { - $sortKey = ''; - } - else { - $propertyValue = SMWPropertyValue::makeUserProperty( trim( $sort ) ); - - if ( $propertyValue->isValid() ) { - $sortKey = $propertyValue->getDataItem()->getKey(); - } else { - $sortErros = array_merge( $sortErros, $propertyValue->getErrors() ); - } - } - - if ( $sortKey !== false ) { - $order = empty( $orders ) ? $defaultSort : array_shift( $orders ); - $sortKeys[$sortKey] = $order; - } - } - - // If more sort arguments are provided then properties, assume the first one is for the page. - // TODO: we might want to add errors if there is more then one. - if ( !array_key_exists( '', $sortKeys ) && !empty( $orders ) ) { - $sortKeys[''] = array_shift( $orders ); - } - - return array( 'keys' => $sortKeys, 'errors' => $sortErros ); - } - - /** - * Add the subject print request, unless mainlabel is set to "-". - * - * @since 1.7 - * - * @param array $printRequests - * @param array $rawParams - */ - public static function addThisPrintout( array &$printRequests, array $rawParams ) { - if ( !is_null( $printRequests ) ) { - $hasMainlabel = array_key_exists( 'mainlabel', $rawParams ); - - if ( !$hasMainlabel || trim( $rawParams['mainlabel'] ) !== '-' ) { - array_unshift( $printRequests, new SMWPrintRequest( - SMWPrintRequest::PRINT_THIS, - $hasMainlabel ? $rawParams['mainlabel'] : '' - ) ); - } - } - } - - /** - * Preprocess a query as given by an array of parameters as is typically - * produced by the #ask parser function. The parsing results in a querystring, - * an array of additional parameters, and an array of additional SMWPrintRequest - * objects, which are filled into call-by-ref parameters. - * $showMode is true if the input should be treated as if given by #show - * - * @param array $rawParams - * @param string $querystring - * @param array $params - * @param array $printouts array of SMWPrintRequest - * @param boolean $showMode - * @deprecated Will vanish after SMW 1.8 is released. - * Use getComponentsFromFunctionParams which has a cleaner interface. - */ - static public function processFunctionParams( array $rawParams, &$querystring, &$params, &$printouts, $showMode = false ) { - list( $querystring, $params, $printouts ) = self::getComponentsFromFunctionParams( $rawParams, $showMode ); - } - - - /** - * Preprocess a query as given by an array of parameters as is - * typically produced by the #ask parser function or by Special:Ask. - * The parsing results in a querystring, an array of additional - * parameters, and an array of additional SMWPrintRequest objects, - * which are returned in an array with three components. If - * $showMode is true then the input will be processed as if for #show. - * This uses a slightly different way to get the query, and different - * default labels (empty) for additional print requests. - * - * @param array $rawParams - * @param boolean $showMode - * @return array( string, array( string => string ), array( SMWPrintRequest ) ) - */ - static public function getComponentsFromFunctionParams( array $rawParams, $showMode ) { - $queryString = ''; - $parameters = array(); - $printouts = array(); - - $lastprintout = null; - foreach ( $rawParams as $name => $rawParam ) { - // special handling for arrays - this can happen if the - // parameter came from a checkboxes input in Special:Ask: - if ( is_array( $rawParam ) ) { - $rawParam = implode( ',', array_keys( $rawParam ) ); - } - - // accept 'name' => 'value' just as '' => 'name=value': - if ( is_string( $name ) && ( $name !== '' ) ) { - $rawParam = $name . '=' . $rawParam; - } - - if ( $rawParam === '' ) { - } elseif ( $rawParam { 0 } == '?' ) { // print statement - $rawParam = substr( $rawParam, 1 ); - $lastprintout = self::getSMWPrintRequestFromString( $rawParam, $showMode ); - if ( !is_null( $lastprintout ) ) { - $printouts[] = $lastprintout; - } - } elseif ( $rawParam[0] == '+' ) { // print request parameter - if ( !is_null( $lastprintout ) ) { - $rawParam = substr( $rawParam, 1 ); - $parts = explode( '=', $rawParam, 2 ); - if ( count( $parts ) == 2 ) { - $lastprintout->setParameter( trim( $parts[0] ), $parts[1] ); - } else { - $lastprintout->setParameter( trim( $parts[0] ), null ); - } - } - } else { // parameter or query - $parts = explode( '=', $rawParam, 2 ); - - if ( count( $parts ) >= 2 ) { - // don't trim here, some parameters care for " " - $parameters[strtolower( trim( $parts[0] ) )] = $parts[1]; - } else { - $queryString .= $rawParam; - } - } - } - - $queryString = str_replace( array( '<', '>' ), array( '<', '>' ), $queryString ); - if ( $showMode ) { - $queryString = "[[:$queryString]]"; - } - - return array( $queryString, $parameters, $printouts); - } - - /** - * Create an SMWPrintRequest object from a string description as one - * would normally use in #ask and related inputs. The string must start - * with a "?" and may contain label and formatting parameters after "=" - * or "#", respectively. However, further parameters, given in #ask by - * "|+param=value" are not allowed here; they must be added - * individually. - * - * @param string $printRequestString - * @param boolean $showMode - * @return SMWPrintRequest||null - * @since 1.8 - */ - static protected function getSMWPrintRequestFromString( $printRequestString, $showMode ) { - global $wgContLang; - - $parts = explode( '=', $printRequestString, 2 ); - $propparts = explode( '#', $parts[0], 2 ); - - $data = null; - - if ( trim( $propparts[0] ) === '' ) { // print "this" - $printmode = SMWPrintRequest::PRINT_THIS; - $label = ''; // default - } elseif ( $wgContLang->getNsText( NS_CATEGORY ) == ucfirst( trim( $propparts[0] ) ) ) { // print categories - $printmode = SMWPrintRequest::PRINT_CATS; - $label = $showMode ? '' : $wgContLang->getNSText( NS_CATEGORY ); // default - } else { // print property or check category - $title = Title::newFromText( trim( $propparts[0] ), SMW_NS_PROPERTY ); // trim needed for \n - if ( is_null( $title ) ) { // not a legal property/category name; give up - return null; - } - - if ( $title->getNamespace() == NS_CATEGORY ) { - $printmode = SMWPrintRequest::PRINT_CCAT; - $data = $title; - $label = $showMode ? '' : $title->getText(); // default - } else { // enforce interpretation as property (even if it starts with something that looks like another namespace) - $printmode = SMWPrintRequest::PRINT_PROP; - $data = SMWPropertyValue::makeUserProperty( trim( $propparts[0] ) ); - if ( !$data->isValid() ) { // not a property; give up - return null; - } - $label = $showMode ? '' : $data->getWikiValue(); // default - } - } - - if ( count( $propparts ) == 1 ) { // no outputformat found, leave empty - $propparts[] = false; - } elseif ( trim( $propparts[1] ) === '' ) { // "plain printout", avoid empty string to avoid confusions with "false" - $propparts[1] = '-'; - } - - if ( count( $parts ) > 1 ) { // label found, use this instead of default - $label = trim( $parts[1] ); - } - - try { - return new SMWPrintRequest( $printmode, $label, $data, trim( $propparts[1] ) ); - } catch ( InvalidArgumentException $e ) { // something still went wrong; give up - return null; - } - } - - /** - * Process and answer a query as given by an array of parameters as is - * typically produced by the #ask parser function. The parameter - * $context defines in what context the query is used, which affects - * certain general settings. - * - * The main task of this function is to preprocess the raw parameters - * to obtain actual parameters, printout requests, and the query string - * for further processing. - * - * @since 1.8 - * @param array $rawParams user-provided list of unparsed parameters - * @param integer $outputMode SMW_OUTPUT_WIKI, SMW_OUTPUT_HTML, ... - * @param integer $context INLINE_QUERY, SPECIAL_PAGE, CONCEPT_DESC - * @param boolean $showMode process like #show parser function? - * @return array( SMWQuery, array of IParam ) - */ - static public function getQueryAndParamsFromFunctionParams( array $rawParams, $outputMode, $context, $showMode ) { - list( $queryString, $params, $printouts ) = self::getComponentsFromFunctionParams( $rawParams, $showMode ); - - if ( !$showMode ) { - self::addThisPrintout( $printouts, $params ); - } - - $params = self::getProcessedParams( $params, $printouts ); - - $query = self::createQuery( $queryString, $params, $context, '', $printouts ); - return array( $query, $params ); - } - - /** - * Process and answer a query as given by an array of parameters as is - * typically produced by the #ask parser function. The result is formatted - * according to the specified $outputformat. The parameter $context defines - * in what context the query is used, which affects ceretain general settings. - * - * The main task of this function is to preprocess the raw parameters to - * obtain actual parameters, printout requests, and the query string for - * further processing. - * - * @note Consider using getQueryAndParamsFromFunctionParams() and - * getResultFromQuery() instead. - * @deprecated Will vanish after release of SMW 1.8. - * See SMW_Ask.php for example code on how to get query results from - * #ask function parameters. - */ - static public function getResultFromFunctionParams( array $rawParams, $outputMode, $context = self::INLINE_QUERY, $showMode = false ) { - list( $queryString, $params, $printouts ) = self::getComponentsFromFunctionParams( $rawParams, $showMode ); - - if ( !$showMode ) { - self::addThisPrintout( $printouts, $params ); - } - - $params = self::getProcessedParams( $params, $printouts ); - - return self::getResultFromQueryString( $queryString, $params, $printouts, SMW_OUTPUT_WIKI, $context ); - } - - /** - * Process a query string in SMW's query language and return a formatted - * result set as specified by $outputmode. A parameter array of key-value-pairs - * constrains the query and determines the serialisation mode for results. The - * parameter $context defines in what context the query is used, which affects - * certain general settings. Finally, $extraprintouts supplies additional - * printout requests for the query results. - * - * @param string $queryString - * @param array $params These need to be the result of a list fed to getProcessedParams - * @param $extraPrintouts - * @param $outputMode - * @param $context - * - * @return string - * @deprecated Will vanish after release of SMW 1.8. - * See SMW_Ask.php for example code on how to get query results from - * #ask function parameters. - */ - static public function getResultFromQueryString( $queryString, array $params, $extraPrintouts, $outputMode, $context = self::INLINE_QUERY ) { - wfProfileIn( 'SMWQueryProcessor::getResultFromQueryString (SMW)' ); - - $query = self::createQuery( $queryString, $params, $context, '', $extraPrintouts ); - $result = self::getResultFromQuery( $query, $params, $outputMode, $context ); - - wfProfileOut( 'SMWQueryProcessor::getResultFromQueryString (SMW)' ); - - return $result; - } - - /** - * Create a fully formatted result string from a query and its - * parameters. The method takes care of processing various types of - * query result. Most cases are handled by printers, but counting and - * debugging uses special code. - * - * @param SMWQuery $query - * @param array $params These need to be the result of a list fed to getProcessedParams - * @param integer $outputMode - * @param integer $context - * @since before 1.7, but public only since 1.8 - * - * @return string - */ - public static function getResultFromQuery( SMWQuery $query, array $params, $outputMode, $context ) { - wfProfileIn( 'SMWQueryProcessor::getResultFromQuery (SMW)' ); - - $res = self::getStoreFromParams( $params )->getQueryResult( $query ); - - if ( ( $query->querymode == SMWQuery::MODE_INSTANCES ) || - ( $query->querymode == SMWQuery::MODE_NONE ) ) { - wfProfileIn( 'SMWQueryProcessor::getResultFromQuery-printout (SMW)' ); - - $printer = self::getResultPrinter( $params['format']->getValue(), $context ); - $result = $printer->getResult( $res, $params, $outputMode ); - - wfProfileOut( 'SMWQueryProcessor::getResultFromQuery-printout (SMW)' ); - wfProfileOut( 'SMWQueryProcessor::getResultFromQuery (SMW)' ); - - return $result; - } else { // result for counting or debugging is just a string or number - - if ( $res instanceof SMWQueryResult ) { - $res = $res->getCountValue(); - } - - if ( is_numeric( $res ) ) { - $res = strval( $res ); - } - - if ( is_string( $res ) ) { - $result = str_replace( '_', ' ', $params['intro']->getValue() ) - . $res - . str_replace( '_', ' ', $params['outro']->getValue() ) - . smwfEncodeMessages( $query->getErrors() ); - } else { - // When no valid result was obtained, $res will be a SMWQueryResult. - $result = smwfEncodeMessages( $query->getErrors() ); - } - - wfProfileOut( 'SMWQueryProcessor::getResultFromQuery (SMW)' ); - - return $result; - } - } - - private static function getStoreFromParams( array $params ) { - - $storeId = null; - $source = $params['source']->getValue(); - - if ( $source !== '' ) { - $storeId = $GLOBALS['smwgQuerySources'][$source]; - } - - return \SMW\StoreFactory::getStore( $storeId ); - } - - /** - * Find suitable SMWResultPrinter for the given format. The context in - * which the query is to be used determines some basic settings of the - * returned printer object. Possible contexts are - * SMWQueryProcessor::SPECIAL_PAGE, SMWQueryProcessor::INLINE_QUERY, - * SMWQueryProcessor::CONCEPT_DESC. - * - * @param string $format - * @param $context - * - * @return SMWResultPrinter - * @throws MWException if no printer is known for the given format - */ - static public function getResultPrinter( $format, $context = self::SPECIAL_PAGE ) { - global $smwgResultFormats; - - if ( !array_key_exists( $format, $smwgResultFormats ) ) { - throw new MWException( "There is no result format for '$format'." ); - } - - $formatClass = $smwgResultFormats[$format]; - - return new $formatClass( $format, ( $context != self::SPECIAL_PAGE ) ); - } - - /** - * A function to describe the allowed parameters of a query using - * any specific format - most query printers should override this - * function. - * - * @since 1.6.2, return element type changed in 1.8 - * - * @return IParamDefinition[] - */ - public static function getParameters() { - $params = array(); - - $allowedFormats = $GLOBALS['smwgResultFormats']; - - foreach ( $GLOBALS['smwgResultAliases'] as $aliases ) { - $allowedFormats += $aliases; - } - - $allowedFormats[] = 'auto'; - - $params['format'] = array( - 'type' => 'smwformat', - 'default' => 'auto', - ); - - // TODO $params['format']->setToLower( true ); - // TODO $allowedFormats - - $params['source'] = self::getSourceParam(); - - $params['limit'] = array( - 'type' => 'integer', - 'default' => $GLOBALS['smwgQDefaultLimit'], - 'negatives' => false, - ); - - $params['offset'] = array( - 'type' => 'integer', - 'default' => 0, - 'negatives' => false, - 'upperbound' => 5000 // TODO: make setting - ); - - $params['link'] = array( - 'default' => 'all', - 'values' => array( 'all', 'subject', 'none' ), - ); - - $params['sort'] = array( - 'islist' => true, - 'default' => array( '' ), // The empty string represents the page itself, which should be sorted by default. - ); - - $params['order'] = array( - 'islist' => true, - 'default' => array(), - 'values' => array( 'descending', 'desc', 'asc', 'ascending', 'rand', 'random' ), - ); - - $params['headers'] = array( - 'default' => 'show', - 'values' => array( 'show', 'hide', 'plain' ), - ); - - $params['mainlabel'] = array( - 'default' => false, - ); - - $params['intro'] = array( - 'default' => '', - ); - - $params['outro'] = array( - 'default' => '', - ); - - $params['searchlabel'] = array( - 'default' => wfMessage( 'smw_iq_moreresults' )->inContentLanguage()->text(), - ); - - $params['default'] = array( - 'default' => '', - ); - - // Give grep a chance to find the usages: - // smw-paramdesc-format, smw-paramdesc-source, smw-paramdesc-limit, smw-paramdesc-offset, - // smw-paramdesc-link, smw-paramdesc-sort, smw-paramdesc-order, smw-paramdesc-headers, - // smw-paramdesc-mainlabel, smw-paramdesc-intro, smw-paramdesc-outro, smw-paramdesc-searchlabel, - // smw-paramdesc-default - foreach ( $params as $name => &$param ) { - if ( is_array( $param ) ) { - $param['message'] = 'smw-paramdesc-' . $name; - } - } - - return ParamDefinition::getCleanDefinitions( $params ); - } - - private static function getSourceParam() { - $sourceValues = is_array( $GLOBALS['smwgQuerySources'] ) ? array_keys( $GLOBALS['smwgQuerySources'] ) : array(); - - return array( - 'default' => array_key_exists( 'default', $sourceValues ) ? 'default' : '', - 'values' => $sourceValues, - ); - } - - /** - * Returns the definitions of all parameters supported by the specified format. - * - * @since 1.8 - * - * @param string $format - * - * @return array of IParamDefinition - */ - public static function getFormatParameters( $format ) { - SMWParamFormat::resolveFormatAliases( $format ); - - if ( array_key_exists( $format, $GLOBALS['smwgResultFormats'] ) ) { - return ParamDefinition::getCleanDefinitions( - SMWQueryProcessor::getResultPrinter( $format )->getParamDefinitions( SMWQueryProcessor::getParameters() ) - ); - } else { - return array(); - } - } - -} diff --git a/SemanticMediaWiki/includes/query/profiler/DescriptionProfile.php b/SemanticMediaWiki/includes/query/profiler/DescriptionProfile.php deleted file mode 100644 index 2f64ed1a..00000000 --- a/SemanticMediaWiki/includes/query/profiler/DescriptionProfile.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php - -namespace SMW\Query\Profiler; - -use SMW\DIProperty; - -use SMWDescription as QueryDescription; -use SMWDINumber as DINumber; -use SMWDIBlob as DIBlob; - -/** - * Provides access to some QueryDescription profiling data - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class DescriptionProfile extends ProfileAnnotatorDecorator { - - /** @var QueryDescription */ - protected $description; - - /** - * @since 1.9 - * - * @param ProfileAnnotator $profileAnnotator - */ - public function __construct( ProfileAnnotator $profileAnnotator, QueryDescription $description ) { - parent::__construct( $profileAnnotator ); - $this->description = $description; - } - - /** - * @since 1.9 - */ - protected function addPropertyValues() { - $this->addQueryString( $this->description->getQueryString() ); - $this->addQuerySize( $this->description->getSize() ); - $this->addQueryDepth( $this->description->getDepth() ); - } - - /** - * @since 1.9 - */ - private function addQueryString( $queryString ) { - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( '_ASKST' ), - new DIBlob( $queryString ) - ); - } - - /** - * @since 1.9 - */ - private function addQuerySize( $size ) { - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( '_ASKSI' ), - new DINumber( $size ) - ); - } - - /** - * @since 1.9 - */ - private function addQueryDepth( $depth ) { - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( '_ASKDE' ), - new DINumber( $depth ) - ); - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/query/profiler/DurationProfile.php b/SemanticMediaWiki/includes/query/profiler/DurationProfile.php deleted file mode 100644 index 0aa19287..00000000 --- a/SemanticMediaWiki/includes/query/profiler/DurationProfile.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -namespace SMW\Query\Profiler; - -use SMW\DIProperty; -use SMWDINumber as DINumber; - -/** - * Adds duration profiling annotation - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class DurationProfile extends ProfileAnnotatorDecorator { - - /** @var integer */ - protected $duration; - - /** - * @since 1.9 - * - * @param ProfileAnnotator $profileAnnotator - */ - public function __construct( ProfileAnnotator $profileAnnotator, $duration ) { - parent::__construct( $profileAnnotator ); - $this->duration = $duration; - } - - /** - * @since 1.9 - */ - protected function addPropertyValues() { - if ( $this->duration > 0 ) { - $this->addGreaterThanZeroQueryDuration( $this->duration ); - } - } - - /** - * @since 1.9 - */ - private function addGreaterThanZeroQueryDuration( $duration ) { - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( '_ASKDU' ), - new DINumber( $duration ) - ); - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/query/profiler/FormatProfile.php b/SemanticMediaWiki/includes/query/profiler/FormatProfile.php deleted file mode 100644 index 6341975f..00000000 --- a/SemanticMediaWiki/includes/query/profiler/FormatProfile.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -namespace SMW\Query\Profiler; - -use SMW\DIProperty; -use SMWDIBlob as DIBlob; - -/** - * Provides access to Format profiling data - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class FormatProfile extends ProfileAnnotatorDecorator { - - /** @var array */ - protected $format; - - /** - * @since 1.9 - * - * @param ProfileAnnotator $profileAnnotator - */ - public function __construct( ProfileAnnotator $profileAnnotator, $format ) { - parent::__construct( $profileAnnotator ); - $this->format = $format; - } - - /** - * @since 1.9 - */ - protected function addPropertyValues() { - $this->addQueryFormat( $this->format ); - } - - /** - * @since 1.9 - */ - private function addQueryFormat( $format ) { - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( '_ASKFO' ), - new DIBlob( $format ) - ); - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/query/profiler/NullProfile.php b/SemanticMediaWiki/includes/query/profiler/NullProfile.php deleted file mode 100644 index 2915795e..00000000 --- a/SemanticMediaWiki/includes/query/profiler/NullProfile.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -namespace SMW\Query\Profiler; - -use SMW\Subobject; -use SMW\IdGenerator; -use SMW\DIProperty; - -/** - * Provides access to the Null object for handling profiling data - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class NullProfile implements ProfileAnnotator { - - /** @var Subobject */ - protected $subobject; - - /** @var string */ - protected $queryId = null; - - /** - * @since 1.9 - * - * @param Subobject $subobject - * @param IdGenerator $queryId - */ - public function __construct( Subobject $subobject, IdGenerator $queryId ) { - $this->subobject = $subobject; - $this->queryId = $queryId; - } - - /** - * Returns errors collected during processing - * - * @since 1.9 - * - * @return array - */ - public function getErrors() { - return $this->subobject->getErrors(); - } - - /** - * ProfileAnnotator::getProperty - * - * @since 1.9 - * - * @return array - */ - public function getProperty() { - return new DIProperty( '_ASK' ); - } - - /** - * ProfileAnnotator::getContainer - * - * @since 1.9 - * - * @return SemanticData - */ - public function getContainer() { - return $this->subobject->getContainer(); - } - - /** - * ProfileAnnotator::getSemanticData - * - * @since 1.9 - * - * @return SemanticData - */ - public function getSemanticData() { - return $this->subobject->getSemanticData(); - } - - /** - * ProfileAnnotator::addAnnotation - * - * @since 1.9 - */ - public function addAnnotation() { - $this->subobject->setSemanticData( - $this->subobject->generateId( $this->queryId->setPrefix( '_QUERY' ) ) - ); - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/query/profiler/ProfileAnnotator.php b/SemanticMediaWiki/includes/query/profiler/ProfileAnnotator.php deleted file mode 100644 index b3a0bb3f..00000000 --- a/SemanticMediaWiki/includes/query/profiler/ProfileAnnotator.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -namespace SMW\Query\Profiler; - -use SMW\PropertyAnnotator; - -/** - * Specifing the ProfileAnnotator interface - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface ProfileAnnotator extends PropertyAnnotator { - - /** - * Returns the query meta data property - * - * @since 1.9 - * - * @return DIProperty - */ - public function getProperty(); - - /** - * Returns the query meta data container - * - * @since 1.9 - * - * @return DIContainer - */ - public function getContainer(); - -} diff --git a/SemanticMediaWiki/includes/query/profiler/ProfileAnnotatorDecorator.php b/SemanticMediaWiki/includes/query/profiler/ProfileAnnotatorDecorator.php deleted file mode 100644 index b01a7766..00000000 --- a/SemanticMediaWiki/includes/query/profiler/ProfileAnnotatorDecorator.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -namespace SMW\Query\Profiler; - -/** - * Decorator implementing the ProfileAnnotator interface - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -abstract class ProfileAnnotatorDecorator implements ProfileAnnotator { - - /** @var ProfileAnnotator */ - protected $profileAnnotator; - - /** - * @since 1.9 - * - * @param ProfileAnnotator $profileAnnotator - */ - public function __construct( ProfileAnnotator $profileAnnotator ) { - $this->profileAnnotator = $profileAnnotator; - } - - /** - * ProfileAnnotator::getProperty - * - * @since 1.9 - * - * @return DIProperty - */ - public function getProperty() { - return $this->profileAnnotator->getProperty(); - } - - /** - * ProfileAnnotator::getContainer - * - * @since 1.9 - * - * @return DIContainer - */ - public function getContainer() { - return $this->profileAnnotator->getContainer(); - } - - /** - * @see ProfileAnnotator::getSemanticData - * - * @since 1.9 - * - * @return SemanticData - */ - public function getSemanticData() { - return $this->profileAnnotator->getSemanticData(); - } - - /** - * ProfileAnnotator::addAnnotation - * - * @since 1.9 - * - * @return ProfileAnnotator - */ - public function addAnnotation() { - $this->profileAnnotator->addAnnotation(); - $this->addPropertyValues(); - } - - /** - * @since 1.9 - */ - protected abstract function addPropertyValues(); - -} diff --git a/SemanticMediaWiki/includes/querypages/PropertiesQueryPage.php b/SemanticMediaWiki/includes/querypages/PropertiesQueryPage.php deleted file mode 100644 index f6902125..00000000 --- a/SemanticMediaWiki/includes/querypages/PropertiesQueryPage.php +++ /dev/null @@ -1,235 +0,0 @@ -<?php - -namespace SMW; - -use SMWTypesValue; -use SMWDIError; - -use Html; - -/** - * Query class that provides content for the Special:Properties page - * - * @ingroup QueryPage - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author mwjames - */ -class PropertiesQueryPage extends QueryPage { - - /** @var Store */ - protected $store; - - /** @var Settings */ - protected $settings; - - /** @var Collector */ - protected $collector; - - /** - * @since 1.9 - * - * @param Store $store - * @param Settings $settings - */ - public function __construct( Store $store, Settings $settings ) { - $this->store = $store; - $this->settings = $settings; - } - - /** - * @codeCoverageIgnore - * Returns available cache information (takes into account user preferences) - * - * @since 1.9 - * - * @return string - */ - public function getCacheInfo() { - return $this->collector->isCached() ? $this->msg( 'smw-sp-properties-cache-info', $this->getLanguage()->userTimeAndDate( $this->collector->getCacheDate(), $this->getUser() ) )->parse() : ''; - } - - /** - * @return string - */ - function getPageHeader() { - return Html::rawElement( - 'p', - array( 'class' => 'smw-sp-properties-docu' ), - $this->msg( 'smw-sp-properties-docu' )->parse() - ) . $this->getSearchForm( $this->getRequest()->getVal( 'property' ), $this->getCacheInfo() ) . - Html::element( - 'h2', - array(), - $this->msg( 'smw-sp-properties-header-label' )->text() - ); - } - - /** - * @codeCoverageIgnore - * @return string - */ - function getName() { - return 'Properties'; - } - - /** - * Format a result in the list of results as a string. We expect the - * result to be an array with one object of type SMWDIProperty - * (normally) or maybe SMWDIError (if something went wrong), followed - * by a number (how often the property is used). - * - * @param Skin $skin provided by MediaWiki, not needed here - * @param mixed $result - * @return String - * @throws InvalidResultException if the result was not of a supported type - */ - function formatResult( $skin, $result ) { - - list ( $dataItem, $useCount ) = $result; - - if ( $dataItem instanceof DIProperty ) { - return $this->formatPropertyItem( $dataItem, $useCount ); - } elseif ( $dataItem instanceof SMWDIError ) { - return $this->getMessageFormatter()->clear() - ->setType( 'warning' ) - ->addFromArray( array( $dataItem->getErrors() ) ) - ->getHtml(); - } else { - throw new InvalidResultException( 'PropertiesQueryPage expects results that are properties or errors.' ); - } - } - - /** - * Produce a formatted string representation for showing a property and - * its usage count in the list of used properties. - * - * @since 1.8 - * - * @param DIProperty $property - * @param integer $useCount - * @return string - */ - protected function formatPropertyItem( DIProperty $property, $useCount ) { - - // Clear formatter before invoking messages - $this->getMessageFormatter()->clear(); - - $diWikiPage = $property->getDiWikiPage(); - $title = $diWikiPage !== null ? $diWikiPage->getTitle() : null; - - if ( $useCount == 0 && !$this->settings->get( 'smwgPropertyZeroCountDisplay' ) ) { - return ''; - } - - if ( $property->isUserDefined() ) { - - if ( $title === null ) { - // Show even messed up property names. - $typestring = ''; - $proplink = $property->getLabel(); - $this->getMessageFormatter()->addFromKey( 'smw_notitle', $proplink ); - } else { - list( $typestring, $proplink ) = $this->getUserDefinedPropertyInfo( $title, $property, $useCount ); - } - - } else { - list( $typestring, $proplink ) = $this->getPredefinedPropertyInfo( $property ); - } - - if ( $typestring === '' ) { // Built-ins have no type - - // @todo Should use numParams for $useCount? - return $this->msg( 'smw_property_template_notype' ) - ->rawParams( $proplink )->numParams( $useCount )->text() . ' ' . - $this->getMessageFormatter()->setType( 'warning' )->escape( false )->getHtml(); - - } else { - - // @todo Should use numParams for $useCount? - return $this->msg( 'smw_property_template' ) - ->rawParams( $proplink, $typestring )->numParams( $useCount )->escaped() . ' ' . - $this->getMessageFormatter()->setType( 'warning' )->escape( false )->getHtml(); - - } - } - - /** - * Returns information related to user-defined properties - * - * @since 1.9 - * - * @param Title $title - * @param DIProperty $property - * @param integer $useCount - * - * @return array - */ - private function getUserDefinedPropertyInfo( $title, $property, $useCount ) { - - if ( $useCount <= $this->settings->get( 'smwgPropertyLowUsageThreshold' ) ) { - $this->getMessageFormatter()->addFromKey( 'smw_propertyhardlyused' ); - } - - // User defined types default to Page - $typestring = SMWTypesValue::newFromTypeId( $this->settings->get( 'smwgPDefaultType' ) )->getLongHTMLText( $this->getLinker() ); - - $label = htmlspecialchars( $property->getLabel() ); - - if ( $title->exists() ) { - - $typeProperty = new DIProperty( '_TYPE' ); - $types = $this->store->getPropertyValues( $property->getDiWikiPage(), $typeProperty ); - - if ( count( $types ) >= 1 ) { - - $typeDataValue = DataValueFactory::getInstance()->newDataItemValue( current( $types ), $typeProperty ); - $typestring = $typeDataValue->getLongHTMLText( $this->getLinker() ); - - } else { - - $this->getMessageFormatter()->addFromKey( 'smw_propertylackstype', $typestring ); - } - - $proplink = $this->getLinker()->link( $title, $label ); - - } else { - - $this->getMessageFormatter()->addFromKey( 'smw_propertylackspage' ); - $proplink = $this->getLinker()->link( $title, $label, array(), array( 'action' => 'view' ) ); - } - - return array( $typestring, $proplink ); - } - - /** - * Returns information related to predefined properties - * - * @since 1.9 - * - * @param DIProperty $property - * - * @return array - */ - private function getPredefinedPropertyInfo( DIProperty $property ) { - return array( - SMWTypesValue::newFromTypeId( $property->findPropertyTypeID() )->getLongHTMLText( $this->getLinker() ), - DataValueFactory::getInstance()->newDataItemValue( $property, null )->getShortHtmlText( $this->getLinker() ) - ); - } - - /** - * Get the list of results. - * - * @param SMWRequestOptions $requestOptions - * @return array of array( SMWDIProperty|SMWDIError, integer ) - */ - function getResults( $requestOptions ) { - $this->collector = $this->store->getPropertiesSpecial( $requestOptions ); - return $this->collector->getResults(); - } - -} diff --git a/SemanticMediaWiki/includes/querypages/QueryPage.php b/SemanticMediaWiki/includes/querypages/QueryPage.php deleted file mode 100644 index f11cf70b..00000000 --- a/SemanticMediaWiki/includes/querypages/QueryPage.php +++ /dev/null @@ -1,243 +0,0 @@ -<?php - -namespace SMW; - -use SMWRequestOptions; -use SMWStringCondition; - -use Html; -use Xml; - -/** - * An abstract query page base class that supports array-based - * data retrieval instead of the SQL-based access used by MW. - * - * @file - * - * @license GNU GPL v2+ - * @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 \QueryPage { - - /** @var MessageFormatter */ - protected $msgFormatter; - - /** @var Linker */ - protected $linker; - - /** @var array */ - protected $selectOptions = array(); - - /** @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 = array(); - $property = $this->getRequest()->getVal( 'property' ); - - if ( $property !== null && $property !== '' ) { - $parameters['property'] = $property; - } - - 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 ( !isset( $this->linker ) ) { - $this->linker = smwfGetLinker(); - } - - return $this->linker; - } - - /** - * Generates a search form - * - * @since 1.9 - * - * @param string $property - * - * @return string - */ - public function getSearchForm( $property = '', $cacheDate = '' ) { - - $this->useSerchForm = true; - - // No need to verify $this->selectOptions because its values are set - // during doQuery() which is processed before this form is generated - $resultCount = wfShowingResults( $this->selectOptions['offset'], $this->selectOptions['count'] ); - - $selection = $this->getLanguage()->viewPrevNext( - $this->getContext()->getTitle(), - $this->selectOptions['offset'], - $this->selectOptions['limit'], - $this->linkParameters(), - $this->selectOptions['end'] - ); - - return Xml::tags( 'form', array( - 'method' => 'get', - 'action' => htmlspecialchars( $GLOBALS['wgScript'] ) - ), Html::hidden( 'title', $this->getContext()->getTitle()->getPrefixedText() ) . - Xml::fieldset( $this->msg( 'properties' )->text(), - Xml::tags( 'p', array(), $resultCount ) . - Xml::tags( 'p', array(), $selection ) . - Xml::tags( 'p', array(), $cacheDate ) . - Xml::tags( 'hr', array( 'style' => 'margin-bottom:10px;' ), '' ) . - Xml::inputLabel( $this->msg( 'smw-sp-property-searchform' )->text(), 'property', 'property', 20, $property ) . ' ' . - Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) - ) - ); - } - - /** - * 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 SMWRequestOptions(); - $options->limit = $limit; - $options->offset = $offset; - $options->sort = true; - - if ( $property ) { - $options->addStringCondition( str_replace( ' ', '_', $property ), SMWStringCondition::STRCOND_MID ); - } - - $res = $this->getResults( $options ); - $num = count( $res ); - - // often disable 'next' link when we reach the end - $atend = $num < $limit; - - $this->selectOptions = array( - '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 unused properties and wanted properties are using the searchForm - // then the useSerchForm if-inclusion can be scrapped - if ( !$this->useSerchForm ) { - - $top = wfShowingResults( $offset, $num ); - - $sl = $this->getLanguage()->viewPrevNext( - $this->getTitleFor( $this->getName() ), - $this->selectOptions['offset'], - $this->selectOptions['limit'], - $this->linkParameters(), - $this->selectOptions['end'] - ); - - $out->addHTML( "<p>{$top}\n" ); - $out->addHTML( "<br />{$sl}</p>\n" ); - } - - if ( $num > 0 ) { - $s = array(); - 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; - } -} diff --git a/SemanticMediaWiki/includes/querypages/UnusedPropertiesQueryPage.php b/SemanticMediaWiki/includes/querypages/UnusedPropertiesQueryPage.php deleted file mode 100644 index 4226c4bb..00000000 --- a/SemanticMediaWiki/includes/querypages/UnusedPropertiesQueryPage.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php - -namespace SMW; - -use SMWTypesValue; -use SMWDIError; - -use Html; - -/** - * Query page that provides content to Special:UnusedProperties - * - * @ingroup QueryPage - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author mwjames - */ -class UnusedPropertiesQueryPage extends QueryPage { - - /** @var Store */ - protected $store; - - /** @var Settings */ - protected $settings; - - /** @var Collector */ - protected $collector; - - /** - * @since 1.9 - * - * @param Store $store - * @param Settings $settings - */ - public function __construct( Store $store, Settings $settings ) { - $this->store = $store; - $this->settings = $settings; - } - - /** - * @codeCoverageIgnore - * @return string - */ - function getName() { - return "UnusedProperties"; - } - - /** - * @codeCoverageIgnore - * @return boolean - */ - function isExpensive() { - return false; // Disables caching for now - } - - /** - * @codeCoverageIgnore - * @return boolean - */ - function isSyndicated() { - return false; // TODO: why not? - } - - /** - * @codeCoverageIgnore - * @return string - */ - function getPageHeader() { - return Html::element( 'p', array(), $this->msg( 'smw_unusedproperties_docu' )->text() ); - } - - /** - * Format a result in the list of results as a string. We expect the - * result to be an object of type SMWDIProperty (normally) or maybe - * SMWDIError (if something went wrong). - * - * @param Skin $skin provided by MediaWiki, not needed here - * @param mixed $result - * - * @return String - * @throws InvalidResultException if the result was not of a supported type - */ - function formatResult( $skin, $result ) { - - if ( $result instanceof DIProperty ) { - return $this->formatPropertyItem( $result ); - } elseif ( $result instanceof SMWDIError ) { - return $this->getMessageFormatter()->clear() - ->setType( 'warning' ) - ->addFromArray( array( $result->getErrors() ) ) - ->getHtml(); - } else { - throw new InvalidResultException( 'UnusedPropertiesQueryPage expects results that are properties or errors.' ); - } - } - - /** - * Produce a formatted string representation for showing a property in - * the list of unused properties. - * - * @since 1.8 - * - * @param DIProperty $property - * - * @return string - */ - protected function formatPropertyItem( DIProperty $property ) { - - // Clear formatter before invoking messages and - // avoid having previous data to be present - $this->getMessageFormatter()->clear(); - - if ( $property->isUserDefined() ) { - - $propertyLink = $this->getLinker()->link( - $property->getDiWikiPage()->getTitle(), - $property->getLabel() - ); - - $types = $this->store->getPropertyValues( $property->getDiWikiPage(), new DIProperty( '_TYPE' ) ); - - if ( count( $types ) >= 1 ) { - $typeDataValue = DataValueFactory::getInstance()->newDataItemValue( current( $types ), new DIProperty( '_TYPE' ) ); - } else { - $typeDataValue = SMWTypesValue::newFromTypeId( '_wpg' ); - $this->getMessageFormatter()->addFromKey( 'smw_propertylackstype', $typeDataValue->getLongHTMLText() ); - } - - } else { - $typeDataValue = SMWTypesValue::newFromTypeId( $property->findPropertyTypeID() ); - $propertyLink = DataValueFactory::getInstance()->newDataItemValue( $property, null )->getShortHtmlText( $this->getLinker() ); - } - - return $this->msg( 'smw_unusedproperty_template', $propertyLink, $typeDataValue->getLongHTMLText( $this->getLinker() ) )->text() . ' ' . - $this->getMessageFormatter()->getHtml(); - } - - /** - * Get the list of results. - * - * @param SMWRequestOptions $requestOptions - * @return array of SMWDIProperty|SMWDIError - */ - function getResults( $requestOptions ) { - $this->collector = $this->store->getUnusedPropertiesSpecial( $requestOptions ); - return $this->collector->getResults(); - } -} diff --git a/SemanticMediaWiki/includes/querypages/WantedPropertiesQueryPage.php b/SemanticMediaWiki/includes/querypages/WantedPropertiesQueryPage.php deleted file mode 100644 index 65135152..00000000 --- a/SemanticMediaWiki/includes/querypages/WantedPropertiesQueryPage.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -namespace SMW; - -use Html; - -/** - * Query class that provides content for the Special:WantedProperties page - * - * @ingroup QueryPage - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author mwjames - */ -class WantedPropertiesQueryPage extends QueryPage { - - /** @var Store */ - protected $store; - - /** @var Settings */ - protected $settings; - - /** @var Collector */ - protected $collector; - - /** - * @since 1.9 - * - * @param Store $store - * @param Settings $settings - */ - public function __construct( Store $store, Settings $settings ) { - $this->store = $store; - $this->settings = $settings; - } - - /** - * @codeCoverageIgnore - * @return string - */ - function getName() { - return "WantedProperties"; - } - - /** - * @codeCoverageIgnore - * @return boolean - */ - function isExpensive() { - return false; /// disables caching for now - } - - /** - * @codeCoverageIgnore - * @return boolean - */ - function isSyndicated() { - return false; ///TODO: why not? - } - - /** - * @codeCoverageIgnore - * @return string - */ - function getPageHeader() { - return Html::element( 'p', array(), $this->msg( 'smw_wantedproperties_docu' )->text() ); - } - - /** - * @param $skin - * @param array $result First item is SMWDIProperty, second item is int - * - * @return string - */ - function formatResult( $skin, $result ) { - - $proplink = ''; - - // Only display user-defined properties because it can happen that - // custom predefined (fixed) properties are mixed within the result - // (did not use their own fixedProperty table and therefore were - // selected as well e.g _SF_PDF etc.) - if ( $result[0] instanceof DIProperty && $result[0]->isUserDefined() ) { - $proplink = $this->getLinker()->link( - $result[0]->getDiWikiPage()->getTitle(), - htmlspecialchars( $result[0]->getLabel() ), - array( 'action' => 'view' ) - ); - } - - return $proplink ? $this->msg( 'smw_wantedproperty_template', $proplink, $result[1] )->text() : ''; - } - - /** - * Get the list of results. - * - * @param SMWRequestOptions $requestOptions - * @return array of SMWDIProperty|SMWDIError - */ - function getResults( $requestoptions ) { - $this->collector = $this->store->getWantedPropertiesSpecial( $requestoptions ); - return $this->collector->getResults(); - } -} diff --git a/SemanticMediaWiki/includes/queryprinters/AggregatablePrinter.php b/SemanticMediaWiki/includes/queryprinters/AggregatablePrinter.php deleted file mode 100644 index a90fcc99..00000000 --- a/SemanticMediaWiki/includes/queryprinters/AggregatablePrinter.php +++ /dev/null @@ -1,280 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; -use SMWDataItem; - -/** - * Abstract class that supports the aggregation and distributive calculation - * of numerical data. - * - * @since 1.9 - * - * @file - * - * @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 === array() ) { - $queryResult->addErrors( array( - $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 = array(); - - 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 = array(); - - // 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'] = array( - 'name' => 'distribution', - 'type' => 'boolean', - 'default' => false, - 'message' => 'smw-paramdesc-distribution', - ); - - $definitions['distributionsort'] = array( - 'name' => 'distributionsort', - 'type' => 'string', - 'default' => 'none', - 'message' => 'smw-paramdesc-distributionsort', - 'values' => array( 'asc', 'desc', 'none' ), - ); - - $definitions['distributionlimit'] = array( - 'name' => 'distributionlimit', - 'type' => 'integer', - 'default' => false, - 'manipulatedefault' => false, - 'message' => 'smw-paramdesc-distributionlimit', - 'lowerbound' => 1, - ); - - $definitions['aggregation'] = array( - 'message' => 'smw-paramdesc-aggregation', - 'default' => 'subject', - 'values' => array( 'property', 'subject' ), - ); - - return $definitions; - } - -} diff --git a/SemanticMediaWiki/includes/queryprinters/CategoryResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/CategoryResultPrinter.php deleted file mode 100644 index 2f61a4c1..00000000 --- a/SemanticMediaWiki/includes/queryprinters/CategoryResultPrinter.php +++ /dev/null @@ -1,217 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; -use SMWDataItem; - -/** - * Print query results in alphabetic groups displayed in columns, a la the - * standard Category pages and the default view in Semantic Drilldown. - * Based on SMW_QP_List by Markus Krötzsch. - * - * @ingroup SMWQuery - * - * @author David Loomer - * @author Yaron Koren - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class CategoryResultPrinter extends ResultPrinter { - - protected $mDelim; - protected $mTemplate; - protected $mUserParam; - protected $mNumColumns; - - /** - * @see SMWResultPrinter::handleParameters - * - * @since 1.6.2 - * - * @param array $params - * @param $outputmode - */ - protected function handleParameters( array $params, $outputmode ) { - parent::handleParameters( $params, $outputmode ); - - $this->mUserParam = trim( $params['userparam'] ); - $this->mDelim = trim( $params['delim'] ); - $this->mNumColumns = $params['columns']; - $this->mTemplate = $params['template']; - } - - public function getName() { - return wfMessage( 'smw_printername_' . $this->mFormat )->text(); - } - - protected function getResultText( SMWQueryResult $res, $outputmode ) { - global $wgContLang; - - $result = ''; - $num = $res->getCount(); - - $prev_first_char = ""; - $rows_per_column = ceil( $num / $this->mNumColumns ); - // column width is a percentage - $column_width = floor( 100 / $this->mNumColumns ); - - // Print all result rows: - $rowindex = 0; - $row = $res->getNext(); - - while ( $row !== false ) { - $nextrow = $res->getNext(); // look ahead - - if ( !isset( $row[0] ) ) { - $row = $nextrow; - continue; - } - - $content = $row[0]->getContent(); - - if ( !isset( $content[0] ) || !( $content[0] instanceof SMWDataItem ) ) { - $row = $nextrow; - continue; - } - - $cur_first_char = $wgContLang->firstChar( - $content[0]->getDIType() == SMWDataItem::TYPE_WIKIPAGE ? - $res->getStore()->getWikiPageSortKey( $content[0] ) - : $content[0]->getSortKey() - ); - - if ( $rowindex % $rows_per_column == 0 ) { - $result .= "\n <div style=\"float: left; width: $column_width%;\">\n"; - if ( $cur_first_char == $prev_first_char ) - $result .= " <h3>$cur_first_char " . wfMessage( 'listingcontinuesabbrev' )->text() . "</h3>\n <ul>\n"; - } - - // if we're at a new first letter, end - // the last list and start a new one - if ( $cur_first_char != $prev_first_char ) { - if ( $rowindex % $rows_per_column > 0 ) - $result .= " </ul>\n"; - $result .= " <h3>$cur_first_char</h3>\n <ul>\n"; - } - $prev_first_char = $cur_first_char; - - $result .= '<li>'; - $first_col = true; - - if ( $this->mTemplate !== '' ) { // build template code - $this->hasTemplates = true; - $wikitext = ( $this->mUserParam ) ? "|userparam=$this->mUserParam":''; - $i = 1; // explicitly number parameters for more robust parsing (values may contain "=") - - foreach ( $row as $field ) { - $wikitext .= '|' . $i++ . '='; - $first_value = true; - - while ( ( $text = $field->getNextText( SMW_OUTPUT_WIKI, $this->getLinker( $first_col ) ) ) !== false ) { - if ( $first_value ) $first_value = false; else $wikitext .= $this->mDelim . ' '; - $wikitext .= $text; - } - - $first_col = false; - } - - $wikitext .= "|#=$rowindex"; - $result .= '{{' . $this->mTemplate . $wikitext . '}}'; - // str_replace('|', '|', // encode '|' for use in templates (templates fail otherwise) -- this is not the place for doing this, since even DV-Wikitexts contain proper "|"! - } else { // build simple list - $first_col = true; - $found_values = false; // has anything but the first column been printed? - - foreach ( $row as $field ) { - $first_value = true; - - while ( ( $text = $field->getNextText( SMW_OUTPUT_WIKI, $this->getLinker( $first_col ) ) ) !== false ) { - if ( !$first_col && !$found_values ) { // first values after first column - $result .= ' ('; - $found_values = true; - } elseif ( $found_values || !$first_value ) { - // any value after '(' or non-first values on first column - $result .= ', '; - } - - if ( $first_value ) { // first value in any column, print header - $first_value = false; - - if ( $this->mShowHeaders && ( $field->getPrintRequest()->getLabel() !== '' ) ) { - $result .= $field->getPrintRequest()->getText( SMW_OUTPUT_WIKI, $this->mLinker ) . ' '; - } - } - - $result .= $text; // actual output value - } - - $first_col = false; - } - - if ( $found_values ) $result .= ')'; - } - - $result .= '</li>'; - $row = $nextrow; - - // end list if we're at the end of the column - // or the page - if ( ( $rowindex + 1 ) % $rows_per_column == 0 && ( $rowindex + 1 ) < $num ) { - $result .= " </ul>\n </div> <!-- end column -->"; - } - - $rowindex++; - } - - if ( $result === '' ) { - - $res->addErrors( array( - $this->msg( 'smw-qp-empty-data' )->inContentLanguage()->text() - ) ); - - return $result; - } - - // Make label for finding further results - if ( $this->linkFurtherResults( $res ) ) { - $result .= '<br /><li>' . $this->getLink( $res, $outputmode )->getText( SMW_OUTPUT_WIKI, $this->mLinker ) . '</li>'; - } - - $result .= "</ul>\n</div> <!-- end column -->"; - // clear all the CSS floats - $result .= "\n" . '<br style="clear: both;"/>'; - - // <H3> will generate TOC entries otherwise. Probably need another way - // to accomplish this -- user might still want TOC for other page content. - $result .= '__NOTOC__'; - - return $result; - } - - public function getParameters() { - return array_merge( parent::getParameters(), array( - array( - 'name' => 'columns', - 'type' => 'integer', - 'message' => 'smw-paramdesc-columns', - 'default' => 3, - ), - array( - 'name' => 'delim', - 'message' => 'smw-paramdesc-category-delim', - 'default' => '', - ), - array( - 'name' => 'template', - 'message' => 'smw-paramdesc-category-template', - 'default' => '', - ), - array( - 'name' => 'userparam', - 'message' => 'smw-paramdesc-category-userparam', - 'default' => '', - ), - ) ); - } - -} diff --git a/SemanticMediaWiki/includes/queryprinters/CsvResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/CsvResultPrinter.php deleted file mode 100644 index a8a258cb..00000000 --- a/SemanticMediaWiki/includes/queryprinters/CsvResultPrinter.php +++ /dev/null @@ -1,160 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryProcessor; -use SMWQueryResult; -use Sanitizer; -use SMWQuery; - -/** - * CSV export for SMW Queries - * - * @since 1.9 - * - * @file - * - * @license GNU GPL v2+ - * @author Nathan R. Yergler - * @author Markus Krötzsch - */ - -/** - * Printer class for generating CSV output - * - * @ingroup QueryPrinter - */ -class CsvResultPrinter extends FileExportPrinter { - - /** - * @codeCoverageIgnore - * - * @return string - */ - public function getName() { - return $this->msg( 'smw_printername_csv' )->text(); - } - - /** - * @see SMWIExportPrinter::getMimeType - * @codeCoverageIgnore - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string - */ - public function getMimeType( SMWQueryResult $queryResult ) { - return 'text/csv'; - } - - /** - * @see SMWIExportPrinter::getFileName - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string|boolean - */ - public function getFileName( SMWQueryResult $queryResult ) { - return $this->params['filename'] ; - } - - public function getQueryMode( $context ) { - return ( $context == SMWQueryProcessor::SPECIAL_PAGE ) ? SMWQuery::MODE_INSTANCES : SMWQuery::MODE_NONE; - } - - protected function getResultText( SMWQueryResult $res, $outputmode ) { - $result = ''; - - if ( $outputmode == SMW_OUTPUT_FILE ) { // make CSV file - $csv = fopen( 'php://temp', 'r+' ); - $sep = str_replace( '_', ' ', $this->params['sep'] ); - - if ( $this->params['showsep'] ) { - fputs( $csv, "sep=" . $sep . "\n" ); - } - - if ( $this->mShowHeaders ) { - $header_items = array(); - - foreach ( $res->getPrintRequests() as $pr ) { - $header_items[] = $pr->getLabel(); - } - - fputcsv( $csv, $header_items, $sep ); - } - - while ( $row = $res->getNext() ) { - $row_items = array(); - - foreach ( $row as /* SMWResultArray */ $field ) { - $growing = array(); - - while ( ( $object = $field->getNextDataValue() ) !== false ) { - $growing[] = Sanitizer::decodeCharReferences( $object->getWikiValue() ); - } - - $row_items[] = implode( ',', $growing ); - } - - fputcsv( $csv, $row_items, $sep ); - } - - rewind( $csv ); - $result .= stream_get_contents( $csv ); - } else { // just make link to feed - $result .= $this->getLink( $res, $outputmode )->getText( $outputmode, $this->mLinker ); - $this->isHTML = ( $outputmode == SMW_OUTPUT_HTML ); // yes, our code can be viewed as HTML if requested, no more parsing needed - } - return $result; - } - - /** - * @see SMWResultPrinter::getParamDefinitions - * @codeCoverageIgnore - * - * @since 1.8 - * - * @param ParamDefinition[] $definitions - * - * @return array - */ - public function getParamDefinitions( array $definitions ) { - $params = parent::getParamDefinitions( $definitions ); - - $definitions['searchlabel']->setDefault( $this->msg( 'smw_csv_link' )->inContentLanguage()->text() ); - - $definitions['limit']->setDefault( 100 ); - - $params[] = array( - 'name' => 'sep', - 'message' => 'smw-paramdesc-csv-sep', - 'default' => ',', - ); - - $params['showsep'] = array( - 'type' => 'boolean', - 'default' => false, - 'message' => 'smw-paramdesc-showsep', - ); - - $params[] = array( - 'name' => 'filename', - 'message' => 'smw-paramdesc-filename', - 'default' => 'result.csv', - ); - - return $params; - } -} - -/** - * SMWCsvResultPrinter - * @codeCoverageIgnore - * - * @deprecated since SMW 1.9 - */ -class_alias( 'SMW\CsvResultPrinter', 'SMWCsvResultPrinter' ); diff --git a/SemanticMediaWiki/includes/queryprinters/DsvResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/DsvResultPrinter.php deleted file mode 100644 index f461fc2e..00000000 --- a/SemanticMediaWiki/includes/queryprinters/DsvResultPrinter.php +++ /dev/null @@ -1,216 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; -use SMWQueryProcessor; -use SMWQuery; -use Sanitizer; - -/** - * Result printer to print results in UNIX-style DSV (deliminter separated value) format. - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class DsvResultPrinter extends FileExportPrinter { - - protected $separator = ':'; - protected $fileName = 'result.dsv'; - - /** - * @see SMWResultPrinter::handleParameters - * - * @since 1.6 - * - * @param array $params - * @param $outputmode - */ - protected function handleParameters( array $params, $outputmode ) { - parent::handleParameters( $params, $outputmode ); - - // Do not allow backspaces as delimiter, as they'll break stuff. - if ( trim( $params['separator'] ) != '\\' ) { - $this->separator = trim( $params['separator'] ); - } - - $this->fileName = str_replace( ' ', '_', $params['filename'] ); - } - - /** - * @see SMWIExportPrinter::getMimeType - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string - */ - public function getMimeType( SMWQueryResult $queryResult ) { - return 'text/dsv'; - } - - /** - * @see SMWIExportPrinter::getFileName - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string|boolean - */ - public function getFileName( SMWQueryResult $queryResult ) { - return $this->fileName; - } - - public function getQueryMode( $context ) { - return $context == SMWQueryProcessor::SPECIAL_PAGE ? SMWQuery::MODE_INSTANCES : SMWQuery::MODE_NONE; - } - - public function getName() { - return wfMessage( 'smw_printername_dsv' )->text(); - } - - protected function getResultText( SMWQueryResult $res, $outputMode ) { - if ( $outputMode == SMW_OUTPUT_FILE ) { // Make the DSV file. - return $this->getResultFileContents( $res ); - } - else { // Create a link pointing to the DSV file. - return $this->getLinkToFile( $res, $outputMode ); - } - } - - /** - * Returns the query result in DSV. - * - * @since 1.6 - * - * @param SMWQueryResult $res - * - * @return string - */ - protected function getResultFileContents( SMWQueryResult $queryResult ) { - $lines = array(); - - if ( $this->mShowHeaders ) { - $headerItems = array(); - - foreach ( $queryResult->getPrintRequests() as $printRequest ) { - $headerItems[] = $printRequest->getLabel(); - } - - $lines[] = $this->getDSVLine( $headerItems ); - } - - // Loop over the result objects (pages). - while ( $row = $queryResult->getNext() ) { - $rowItems = array(); - - /** - * Loop over their fields (properties). - * @var SMWResultArray $field - */ - foreach ( $row as $field ) { - $itemSegments = array(); - - // Loop over all values for the property. - while ( ( $object = $field->getNextDataValue() ) !== false ) { - $itemSegments[] = Sanitizer::decodeCharReferences( $object->getWikiValue() ); - } - - // Join all values into a single string, separating them with comma's. - $rowItems[] = implode( ',', $itemSegments ); - } - - $lines[] = $this->getDSVLine( $rowItems ); - } - - return implode( "\n", $lines ); - } - - /** - * Returns a single DSV line. - * - * @since 1.6 - * - * @param array $fields - * - * @return string - */ - protected function getDSVLine( array $fields ) { - return implode( $this->separator, array_map( array( $this, 'encodeDSV' ), $fields ) ); - } - - /** - * Encodes a single DSV. - * - * @since 1.6 - * - * @param string $value - * - * @return string - */ - protected function encodeDSV( $value ) { - // TODO - // \nnn or \onnn or \0nnn for the character with octal value nnn - // \xnn for the character with hexadecimal value nn - // \dnnn for the character with decimal value nnn - // \unnnn for a hexadecimal Unicode literal. - return str_replace( - array( '\n', '\r', '\t', '\b', '\f', '\\', $this->separator ), - array( "\n", "\r", "\t", "\b", "\f", '\\\\', "\\$this->separator" ), - $value - ); - } - - /** - * Returns html for a link to a query that returns the DSV file. - * - * @since 1.6 - * - * @param SMWQueryResult $res - * @param $outputMode - * - * @return string - */ - protected function getLinkToFile( SMWQueryResult $res, $outputMode ) { - // yes, our code can be viewed as HTML if requested, no more parsing needed - $this->isHTML = ( $outputMode == SMW_OUTPUT_HTML ); - return $this->getLink( $res, $outputMode )->getText( $outputMode, $this->mLinker ); - } - - /** - * @see SMWResultPrinter::getParamDefinitions - * - * @since 1.8 - * - * @param ParamDefinition[] $definitions - * - * @return array - */ - public function getParamDefinitions( array $definitions ) { - $params = parent::getParamDefinitions( $definitions ); - - $params['searchlabel']->setDefault( wfMessage( 'smw_dsv_link' )->text() ); - - $params['limit']->setDefault( 100 ); - - $params[] = array( - 'name' => 'separator', - 'message' => 'smw-paramdesc-dsv-separator', - 'default' => $this->separator, - 'aliases' => 'sep', - ); - - $params[] = array( - 'name' => 'filename', - 'message' => 'smw-paramdesc-dsv-filename', - 'default' => $this->fileName, - ); - - return $params; - } - -} diff --git a/SemanticMediaWiki/includes/queryprinters/EmbeddedResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/EmbeddedResultPrinter.php deleted file mode 100644 index e4424c30..00000000 --- a/SemanticMediaWiki/includes/queryprinters/EmbeddedResultPrinter.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; - -use Title; - -/** - * Printer for embedded data. - * - * Embeds in the page output the contents of the pages in the query result set. - * Printouts are ignored: it only matters which pages were returned by the query. - * The optional "titlestyle" formatting parameter can be used to apply a format to - * the headings for the page titles. If "titlestyle" is not specified, a <h1> tag is - * used. - * - * @license GNU GPL v2+ - * @since 1.7 - * - * @author Fernando Correia - * @author Markus Krötzsch - */ -class EmbeddedResultPrinter extends ResultPrinter { - - protected $m_showhead; - protected $m_embedformat; - - /** - * @see SMWResultPrinter::handleParameters - * - * @since 1.7 - * - * @param array $params - * @param $outputmode - */ - protected function handleParameters( array $params, $outputmode ) { - parent::handleParameters( $params, $outputmode ); - - $this->m_showhead = !$params['embedonly']; - $this->m_embedformat = $params['embedformat']; - } - - public function getName() { - return wfMessage( 'smw_printername_embedded' )->text(); - } - - protected function getResultText( SMWQueryResult $res, $outputmode ) { - global $wgParser; - // No page should embed itself, find out who we are: - if ( $wgParser->getTitle() instanceof Title ) { - $title = $wgParser->getTitle()->getPrefixedText(); - } else { // this is likely to be in vain -- this case is typical if we run on special pages - global $wgTitle; - $title = $wgTitle->getPrefixedText(); - } - - // print header - $result = ''; - $footer = ''; - $embstart = ''; - $embend = ''; - $headstart = ''; - $headend = ''; - $this->hasTemplates = true; - - switch ( $this->m_embedformat ) { - case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': - $headstart = '<' . $this->m_embedformat . '>'; - $headend = '</' . $this->m_embedformat . ">\n"; - break; - case 'ul': case 'ol': - $result .= '<' . $this->m_embedformat . '>'; - $footer = '</' . $this->m_embedformat . '>'; - $embstart = '<li>'; - $headend = "<br />\n"; - $embend = "</li>\n"; - break; - } - - // Print all result rows: - foreach ( $res->getResults() as $diWikiPage ) { - if ( $diWikiPage instanceof DIWikiPage ) { // ensure that we deal with title-likes - $dvWikiPage = DataValueFactory::getInstance()->newDataItemValue( $diWikiPage, null ); - $result .= $embstart; - - if ( $this->m_showhead ) { - $result .= $headstart . $dvWikiPage->getLongWikiText( $this->mLinker ) . $headend; - } - - if ( $dvWikiPage->getLongWikiText() != $title ) { - if ( $diWikiPage->getNamespace() == NS_MAIN ) { - $result .= '{{:' . $diWikiPage->getDBkey() . '}}'; - } else { - $result .= '{{' . $dvWikiPage->getLongWikiText() . '}}'; - } - } else { // block recursion - $result .= '<b>' . $dvWikiPage->getLongWikiText() . '</b>'; - } - - $result .= $embend; - } - } - - // show link to more results - if ( $this->linkFurtherResults( $res ) ) { - $result .= $embstart - . $this->getFurtherResultsLink( $res, $outputmode )->getText( SMW_OUTPUT_WIKI, $this->mLinker ) - . $embend; - } - - $result .= $footer; - - return $result; - } - - public function getParameters() { - $params = parent::getParameters(); - - $params[] = array( - 'name' => 'embedformat', - 'message' => 'smw-paramdesc-embedformat', - 'default' => 'h1', - 'values' => array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul' ), - ); - - $params[] = array( - 'name' => 'embedonly', - 'type' => 'boolean', - 'message' => 'smw-paramdesc-embedonly', - 'default' => false, - ); - - return $params; - } - -} diff --git a/SemanticMediaWiki/includes/queryprinters/ExportPrinter.php b/SemanticMediaWiki/includes/queryprinters/ExportPrinter.php deleted file mode 100644 index 2bfbd55e..00000000 --- a/SemanticMediaWiki/includes/queryprinters/ExportPrinter.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; - -/** - * Interface for SMW export related result printers - * - * @license GNU GPL v2+ - * @since 1.8 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -interface ExportPrinter extends QueryResultPrinter { - - /** - * Outputs the result as file. - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * @param array $params - */ - public function outputAsFile( SMWQueryResult $queryResult, array $params ); - - /** - * Some printers do not mainly produce embeddable HTML or Wikitext, but - * produce stand-alone files. An example is RSS or iCalendar. This function - * returns the mimetype string that this file would have, or FALSE if no - * standalone files are produced. - * - * If this function returns something other than FALSE, then the printer will - * not be regarded as a printer that displays in-line results. This is used to - * determine if a file output should be generated in Special:Ask. - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string - */ - public function getMimeType( SMWQueryResult $queryResult ); - - /** - * Some printers can produce not only embeddable HTML or Wikitext, but - * can also produce stand-alone files. An example is RSS or iCalendar. - * This function returns a filename that is to be sent to the caller - * in such a case (the default filename is created by browsers from the - * URL, and it is often not pretty). - * - * @param SMWQueryResult $queryResult - * - * @return string|boolean - */ - public function getFileName( SMWQueryResult $queryResult ); - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/queryprinters/FeedResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/FeedResultPrinter.php deleted file mode 100644 index a908499a..00000000 --- a/SemanticMediaWiki/includes/queryprinters/FeedResultPrinter.php +++ /dev/null @@ -1,337 +0,0 @@ -<?php - -namespace SMW; -use SMWQueryResult, SMWQuery, SMWQueryProcessor, SMWDIWikipage; -use Sanitizer, WikiPage, ParserOptions, FeedItem, TextContent, Title; - -/** - * Result printer that exports query results as RSS/Atom feed - * - * @since 1.8 - * - * @file - * - * @license GNU GPL v2 or later - * @author mwjames - */ - -/** - * Result printer that exports query results as RSS/Atom feed - * - * @ingroup QueryPrinter - */ -final class FeedResultPrinter extends FileExportPrinter { - - /** - * Returns human readable label for this printer - * - * @return string - */ - public function getName() { - return $this->getContext()->msg( 'smw-printername-feed' )->text(); - } - - /** - * @see SMWIExportPrinter::getMimeType - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string - */ - public function getMimeType( SMWQueryResult $queryResult ) { - return $this->params['type'] === 'atom' ? 'application/atom+xml' : 'application/rss+xml'; - } - - /** - * @see SMWIExportPrinter::outputAsFile - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * @param array $params - */ - public function outputAsFile( SMWQueryResult $queryResult, array $params ) { - $this->getResult( $queryResult, $params, SMW_OUTPUT_FILE ); - } - - /** - * File exports use MODE_INSTANCES on special pages (so that instances are - * retrieved for the export) and MODE_NONE otherwise (displaying just a download link). - * - * @param $mode - * - * @return integer - */ - public function getQueryMode( $mode ) { - return $mode == SMWQueryProcessor::SPECIAL_PAGE ? SMWQuery::MODE_INSTANCES : SMWQuery::MODE_NONE; - } - - /** - * Returns a string that is to be sent to the caller - * - * @param SMWQueryResult $res - * @param integer $outputMode - * - * @return string - */ - protected function getResultText( SMWQueryResult $res, $outputMode ) { - - if ( $outputMode == SMW_OUTPUT_FILE ) { - if ( $res->getCount() == 0 ){ - $res->addErrors( array( $this->getContext()->msg( 'smw_result_noresults' )->inContentLanguage()->text() ) ); - return ''; - } - $result = $this->getFeed( $res, $this->params['type'] ); - } else { - // Points to the Feed link - $result = $this->getLink( $res, $outputMode )->getText( $outputMode, $this->mLinker ); - - $this->isHTML = $outputMode == SMW_OUTPUT_HTML; - } - return $result; - } - - /** - * Build a feed - * - * @since 1.8 - * - * @param SMWQueryResult $results - * @param $type - * - * @return string - */ - protected function getFeed( SMWQueryResult $results, $type ) { - global $wgFeedClasses; - - if( !isset( $wgFeedClasses[$type] ) ) { - $results->addErrors( array( $this->getContext()->msg( 'feed-invalid' )->inContentLanguage()->text() ) ); - return ''; - } - - // Get feed class instance - - /** - * @var \ChannelFeed $feed - */ - $feed = new $wgFeedClasses[$type]( - $this->feedTitle(), - $this->feedDescription(), - $this->feedURL() - ); - - // Create feed header - $feed->outHeader(); - - // Create feed items - while ( $row = $results->getNext() ) { - $feed->outItem( $this->feedItem( $row ) ); - } - - // Create feed footer - $feed->outFooter(); - - return $feed; - } - - /** - * Returns feed title - * - * @since 1.8 - * - * @return string - */ - protected function feedTitle() { - return $this->params['title'] === '' ? $GLOBALS['wgSitename'] : $this->params['title']; - } - - /** - * Returns feed description - * - * @since 1.8 - * - * @return string - */ - protected function feedDescription() { - return $this->params['description'] !== '' ? $this->getContext()->msg( 'smw-label-feed-description', $this->params['description'], $this->params['type'] )->text() : $this->getContext()->msg( 'tagline' )->text(); - } - - /** - * Returns feed URL - * - * @since 1.8 - * - * @return string - */ - protected function feedURL() { - return $GLOBALS['wgTitle']->getFullUrl(); - } - - /** - * Returns feed item - * - * @since 1.8 - * - * @param array $row - * - * @return array - */ - protected function feedItem( array $row ) { - $rowItems = array(); - - $subject = false; - - /** - * Loop over all properties within a row - * - * @var \SMWResultArray $field - * @var \SMWDataValue $object - */ - foreach ( $row as $field ) { - $itemSegments = array(); - - $subject = $field->getResultSubject()->getTitle(); - - // Loop over all values for the property. - while ( ( $dataValue = $field->getNextDataValue() ) !== false ) { - if ( $dataValue->getDataItem() instanceof SMWDIWikipage ) { - $itemSegments[] = Sanitizer::decodeCharReferences( $dataValue->getLongHTMLText() ); - } else { - $itemSegments[] = Sanitizer::decodeCharReferences( $dataValue->getWikiValue() ); - } - } - - // Join all property values into a single string, separated by a comma - if ( $itemSegments !== array() ) { - $rowItems[] = implode( ', ', $itemSegments ); - } - } - - if ( $subject instanceof Title ) { - $wikiPage = WikiPage::newFromID( $subject->getArticleID() ); - - if ( $wikiPage->exists() ){ - return new FeedItem( - $subject->getPrefixedText(), - $this->feedItemDescription( $rowItems, $this->getPageContent( $wikiPage ) ), - $subject->getFullURL(), - $wikiPage->getTimestamp(), - $wikiPage->getUserText(), - $this->feedItemComments() - ); - } - } - - return array(); - } - - /** - * Returns page content - * - * @since 1.8 - * - * @param WikiPage $wikiPage - * - * @return string - */ - protected function getPageContent( WikiPage $wikiPage ) { - if ( in_array( $this->params['page'], array( 'abstract', 'full' ) ) ) { - $parserOptions = new ParserOptions(); - $parserOptions->setEditSection( false ); - - if ( $this->params['page'] === 'abstract' ) { - // Abstract of the first 30 words - // preg_match( '/^([^.!?\s]*[\.!?\s]+){0,30}/', $wikiPage->getText(), $abstract ); - // $text = $abstract[0] . ' ...'; - } else { - if ( method_exists( $wikiPage, 'getContent' ) ) { - $content = $wikiPage->getContent(); - - if ( $content instanceof TextContent ) { - $text = $content->getNativeData(); - } else { - return ''; - } - } else { - $text = $wikiPage->getText(); - } - } - return $GLOBALS['wgParser']->parse( $text , $wikiPage->getTitle(), $parserOptions )->getText(); - } else { - return ''; - } - } - - /** - * Feed item description and property value output manipulation - * - * @note FeedItem will do an FeedItem::xmlEncode therefore no need - * to be overly cautious here - * - * @since 1.8 - * - * @param array $items - * @param string $pageContent - * - * @return string - */ - protected function feedItemDescription( $items, $pageContent ) { - return FeedItem::stripComment( implode( ',', $items ) ) . - FeedItem::stripComment( $pageContent ); - } - - /** - * According to MW documentation, the comment field is only implemented for RSS - * - * @since 1.8 - * - * @return string - */ - protected function feedItemComments( ) { - return ''; - } - - /** - * @see SMWResultPrinter::getParamDefinitions - * - * @since 1.8 - * - * @param ParamDefinition[] $definitions - * - * @return array - */ - public function getParamDefinitions( array $definitions ) { - $params = parent::getParamDefinitions( $definitions ); - - $params['searchlabel']->setDefault( $this->getContext()->msg( 'smw-label-feed-link' )->inContentLanguage()->text() ); - - $params['type'] = array( - 'type' => 'string', - 'default' => 'rss', - 'message' => 'smw-paramdesc-feedtype', - 'values' => array( 'rss', 'atom' ), - ); - - $params['title'] = array( - 'message' => 'smw-paramdesc-feedtitle', - 'default' => '', - 'aliases' => array( 'rsstitle' ), - ); - - $params['description'] = array( - 'message' => 'smw-paramdesc-feeddescription', - 'default' => '', - 'aliases' => array( 'rssdescription' ), - ); - - $params['page'] = array( - 'message' => 'smw-paramdesc-feedpagecontent', - 'default' => 'none', - 'values' => array( 'none', 'full' ), // @note Option abstract is not deployed with the 1.8 release - ); - - return $params; - } -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/queryprinters/FileExportPrinter.php b/SemanticMediaWiki/includes/queryprinters/FileExportPrinter.php deleted file mode 100644 index 37878e8c..00000000 --- a/SemanticMediaWiki/includes/queryprinters/FileExportPrinter.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; - -/** - * Base class for file export result printers - * - * @since 1.8 - * @license GNU GPL v2+ - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -abstract class FileExportPrinter extends ResultPrinter implements ExportPrinter { - - /** - * @see ExportPrinter::isExportFormat - * - * @since 1.8 - * - * @return boolean - */ - public final function isExportFormat() { - return true; - } - - /** - * @see ExportPrinter::outputAsFile - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * @param array $params - */ - public function outputAsFile( SMWQueryResult $queryResult, array $params ) { - $result = $this->getResult( $queryResult, $params, SMW_OUTPUT_FILE ); - - header( 'Content-type: ' . $this->getMimeType( $queryResult ) . '; charset=UTF-8' ); - - $fileName = $this->getFileName( $queryResult ); - - if ( $fileName !== false ) { - $utf8Name = rawurlencode( $fileName ); - $fileName = iconv( "UTF-8", "ASCII//TRANSLIT", $fileName ); - header( "content-disposition: attachment; filename=\"$fileName\"; filename*=UTF-8''$utf8Name;" ); - } - - echo $result; - } - - /** - * @see ExportPrinter::getFileName - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string|boolean - */ - public function getFileName( SMWQueryResult $queryResult ) { - return false; - } - -} diff --git a/SemanticMediaWiki/includes/queryprinters/JsonResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/JsonResultPrinter.php deleted file mode 100644 index 1f582463..00000000 --- a/SemanticMediaWiki/includes/queryprinters/JsonResultPrinter.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; -use SMWQueryProcessor; -use SMWQuery; -use FormatJSON; - -/** - * Print links to JSON files representing query results. - * - * @see http://www.semantic-mediawiki.org/wiki/Help:JSON_format - * - * @since 1.5.3 - * - * @file - * - * @license GNU GPL v2 or later - * @author mwjames - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author Fabian Howahl - */ - -/** - * Print links to JSON files representing query results. - * - * @ingroup QueryPrinter - */ -class JsonResultPrinter extends FileExportPrinter { - - /** - * Returns human readable label for this printer - * @codeCoverageIgnore - * - * @return string - */ - public function getName() { - return $this->msg( 'smw_printername_json' )->text(); - } - - /** - * @see SMWIExportPrinter::getMimeType - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string - */ - public function getMimeType( SMWQueryResult $queryResult ) { - return 'application/json'; - } - - /** - * @see SMWIExportPrinter::getFileName - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string|boolean - */ - public function getFileName( SMWQueryResult $queryResult ) { - if ( $this->getSearchLabel( SMW_OUTPUT_WIKI ) !== '' ) { - return str_replace( ' ', '_', $this->getSearchLabel( SMW_OUTPUT_WIKI ) ) . '.json'; - } else { - return 'result.json'; - } - } - - /** - * File exports use MODE_INSTANCES on special pages (so that instances are - * retrieved for the export) and MODE_NONE otherwise (displaying just a download link). - * - * @param $context - * - * @return integer - */ - public function getQueryMode( $context ) { - return ( $context == SMWQueryProcessor::SPECIAL_PAGE ) ? SMWQuery::MODE_INSTANCES : SMWQuery::MODE_NONE; - } - - /** - * Returns a filename that is to be sent to the caller - * - * @param SMWQueryResult $res - * @param $outputmode integer - * - * @return string - */ - protected function getResultText( SMWQueryResult $res, $outputmode ) { - - if ( $outputmode == SMW_OUTPUT_FILE ) { - - // No results, just bailout - if ( $res->getCount() == 0 ){ - return $this->params['default'] !== '' ? $this->params['default'] : ''; - } - - // Serialize queryResult - $result = FormatJSON::encode( - array_merge( - $res->serializeToArray(), - array ( 'rows' => $res->getCount() ) - ), - $this->params['prettyprint'] - ); - - } else { - // Create a link that points to the JSON file - $result = $this->getLink( $res, $outputmode )->getText( $outputmode, $this->mLinker ); - - // Code can be viewed as HTML if requested, no more parsing needed - $this->isHTML = $outputmode == SMW_OUTPUT_HTML; - } - - return $result; - } - - /** - * @see SMWResultPrinter::getParamDefinitions - * @codeCoverageIgnore - * - * @since 1.8 - * - * @param ParamDefinition[] $definitions - * - * @return array - */ - public function getParamDefinitions( array $definitions ) { - $params = parent::getParamDefinitions( $definitions ); - - $params['searchlabel']->setDefault( $this->msg( 'smw_json_link' )->text() ); - - $params['limit']->setDefault( 100 ); - - $params['prettyprint'] = array( - 'type' => 'boolean', - 'default' => '', - 'message' => 'smw-paramdesc-prettyprint', - ); - - return $params; - } -} - -/** - * SMWJsonResultPrinter - * @codeCoverageIgnore - * - * @deprecated since SMW 1.9 - */ -class_alias( 'SMW\JsonResultPrinter', 'SMWJsonResultPrinter' ); diff --git a/SemanticMediaWiki/includes/queryprinters/ListResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/ListResultPrinter.php deleted file mode 100644 index c25adf53..00000000 --- a/SemanticMediaWiki/includes/queryprinters/ListResultPrinter.php +++ /dev/null @@ -1,481 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; -use SMWDataItem; -use SMWResultArray; - -use Sanitizer; -use Html; - -/** - * Print query results in lists. - * - * @author Markus Krötzsch - * @file - * @ingroup SMWQuery - */ - -/** - * New implementation of SMW's printer for results in lists. - * The implementation covers comma-separated lists, ordered and unordered lists. - * List items may be formatted using templates, and list output can be in - * multiple columns (at least for ordered and unordered lists). - * - * In the code below, one list item (with all extra information displayed for - * it) is called a "row", while one entry in this row is called a "field" to - * avoid confusion with the "columns" that we have in multi-column display. - * Every field may in turn contain many "values". - * - * @ingroup SMWQuery - */ -class ListResultPrinter extends ResultPrinter { - - protected $mTemplate; - protected $mNamedArgs; - protected $mUserParam; - protected $mColumns; - protected $mIntroTemplate; - protected $mOutroTemplate; - - /** - * The text used to start the list. - * @var string - * @since 1.9 - */ - protected $header; - /** - * The text used to end the list. - * @var string - * @since 1.9 - */ - protected $footer; - /** - * The text used to start a row in the list. - * @var string - * @since 1.9 - */ - protected $rowstart; - /** - * The text used to end a row in the list. - * @var string - * @since 1.9 - */ - protected $rowend; - /** - * The text used to separate items in the list, other than the final - * one. - * @var string - * @since 1.9 - */ - protected $listsep; - /** - * The text used to separate the last item in the list from the rest. - * @var string - * @since 1.9 - */ - protected $finallistsep; - /** - * Width (in percent) of columns in multi-column display. - * @var integer - * @since 1.9 - */ - protected $columnWidth; - /** - * Number of results per column in multi-column display. - * @var integer - * @since 1.9 - */ - protected $rowsPerColumn; - /** - * Number of results in current column in multi-column display. - * @var integer - * @since 1.9 - */ - protected $numRowsInColumn; - /** - * Number of results printed so far (equals index of result - * to print next). - * @var integer - * @since 1.9 - */ - protected $numRows; - - - /** - * @see SMWResultPrinter::handleParameters - * - * @since 1.6 - * - * @param array $params - * @param $outputmode - */ - protected function handleParameters( array $params, $outputmode ) { - parent::handleParameters( $params, $outputmode ); - - $this->mTemplate = trim( $params['template'] ); - $this->mNamedArgs = $params['named args']; - $this->mUserParam = trim( $params['userparam'] ); - $this->mColumns = !$this->isPlainlist() ? $params['columns'] : 1; - $this->mIntroTemplate = $params['introtemplate']; - $this->mOutroTemplate = $params['outrotemplate']; - } - - /** - * @see SMW\ResultPrinter::getName - * - */ - public function getName() { - // Give grep a chance to find the usages: - // smw_printername_list, smw_printername_ol,smw_printername_ul, smw_printername_template - return $this->getContext()->msg( 'smw_printername_' . $this->mFormat )->text(); - } - - /** - * @see SMW\ResultPrinter::getResultText - * - * @param SMWQueryResult $queryResult - * @param $outputmode - * - * @return string - */ - protected function getResultText( SMWQueryResult $queryResult, $outputmode ) { - if ( $this->mFormat == 'template' && !$this->mTemplate ) { - $queryResult->addErrors( array( - $this->getContext()->msg( 'smw_notemplategiven' )->inContentLanguage()->text() - ) ); - return ''; - } - - $this->initializePrintingParameters( $queryResult ); - - $result = ''; - - // Set up floating divs if there's more than one column - if ( $this->mColumns > 1 ) { - $result .= '<div style="float: left; width: ' . $this->columnWidth . '%">' . "\n"; - } - - $result .= $this->header; - - if ( $this->mIntroTemplate !== '' ) { - $result .= "{{" . $this->mIntroTemplate . $this->addCommonTemplateParameters( $queryResult ) . "}}"; - } - - while ( $row = $queryResult->getNext() ) { - $result .= $this->getRowText( $row, $queryResult ); - } - - if ( $this->mOutroTemplate !== '' ) { - $result .= "{{" . $this->mOutroTemplate . $this->addCommonTemplateParameters( $queryResult ) . "}}"; - } - - // Make label for finding further results - if ( $this->linkFurtherResults( $queryResult ) && - ( $this->mFormat != 'ol' || $this->getSearchLabel( SMW_OUTPUT_WIKI ) ) ) { - $result .= $this->getFurtherResultsText( $queryResult, $outputmode ); - } - - $result .= $this->footer; - - if ( $this->mColumns > 1 ) { - $result .= "</div>\n" . '<br style="clear: both" />' . "\n"; - } - - // Display default if the result is empty - if ( $result == '' ) { - $result = $this->params['default']; - } - - return $result; - } - - /** - * Initialize the internal parameters that should be used to print this - * list, and reset row counters. - * - * @since 1.9 - * @param SMWQueryResult $queryResult - */ - protected function initializePrintingParameters( SMWQueryResult $queryResult ) { - $this->numRows = 0; - $this->numRowsInColumn = 0; - $this->rowSortkey = ''; - - $this->columnWidth = floor( 100 / $this->mColumns ); - $this->rowsPerColumn = ceil( $queryResult->getCount() / $this->mColumns ); - - // Determine mark-up strings used around list items: - if ( $this->mFormat == 'ul' || $this->mFormat == 'ol' ) { - $this->header = "<" . $this->mFormat . ">\n"; - $this->footer = "</" . $this->mFormat . ">\n"; - $this->rowstart = "\t<li>"; - $this->rowend = "</li>\n"; - } else { // "list" and "template" format - $this->header = ''; - $this->footer = ''; - $this->rowstart = ''; - $this->rowend = ''; - } - - // Define separators for list items - if ( $this->params['format'] !== 'template' ){ - if ( $this->params['format'] === 'list' && $this->params['sep'] === ',' ){ - // Make default list ", , , and " - $this->listsep = ', '; - $this->finallistsep = $this->getContext()->msg( 'smw_finallistconjunct' )->inContentLanguage()->text() . ' '; - } else { - // Allow "_" for encoding spaces, as documented - $this->listsep = str_replace( '_', ' ', $this->params['sep'] ); - $this->finallistsep = $this->listsep; - } - } else { - // No default separators for format "template" - $this->listsep = ''; - $this->finallistsep = ''; - } - } - - /** - * Get result text for one result row as part of getResultText(). - * - * @since 1.9 - * @param SMWResultArray[] $row - * @param SMWQueryResult $res - * @return string - */ - protected function getRowText( array $row, SMWQueryResult $res ) { - $result = ''; - - // Start new column: - if ( $this->numRowsInColumn == $this->rowsPerColumn ) { - // If it's a numbered list, and it's split - // into columns, add in the 'start=' - // attribute so that each additional column - // starts at the right place. This attribute - // is actually deprecated, but it appears to - // still be supported by the major browsers... - if ( $this->mFormat == 'ol' ) { - $header = "<ol start=\"" . ( $this->numRows + 1 ) . "\">"; - } else { - $header = $this->header; - } - - $this->numRowsInColumn = 0; - - $result .= $this->footer . '</div>' . - "<div style=\"float: left; width: {$this->columnWidth}%\">" . - $header; - } - - if ( $this->mTemplate !== '' ) { // Build template code - $this->hasTemplates = true; - $content = $this->mTemplate . $this->getTemplateContent( $row ) . $this->addCommonTemplateParameters( $res ); - $result .= $this->getRowStart( $res ) . '{{' . $content . '}}'; - } else { // Build simple list - $content = $this->getRowListContent( $row ); - $result .= $this->getRowStart( $res ) . $content; - } - - $result .= $this->rowend; - $this->numRows++; - $this->numRowsInColumn++; - $this->rowSortkey = ''; - - return $result; - } - - /** - * Returns row start element - * - * @since 1.9 - * - * @param SMWQueryResult $res - * - * @return string - */ - protected function getRowStart( SMWQueryResult $res ){ - - if ( $this->numRows > 0 && $this->isPlainlist() ) { - // Use comma between "rows" other than the last one: - return ( $this->numRows <= $res->getCount() ) ? $this->listsep : $this->finallistsep; - } - - if ( $this->rowSortkey !== '' ) { - return "\t" . Html::openElement( 'li', - array( 'data-sortkey' => mb_substr( $this->rowSortkey, 0, 1 ) ) - ); - } - - return $this->rowstart; - } - - /** - * Returns text for one result row, formatted as a list. - * - * @since 1.9 - * @todo The inner lists of values per field should use different separators. - * @todo Some spaces are hard-coded here; should probably be part of separators. - * @bug Bad HTML tag escaping with hardcoded exceptions (for datatype _qty) - * - * @param SMWResultArray[] $row - * - * @return string - */ - protected function getRowListContent( array $row ) { - $firstField = true; // is this the first entry in this row? - $extraFields = false; // has anything but the first field been printed? - $result = ''; - - foreach ( $row as $field ) { - $firstValue = true; // is this the first value in this field? - - while ( ( $dataValue = $field->getNextDataValue() ) !== false ) { - - // Add sortkey for all non-list formats - if ( $firstField && $this->params['format'] !== 'list' && - $dataValue->getDataItem()->getDIType() === SMWDataItem::TYPE_WIKIPAGE ) { - $this->rowSortkey = StoreFactory::getStore()->getWikiPageSortKey( $dataValue->getDataItem() ); - } - - $text = $dataValue->getShortText( SMW_OUTPUT_WIKI, $this->getLinker( $firstField ) ); - - if ( !$firstField && !$extraFields ) { // first values after first column - $result .= ' ('; - $extraFields = true; - } elseif ( $extraFields || !$firstValue ) { - // any value after '(' or non-first values on first column - $result .= $this->listsep . ' '; - } - - if ( $firstValue ) { // first value in any field, print header - $firstValue = false; - - if ( ( $this->mShowHeaders != SMW_HEADERS_HIDE ) && ( $field->getPrintRequest()->getLabel() !== '' ) ) { - $result .= $field->getPrintRequest()->getText( SMW_OUTPUT_WIKI, ( $this->mShowHeaders == SMW_HEADERS_PLAIN ? null:$this->mLinker ) ) . ' '; - } - } - - // Display the text with tags for all non-list type outputs and - // where the property is of type _qty (to ensure the highlighter - // is displayed) but for others remove tags so that lists are - // not distorted by unresolved in-text tags - // FIXME This is a hack that limits extendibility of SMW datatypes - // by giving _qty a special status that no other type can have. - if ( $dataValue->getTypeID() === '_qty' || $this->isPlainlist() ) { - $result .= $text; - } else { - $result .= Sanitizer::stripAllTags( $text ); - } - } - - $firstField = false; - } - if ( $extraFields ) $result .= ')'; - - return $result; - } - - /** - * Returns text for one result row, formatted as a template call. - * - * @since 1.9 - * - * @param $row - * - * @return string - */ - protected function getTemplateContent( $row ){ - $wikitext = ''; - - foreach ( $row as $i => $field ) { - $wikitext .= '|' . ( $this->mNamedArgs ? '?' . $field->getPrintRequest()->getLabel() : $i + 1 ) . '='; - $first_value = true; - - while ( ( $text = $field->getNextText( SMW_OUTPUT_WIKI, $this->getLinker( $i == 0 ) ) ) !== false ) { - if ( $first_value ) { - $first_value = false; - } else { - $wikitext .= ', '; - } - $wikitext .= $text; - } - } - - $wikitext .= "|#={$this->numRows}"; - return $wikitext; - } - - protected function addCommonTemplateParameters( $queryResult ) { - return ( $this->mUserParam ? "|userparam=$this->mUserParam" : '' ) . - "|smw-resultquerycondition=" . $queryResult->getQuery()->getQueryString() . - "|smw-resultquerylimit=" . $queryResult->getQuery()->getLimit() . - "|smw-resultqueryoffset=" . $queryResult->getQuery()->getOffset(); - } - - /** - * Get text for further results link. Used only during getResultText(). - * - * @since 1.9 - * @param SMWQueryResult $res - * @param integer $outputMode - * @return string - */ - protected function getFurtherResultsText( SMWQueryResult $res, $outputMode ) { - $link = $this->getFurtherResultsLink( $res, $outputMode ); - return $this->rowstart . ' ' . - $link->getText( SMW_OUTPUT_WIKI, $this->mLinker ) . - $this->rowend; - } - - protected function isPlainlist() { - return $this->mFormat != 'ul' && $this->mFormat != 'ol'; - } - - public function getParameters() { - $params = parent::getParameters(); - - $params['sep'] = array( - 'message' => 'smw-paramdesc-sep', - 'default' => ',', - ); - - $params['template'] = array( - 'message' => 'smw-paramdesc-template', - 'default' => '', - ); - - $params['named args'] = array( - 'type' => 'boolean', - 'message' => 'smw-paramdesc-named_args', - 'default' => false, - ); - - if ( !$this->isPlainlist() ) { - $params['columns'] = array( - 'type' => 'integer', - 'message' => 'smw-paramdesc-columns', - 'default' => 1, - 'range' => array( 1, 10 ), - ); - } - - $params['userparam'] = array( - 'message' => 'smw-paramdesc-userparam', - 'default' => '', - ); - - $params['introtemplate'] = array( - 'message' => 'smw-paramdesc-introtemplate', - 'default' => '', - ); - - $params['outrotemplate'] = array( - 'message' => 'smw-paramdesc-outrotemplate', - 'default' => '', - ); - - return $params; - } -} diff --git a/SemanticMediaWiki/includes/queryprinters/QueryResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/QueryResultPrinter.php deleted file mode 100644 index e71e82b3..00000000 --- a/SemanticMediaWiki/includes/queryprinters/QueryResultPrinter.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult as QueryResult; - -/** - * Interface for SMW result printers. - * - * @license GNU GPL v2+ - * @since 1.8 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author Markus Krötzsch - */ -interface QueryResultPrinter { - - // Constructor restriction: - // Needs to have exactly one required argument $formatName. - // Is allowed to have additional optional arguments. - - /** - * Main entry point: takes an QueryResult and parameters given as key-value-pairs in an array, - * and returns the serialised version of the results, formatted as HTML or Wiki or whatever is - * specified. Normally this is not overwritten by subclasses. - * - * If the outputmode is SMW_OUTPUT_WIKI, then the function will return something that is suitable - * for being used in a MediaWiki parser function, i.e. a wikitext strong *or* an array with flags - * and the string as entry 0. See Parser::setFunctionHook() for documentation on this. In all other - * cases, the function returns just a string. - * - * For outputs SMW_OUTPUT_WIKI and SMW_OUTPUT_HTML, error messages or standard "further results" links - * are directly generated and appended. For SMW_OUTPUT_FILE, only the plain generated text is returned. - * - * @note A note on recursion: some query printers may return wiki code that comes from other pages, - * e.g. from templates that are used in formatting or from embedded result pages. Both kinds of pages - * may contain \#ask queries that do again use new pages, so we must care about recursion. We do so - * by simply counting how often this method starts a subparse and stopping at depth 2. There is one - * special case: if this method is called outside parsing, and the concrete printer returns wiki text, - * and wiki text is requested, then we may return wiki text with sub-queries to the caller. If the - * caller parses this (which is likely) then this will again call us in parse-context and all recursion - * checks catch. Only the first level of parsing is done outside and thus not counted. Thus you - * effectively can get down to level 3. The basic maximal depth of 2 can be changed by setting the - * variable SMWResultPrinter::$maxRecursionDepth (in LocalSettings.php, after enableSemantics()). - * Do this at your own risk. - * - * @param $results QueryResult - * @param $fullParams array - * @param $outputMode integer - * - * @return string - */ - public function getResult( QueryResult $results, array $fullParams, $outputMode ); - - /** - * This function determines the query mode that is to be used for this printer in - * various contexts. The query mode influences how queries to that printer should - * be processed to obtain a result. Possible values are SMWQuery::MODE_INSTANCES - * (retrieve instances), SMWQuery::MODE_NONE (do nothing), SMWQuery::MODE_COUNT - * (get number of results), SMWQuery::MODE_DEBUG (return debugging text). - * Possible values for context are SMWQueryProcessor::SPECIAL_PAGE, - * SMWQueryProcessor::INLINE_QUERY, SMWQueryProcessor::CONCEPT_DESC. - * - * The default implementation always returns SMWQuery::MODE_INSTANCES. File exports - * like RSS will use MODE_INSTANCES on special pages (so that instances are - * retrieved for the export) and MODE_NONE otherwise (displaying just a download link). - * - * @param $context - * - * @return integer - */ - public function getQueryMode( $context ); - - /** - * Get a human readable label for this printer. The default is to - * return just the format identifier. Concrete implementations may - * refer to messages here. The format name is normally not used in - * wiki text but only in forms etc. hence the user language should be - * used when retrieving messages. - * - * @return string - */ - public function getName(); - - /** - * Set whether errors should be shown. By default they are. - * - * @param boolean $show - */ - public function setShowErrors( $show ); - - /** - * Takes a list of parameter definitions and adds those supported by this - * result printer. Most result printers should override this method. - * - * @since 1.8 - * - * @param ParamDefinition[] $definitions - * - * @return array - */ - public function getParamDefinitions( array $definitions ); - - /** - * Returns if the format is an export format. - * - * @since 1.8 - * - * @return boolean - */ - public function isExportFormat(); - -} diff --git a/SemanticMediaWiki/includes/queryprinters/RawResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/RawResultPrinter.php deleted file mode 100644 index c5f97983..00000000 --- a/SemanticMediaWiki/includes/queryprinters/RawResultPrinter.php +++ /dev/null @@ -1,130 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; -use SMWOutputs; -use Html; -use FormatJson; - -/** - * Base class for result printers that use the serialized results - * - * @since 1.9 - * - * @license GNU GPL v2 or later - * @author mwjames - */ -abstract class RawResultPrinter extends ResultPrinter { - - /** - * Returns html output. - * - * @since 1.9 - */ - abstract protected function getHtml( array $data ); - - /** - * Convenience method to register resources - * - * @since 1.9 - * - * @param string $resource - */ - protected function addResources( $resource ) { - SMWOutputs::requireResource( $resource ); - } - - /** - * Convenience method to create a unique id - * - * @since 1.9 - */ - protected function getId( ) { - return 'smw-' . uniqid(); - } - - /** - * Convenience method generating a visual placeholder before any - * JS is registered to indicate that resources (JavaScript, CSS) - * are being loaded and once ready ensure to set - * ( '.smw-spinner' ).hide() - * - * @since 1.9 - */ - protected function createLoadingHtmlPlaceholder() { - $this->addResources( 'ext.smw.style' ); - - return Html::rawElement( - 'div', - array( 'class' => 'smw-spinner left mw-small-spinner' ), - Html::element( - 'p', - array( 'class' => 'text' ), - $this->msg( 'smw-livepreview-loading' )->inContentLanguage()->text() - ) - ); - } - - /** - * @deprecated since 2.0 - */ - protected function loading() { - return $this->createLoadingHtmlPlaceholder(); - } - - /** - * Convenience method to encode output data - * - * @since 1.9 - * - * @param string $id - * @param array $data - */ - protected function encodeToJsonForId( $id, $data ) { - SMWOutputs::requireHeadItem( - $id, - $this->getSkin()->makeVariablesScript( array ( $id => FormatJson::encode( $data ) ) - ) ); - - return $this; - } - - /** - * @deprecated since 2.0 - */ - protected function encode( $id, $data ) { - return $this->encodeToJsonForId( $id, $data ); - } - - /** - * Returns serialised content - * - * @see SMWResultPrinter::getResultText() - * - * @param SMWQueryResult $queryResult - * @param $outputMode - * - * @return string - */ - protected function getResultText( SMWQueryResult $queryResult, $outputMode ) { - - // Add parameters that are only known to the specific printer - $ask = $queryResult->getQuery()->toArray(); - foreach ( $this->params as $key => $value ) { - if ( is_string( $value ) || is_integer( $value ) || is_bool( $value ) ) { - $ask['parameters'][$key] = $value; - } - } - - // Combine all data into one object - $data = array( - 'query' => array( - 'result' => $queryResult->toArray(), - 'ask' => $ask - ) - ); - - return $this->getHtml( $data ); - } -} diff --git a/SemanticMediaWiki/includes/queryprinters/RdfResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/RdfResultPrinter.php deleted file mode 100644 index 9743e083..00000000 --- a/SemanticMediaWiki/includes/queryprinters/RdfResultPrinter.php +++ /dev/null @@ -1,147 +0,0 @@ -<?php - -namespace SMW; - -use SMWQueryResult; -use SMWQuery; -use SMWQueryProcessor; -use SMWPrintRequest; -use SMWExporter; -use SMWTurtleSerializer; -use SMWRDFXMLSerializer; - -/** - * Printer class for generating RDF output - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class RdfResultPrinter extends FileExportPrinter { - - /** - * The syntax to be used for export. May be 'rdfxml' or 'turtle'. - */ - protected $syntax; - - /** - * @see SMWResultPrinter::handleParameters - * - * @since 1.7 - * - * @param array $params - * @param $outputmode - */ - protected function handleParameters( array $params, $outputmode ) { - parent::handleParameters( $params, $outputmode ); - $this->syntax = $params['syntax']; - } - - /** - * @see SMWIExportPrinter::getMimeType - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string - */ - public function getMimeType( SMWQueryResult $queryResult ) { - return $this->syntax == 'turtle' ? 'application/x-turtle' : 'application/xml'; - } - - /** - * @see SMWIExportPrinter::getFileName - * - * @since 1.8 - * - * @param SMWQueryResult $queryResult - * - * @return string|boolean - */ - public function getFileName( SMWQueryResult $queryResult ) { - return $this->syntax == 'turtle' ? 'result.ttl' : 'result.rdf'; - } - - public function getQueryMode( $context ) { - return ( $context == SMWQueryProcessor::SPECIAL_PAGE ) ? SMWQuery::MODE_INSTANCES : SMWQuery::MODE_NONE; - } - - public function getName() { - return wfMessage( 'smw_printername_rdf' )->text(); - } - - protected function getResultText( SMWQueryResult $res, $outputmode ) { - if ( $outputmode == SMW_OUTPUT_FILE ) { // make RDF file - $serializer = $this->syntax == 'turtle' ? new SMWTurtleSerializer() : new SMWRDFXMLSerializer(); - $serializer->startSerialization(); - $serializer->serializeExpData( SMWExporter::getOntologyExpData( '' ) ); - - while ( $row = $res->getNext() ) { - $subjectDi = reset( $row )->getResultSubject(); - $data = SMWExporter::makeExportDataForSubject( $subjectDi ); - - foreach ( $row as $resultarray ) { - $printreq = $resultarray->getPrintRequest(); - $property = null; - - switch ( $printreq->getMode() ) { - case SMWPrintRequest::PRINT_PROP: - $property = $printreq->getData()->getDataItem(); - break; - case SMWPrintRequest::PRINT_CATS: - $property = new SMWDIProperty( '_TYPE' ); - break; - case SMWPrintRequest::PRINT_CCAT: - // not serialised right now - break; - case SMWPrintRequest::PRINT_THIS: - // ignored here (object is always included in export) - break; - } - - if ( !is_null( $property ) ) { - SMWExporter::addPropertyValues( $property, $resultarray->getContent() , $data, $subjectDi ); - } - } - $serializer->serializeExpData( $data ); - } - - $serializer->finishSerialization(); - - return $serializer->flushContent(); - } else { // just make link to feed - $this->isHTML = ( $outputmode == SMW_OUTPUT_HTML ); // yes, our code can be viewed as HTML if requested, no more parsing needed - - return $this->getLink( $res, $outputmode )->getText( $outputmode, $this->mLinker ); - } - } - - /** - * @see SMWResultPrinter::getParamDefinitions - * - * @since 1.8 - * - * @param ParamDefinition[] $definitions - * - * @return array - */ - public function getParamDefinitions( array $definitions ) { - $definitions = parent::getParamDefinitions( $definitions ); - - $definitions['limit']->setDefault( 100 ); - - $definitions['searchlabel']->setDefault( wfMessage( 'smw_rdf_link' )->inContentLanguage()->text() ); - - $definitions[] = array( - 'name' => 'syntax', - 'message' => 'smw-paramdesc-rdfsyntax', - 'values' => array( 'rdfxml', 'turtle' ), - 'default' => 'rdfxml', - ); - - return $definitions; - } - -} diff --git a/SemanticMediaWiki/includes/queryprinters/ResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/ResultPrinter.php deleted file mode 100644 index 3f2f1360..00000000 --- a/SemanticMediaWiki/includes/queryprinters/ResultPrinter.php +++ /dev/null @@ -1,641 +0,0 @@ -<?php - -namespace SMW; -use ParamProcessor\ParamDefinition; -use SMWIResultPrinter, SMWQueryResult, SMWQuery; -use ParserOptions, Sanitizer, DummyLinker, SMWInfolink, Title; - -/** - * Abstract base class for printing query results. - * - * @since 1.9 - * - * @file - * @ingroup SMWQuery - * - * @licence GNU GPL v2 or later - * @author Markus Krötzsch - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author mwjames - */ - -/** - * This group contains all members that are relate to query formatting and - * printing. - * - * @defgroup QueryPrinter QueryPrinter - * @ingroup SMWQuery - */ - -/** - * 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. - * - * @ingroup SMWQuery - */ -abstract class ResultPrinter extends \ContextSource implements QueryResultPrinter { - - /** - * @deprecated Use $params instead. Will be removed in 1.10. - */ - protected $m_params; - - /** - * 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 SMWQueryResult - */ - 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 = array(); - - /** - * 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; - - /** - * Return serialised results in specified format. - * Implemented by subclasses. - */ - abstract protected function getResultText( SMWQueryResult $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 - * @param boolean $useValidator Deprecated since 1.6.2, removal in 1.10 - */ - public function __construct( $format, $inline = true, $useValidator = false ) { - global $smwgQDefaultLinking; - - // Context aware since SMW 1.9 - // - // If someone cleans the constructor, please add - // IContextSource $context = null as for now we leave it - // in order to keep compatibility with the original constructor - $this->setContext( \RequestContext::getMain() ); - - $this->mFormat = $format; - $this->mInline = $inline; - $this->mLinkFirst = ( $smwgQDefaultLinking != 'none' ); - $this->mLinkOthers = ( $smwgQDefaultLinking == 'all' ); - $this->mLinker = class_exists( 'DummyLinker' ) ? new DummyLinker() : new \Linker(); ///TODO: how can we get the default or user skin here (depending on context)? - } - - /** - * @see SMWIResultPrinter::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 SMWQueryResult - * @param $fullParams array - * @param $outputMode integer - * - * @return string - */ - public final function getResult( SMWQueryResult $results, array $fullParams, $outputMode ) { - $this->outputMode = $outputMode; - $this->results = $results; - - $params = array(); - - /** - * @var \IParam $param - */ - foreach ( $fullParams as $param ) { - $params[$param->getName()] = $param->getValue(); - } - - $this->params = $params; - $this->m_params = $params; // Compat, change made in 1.6.3/1.7, removal in 1.10 - $this->fullParams = $fullParams; - - $this->postProcessParameters(); - $this->handleParameters( $this->params, $outputMode ); - - return $this->buildResult( $results ); - } - - /** - * Build and return the HTML result. - * - * @since 1.8 - * - * @param SMWQueryResult $results - * - * @return string - */ - protected function buildResult( SMWQueryResult $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 ) { - 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 ); - } - - if ( $GLOBALS['wgDBtype'] == 'postgres' ) { - $result = pg_unescape_bytea( $result ); - } - - return $result; - } - - /** - * Continuation of getResult that only gets executed for non file outputs. - * - * @since 1.6 - * - * @param string $result - * @param SMWQueryResult $results - * @param integer $outputmode - * - * @return string - */ - protected function handleNonFileResult( $result, SMWQueryResult $results, $outputmode ) { - /** - * @var \Parser $wgParser - */ - global $wgParser; - - $result .= $this->getErrorString( $results ); // append errors - - // Apply intro parameter - if ( ( $this->mIntro ) && ( $results->getCount() > 0 ) ) { - if ( $outputmode == SMW_OUTPUT_HTML && $wgParser->getTitle() instanceof Title ) { - global $wgParser; - $result = $wgParser->recursiveTagParse( $this->mIntro ) . $result; - } else { - $result = $this->mIntro . $result; - } - } - - // Apply outro parameter - if ( ( $this->mOutro ) && ( $results->getCount() > 0 ) ) { - if ( $outputmode == SMW_OUTPUT_HTML && $wgParser->getTitle() instanceof Title ) { - global $wgParser; - $result = $result . $wgParser->recursiveTagParse( $this->mOutro ); - } else { - $result = $result . $this->mOutro; - } - } - - // Preprocess embedded templates if needed - if ( ( !$this->isHTML ) && ( $this->hasTemplates ) ) { - if ( ( $wgParser->getTitle() instanceof Title ) && ( $wgParser->getOptions() instanceof ParserOptions ) ) { - self::$mRecursionDepth++; - - if ( self::$mRecursionDepth <= self::$maxRecursionDepth ) { // restrict recursion - $result = '[[SMW::off]]' . $wgParser->replaceVariables( $result ) . '[[SMW::on]]'; - } else { - $result = ''; /// TODO: explain problem (too much recursive parses) - } - - self::$mRecursionDepth--; - } else { // not during parsing, no preprocessing needed, still protect the result - $result = '[[SMW::off]]' . $result . '[[SMW::on]]'; - } - } - - if ( ( $this->isHTML ) && ( $outputmode == SMW_OUTPUT_WIKI ) ) { - $result = array( $result, 'isHTML' => true ); - } elseif ( ( !$this->isHTML ) && ( $outputmode == SMW_OUTPUT_HTML ) ) { - self::$mRecursionDepth++; - - // check whether we are in an existing parse, or if we should start a new parse for $wgTitle - if ( self::$mRecursionDepth <= self::$maxRecursionDepth ) { // retrict recursion - if ( ( $wgParser->getTitle() instanceof Title ) && ( $wgParser->getOptions() instanceof ParserOptions ) ) { - $result = $wgParser->recursiveTagParse( $result ); - } else { - global $wgTitle; - - $popt = new ParserOptions(); - $popt->setEditSection( false ); - $pout = $wgParser->parse( $result . '__NOTOC__', $wgTitle, $popt ); - - /// NOTE: as of MW 1.14SVN, there is apparently no better way to hide the TOC - \SMWOutputs::requireFromParserOutput( $pout ); - $result = $pout->getText(); - } - } else { - $result = ''; /// TODO: explain problem (too much recursive parses) - } - - self::$mRecursionDepth--; - } - - 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 = str_replace( '_', ' ', $params['intro'] ); - $this->mOutro = str_replace( '_', ' ', $params['outro'] ); - - $this->mSearchlabel = $params['searchlabel'] === false ? null : $params['searchlabel']; - - switch ( $params['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 = str_replace( '_', ' ', $params['default'] ); - - if ( $params['headers'] == 'hide' ) { - $this->mShowHeaders = SMW_HEADERS_HIDE; - } elseif ( $params['headers'] == 'plain' ) { - $this->mShowHeaders = SMW_HEADERS_PLAIN; - } else { - $this->mShowHeaders = SMW_HEADERS_SHOW; - } - } - - /** - * 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). - */ - 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 SMWQueryResult $res - * @param $outputMode - * @param string $classAffix - * - * @return SMWInfolink - */ - protected function getLink( SMWQueryResult $res, $outputMode, $classAffix = '' ) { - $link = $res->getLink(); - - $link->setCaption( $this->getSearchLabel( $outputMode ) ); - - if ( $classAffix !== '' ){ - $link->setStyle( 'smw-' . $this->params['format'] . '-' . Sanitizer::escapeClass( $classAffix ) ); - } - - /** - * @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 SMWQueryResult $res - * @param $outputMode - * - * @return SMWInfolink - */ - protected function getFurtherResultsLink( SMWQueryResult $res, $outputMode ) { - $link = $this->getLink( $res, $outputMode, 'furtherresults' ); - $link->setParameter( $this->params['offset'] + $res->getCount(), 'offset' ); - return $link; - } - - /** - * @see SMWIResultPrinter::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 SMWIResultPrinter::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 SMWQueryResult $res - * - * @return string - */ - protected function getErrorString( SMWQueryResult $res ) { - return $this->mShowErrors ? smwfEncodeMessages( array_merge( $this->mErrors, $res->getErrors() ) ) : ''; - } - - /** - * @see SMWIResultPrinter::setShowErrors - * - * @param boolean $show - */ - public function setShowErrors( $show ) { - $this->mShowErrors = $show; - } - - /** - * If $outputmode is SMW_OUTPUT_HTML, escape special characters occuring 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 SMWQueryResult $results - * - * @return boolean - */ - protected function linkFurtherResults( SMWQueryResult $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; - } - - /** - * Return an array describing the parameters of specifically text-based - * formats, like 'list' and 'table', for use in their getParameters() - * functions - * - * @deprecated since 1.8, removal in 1.10 - * - * @since 1.5.0 - * - * @return array - */ - protected function textDisplayParameters() { - return array(); - } - - /** - * Return an array describing the parameters of the export formats - * like 'rss' and 'csv', for use in their getParameters() functions - * - * @deprecated since 1.8, removal in 1.10 - * - * @since 1.5.0 - * - * @return array - */ - protected function exportFormatParameters() { - return array(); - } - - /** - * 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 array(); - } - - /** - * @see SMWIResultPrinter::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 = array() ) { - $params = array(); - - foreach ( $this->getParamDefinitions( $definitions ) as $param ) { - $params[is_array( $param ) ? $param['name'] : $param->getName()] = $param; - } - - return $params; - } - - /** - * @see SMWIResultPrinter::isExportFormat - * - * @since 1.8 - * - * @return boolean - */ - public function isExportFormat() { - return false; - } - -} diff --git a/SemanticMediaWiki/includes/queryprinters/TableResultPrinter.php b/SemanticMediaWiki/includes/queryprinters/TableResultPrinter.php deleted file mode 100644 index d27f9931..00000000 --- a/SemanticMediaWiki/includes/queryprinters/TableResultPrinter.php +++ /dev/null @@ -1,225 +0,0 @@ -<?php - -namespace SMW; - -use SMWResultArray; -use SMWQueryResult; -use SMWQueryProcessor; -use SMWPrintRequest; - -/** - * Print query results in tables - * - * @since 1.5.3 - * - * @file - * - * @license GNU GPL v2 or later - * @author Markus Krötzsch - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author mwjames - */ - -/** - * Print query results in tables - * - * @ingroup QueryPrinter - */ -class TableResultPrinter extends ResultPrinter { - - /** - * @note grep search smw_printername_table, smw_printername_broadtable - * @codeCoverageIgnore - * - * @return string - */ - public function getName() { - return $this->msg( 'smw_printername_' . $this->mFormat )->text(); - } - - /** - * Returns a table - * - * @param SMWQueryResult $res - * @param $outputmode integer - * - * @return string - */ - protected function getResultText( SMWQueryResult $res, $outputmode ) { - $result = ''; - - $this->isHTML = ( $outputmode === SMW_OUTPUT_HTML ); - $this->tableFormatter = new TableFormatter( $this->isHTML ); - - $columnClasses = array(); - - - if ( $this->mShowHeaders != SMW_HEADERS_HIDE ) { // building headers - $headers = array(); - - foreach ( $res->getPrintRequests() as /* SMWPrintRequest */ $pr ) { - $attribs = array(); - $columnClass = str_replace( array( ' ', '_' ), '-', strip_tags( $pr->getText( SMW_OUTPUT_WIKI ) ) ); - $attribs['class'] = $columnClass; - // Also add this to the array of classes, for - // use in displaying each row. - $columnClasses[] = $columnClass; - $text = $pr->getText( $outputmode, ( $this->mShowHeaders == SMW_HEADERS_PLAIN ? null : $this->mLinker ) ); - - $this->tableFormatter->addTableHeader( ( $text === '' ? ' ' : $text ), $attribs ); - } - } - - while ( $subject = $res->getNext() ) { - $this->getRowForSubject( $subject, $outputmode, $columnClasses ); - $this->tableFormatter->addTableRow(); - } - - // print further results footer - if ( $this->linkFurtherResults( $res ) ) { - $link = $this->getFurtherResultsLink( $res, $outputmode ); - - $this->tableFormatter->addTableCell( - $link->getText( $outputmode, $this->mLinker ), - array( 'class' => 'sortbottom', 'colspan' => $res->getColumnCount() ) - ); - $this->tableFormatter->addTableRow( array( 'class' => 'smwfooter' ) ); - } - - $tableAttrs = array( 'class' => $this->params['class'] ); - - if ( $this->mFormat == 'broadtable' ) { - $tableAttrs['width'] = '100%'; - } - - return $this->tableFormatter->transpose( $this->mShowHeaders !== SMW_HEADERS_HIDE && $this->params['transpose'] )->getTable( $tableAttrs ); - } - - /** - * Gets a single table row for a subject, ie page. - * - * @since 1.6.1 - * - * @param array $subject - * @param $outputmode - * - * @return string - */ - protected function getRowForSubject( array /* of SMWResultArray */ $subject, $outputmode, $columnClasses ) { - - foreach ( $subject as $i => $field ) { - // $columnClasses will be empty if "headers=hide" - // was set. - if ( array_key_exists( $i, $columnClasses ) ) { - $columnClass = $columnClasses[$i]; - } else { - $columnClass = null; - } - - $this->getCellForPropVals( $field, $outputmode, $columnClass ); - } - } - - /** - * Gets a table cell for all values of a property of a subject. - * - * @since 1.6.1 - * - * @param SMWResultArray $resultArray - * @param $outputmode - * - * @return string - */ - protected function getCellForPropVals( SMWResultArray $resultArray, $outputmode, $columnClass ) { - $dataValues = array(); - - while ( ( $dv = $resultArray->getNextDataValue() ) !== false ) { - $dataValues[] = $dv; - } - - $attribs = array(); - $content = null; - - if ( count( $dataValues ) > 0 ) { - $sortkey = $dataValues[0]->getDataItem()->getSortKey(); - $dataValueType = $dataValues[0]->getTypeID(); - - if ( is_numeric( $sortkey ) ) { - $attribs['data-sort-value'] = $sortkey; - } - - $alignment = trim( $resultArray->getPrintRequest()->getParameter( 'align' ) ); - - if ( in_array( $alignment, array( 'right', 'left', 'center' ) ) ) { - $attribs['style'] = "text-align:' . $alignment . ';"; - } - $attribs['class'] = $columnClass . ( $dataValueType !== '' ? ' smwtype' . $dataValueType : '' ); - - $content = $this->getCellContent( - $dataValues, - $outputmode, - $resultArray->getPrintRequest()->getMode() == SMWPrintRequest::PRINT_THIS - ); - } - - $this->tableFormatter->addTableCell( $content, $attribs ); - } - - /** - * Gets the contents for a table cell for all values of a property of a subject. - * - * @since 1.6.1 - * - * @param array $dataValues - * @param $outputmode - * @param boolean $isSubject - * - * @return string - */ - protected function getCellContent( array /* of SMWDataValue */ $dataValues, $outputmode, $isSubject ) { - $values = array(); - - foreach ( $dataValues as $dv ) { - $value = $dv->getShortText( $outputmode, $this->getLinker( $isSubject ) ); - $values[] = $value; - } - - return implode( '<br />', $values ); - } - - /** - * @see SMWResultPrinter::getParamDefinitions - * @codeCoverageIgnore - * - * @since 1.8 - * - * @param ParamDefinition[] $definitions - * - * @return array - */ - public function getParamDefinitions( array $definitions ) { - $params = parent::getParamDefinitions( $definitions ); - - $params['class'] = array( - 'name' => 'class', - 'message' => 'smw-paramdesc-table-class', - 'default' => 'sortable wikitable smwtable', - ); - - $params['transpose'] = array( - 'type' => 'boolean', - 'default' => false, - 'message' => 'smw-paramdesc-table-transpose', - ); - - return $params; - } -} - -/** - * SMWTableResultPrinter - * @codeCoverageIgnore - * - * @deprecated since SMW 1.9 - */ -class_alias( 'SMW\TableResultPrinter', 'SMWTableResultPrinter' ); diff --git a/SemanticMediaWiki/includes/serializer/Deserializer.php b/SemanticMediaWiki/includes/serializer/Deserializer.php deleted file mode 100644 index c692f9b3..00000000 --- a/SemanticMediaWiki/includes/serializer/Deserializer.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -namespace SMW\Deserializers; - -/** - * Borrowed from Serializers\Deserializer as drop-in interface - * - * @since 1.0 - * - * @file - * @ingroup Serialization - * - * @licence GNU GPL v2+ - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -interface Deserializer { - - /** - * @since 1.0 - * - * @param mixed $serialization - * - * @return object - * @throws DeserializationException - */ - public function deserialize( $serialization ); - - /** - * Returns if the deserializer can deserialize the provided object. - * - * @since 1.0 - * - * @param mixed $serialization - * - * @return boolean - */ - public function isDeserializerFor( $serialization ); - -} diff --git a/SemanticMediaWiki/includes/serializer/Deserializers/SemanticDataDeserializer.php b/SemanticMediaWiki/includes/serializer/Deserializers/SemanticDataDeserializer.php deleted file mode 100644 index 3cbd8626..00000000 --- a/SemanticMediaWiki/includes/serializer/Deserializers/SemanticDataDeserializer.php +++ /dev/null @@ -1,212 +0,0 @@ -<?php - -namespace SMW\Deserializers; - -use SMW\SemanticData; -use SMW\DataTypeRegistry; -use SMW\DIProperty; -use SMW\DIWikiPage; - -use SMWContainerSemanticData; -use SMWDIContainer as DIContainer; -use SMWDataItem as DataItem; -use SMWErrorValue as ErrorValue; - -use OutOfBoundsException; - -/** - * SemanticData deserializer - * - * @ingroup Deserializers - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SemanticDataDeserializer implements Deserializer { - - /** - * Cache for already processed Id's which is to minimize lock-up performance - * during unserialization - * - * @var array - */ - protected $dataItemTypeIdCache = array(); - - /** - * @see Deserializers::deserialize - * - * @since 1.9 - * - * @return SemanticData - * @throws OutOfBoundsException - */ - public function deserialize( $data ) { - - $semanticData = null; - - if ( isset( $data['version'] ) && $data['version'] !== 0.1 ) { - throw new OutOfBoundsException( 'Serializer/Unserializer version do not match, please update your data' ); - } - - if ( isset( $data['subject'] ) ) { - $semanticData = new SemanticData( DIWikiPage::doUnserialize( $data['subject'] ) ); - } - - if ( !( $this->isDeserializerFor( $semanticData ) ) ) { - throw new OutOfBoundsException( 'SemanticData could not be created probably due to a missing subject' ); - } - - $this->unserializeSemanticData( $data, $semanticData ); - - return $semanticData; - } - - /** - * @see Deserializers::isDeserializerFor - * - * @since 1.9 - * - * @return boolean - */ - public function isDeserializerFor( $semanticData ) { - return $semanticData instanceOf SemanticData; - } - - /** - * @return null - */ - protected function unserializeSemanticData( $data, &$semanticData ) { - - $property = null; - - if ( !isset( $data['data'] ) ) { - return; - } - - foreach ( $data['data'] as $values ) { - - if ( is_array( $values ) ) { - - foreach ( $values as $key => $value ) { - - /** - * @var DIProperty $property - */ - if ( $key === 'property' ) { - $property = DIProperty::doUnserialize( $value ); - } - - /** - * @var DataItem - */ - if ( $key === 'dataitem' ) { - foreach ( $value as $val ) { - $this->unserializeDataItem( $property, $data, $val, $semanticData ); - } - } - } - } - } - } - - /** - * @return DataItem - */ - protected function unserializeDataItem( $property, $data, $value, $semanticData ) { - - $dataItem = null; - - $type = $this->getDataItemId( $property ); - - // Verify that the current property type definition and the type of the - // property during serialization do match, throw an error value to avoid any - // exception during unserialization caused by the DataItem object due to a - // mismatch of type definitions - if ( $type === $value['type'] ) { - $dataItem = DataItem::newFromSerialization( $value['type'], $value['item'] ); - } else { - $dataItem = $property->getDiWikiPage(); - $property = new DIProperty( DIProperty::TYPE_ERROR ); - - $semanticData->addError( array( - new ErrorValue( $type, 'type mismatch', $property->getLabel() ) - ) ); - - } - - // Check whether the current dataItem has a subobject reference - if ( $dataItem->getDIType() === DataItem::TYPE_WIKIPAGE && $dataItem->getSubobjectName() !== '' ) { - - $dataItem = $this->unserializeSubobject( - $data, - $value['item'], - new SMWContainerSemanticData( $dataItem ) - ); - - } - - // Ensure that errors are collected from a subobject level as well and - // made available at the top - if ( $dataItem instanceOf DIContainer ) { - $semanticData->addError( $dataItem->getSemanticData()->getErrors() ); - } - - if ( $property !== null && $dataItem !== null ) { - $semanticData->addPropertyObjectValue( $property, $dataItem ); - } - - } - - /** - * Resolves properties and dataitems assigned to a subobject recursively - * - * @note The serializer has to make sure to provide a complete data set - * otherwise the subobject is neglected (of course one could set an error - * value to the DIContainer but as of now that seems unnecessary) - * - * @return DIContainer|null - */ - protected function unserializeSubobject( $data, $id, $semanticData ) { - - if ( !isset( $data['sobj'] ) ) { - return null; - } - - foreach ( $data['sobj'] as $subobject ) { - - if ( $subobject['subject'] === $id ) { - $this->unserializeSemanticData( $subobject, $semanticData ); - } - - } - - return new DIContainer( $semanticData ); - } - - /** - * Returns DataItemId for a property - * - * @note findPropertyTypeID is calling the Store to find the - * typeId reference this is costly but at the moment there is no other - * way to determine the typeId - * - * This check is to ensure that during unserialization the correct item - * in terms of its definition is being sought otherwise inconsistencies - * can occur due to type changes of a property between the time of - * the serialization and the deserialization (e.g for when the - * serialization object is stored in cache, DB etc.) - * - * @return integer - */ - protected function getDataItemId( DIProperty $property ) { - - if ( !isset( $this->dataItemTypeIdCache[ $property->getKey() ] ) ) { - $this->dataItemTypeIdCache[ $property->getKey() ] = DataTypeRegistry::getInstance()->getDataItemId( $property->findPropertyTypeID() ); - } - - return $this->dataItemTypeIdCache[ $property->getKey() ]; - } - -} diff --git a/SemanticMediaWiki/includes/serializer/Serializer.php b/SemanticMediaWiki/includes/serializer/Serializer.php deleted file mode 100644 index cc8ad1e5..00000000 --- a/SemanticMediaWiki/includes/serializer/Serializer.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -namespace SMW\Serializers; - -/** - * Borrowed from Serializers\Serializer as drop-in interface - * - * @since 1.0 - * - * @file - * @ingroup Deserialization - * - * @licence GNU GPL v2+ - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -interface Serializer { - - /** - * @since 1.0 - * - * @param mixed $object - * - * @return array|int|string|bool|float A possibly nested structure consisting of only arrays and scalar values - */ - public function serialize( $object ); - - /** - * @since 1.0 - * - * @param mixed $object - * - * @return boolean - */ - public function isSerializerFor( $object ); - -} diff --git a/SemanticMediaWiki/includes/serializer/SerializerFactory.php b/SemanticMediaWiki/includes/serializer/SerializerFactory.php deleted file mode 100644 index a53a4910..00000000 --- a/SemanticMediaWiki/includes/serializer/SerializerFactory.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -namespace SMW; - -use SMW\Serializers\Serializer; -use SMW\Deserializers\Deserializer; -use SMW\Serializers\SemanticDataSerializer; -use SMW\Deserializers\SemanticDataDeserializer; -use SMW\Serializers\QueryResultSerializer; - -use SMWQueryResult as QueryResult; -use OutOfBoundsException; - -/** - * Factory class for a serializable object - * - * A factory class that assigns registered serializers to an object and - * identifies an unserializer based on the invoked array. - * - * @ingroup Serializers - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SerializerFactory { - - /** - * Initiates serialization of an object - * - * @since 1.9 - * - * @param mixed $object - * - * @return array - */ - public static function serialize( $object ) { - - $serializer = null; - - if ( $object instanceof SemanticData ) { - $serializer = new SemanticDataSerializer; - } elseif ( $object instanceof QueryResult ) { - $serializer = new QueryResultSerializer; - } - - if ( !( $serializer instanceof Serializer ) ) { - throw new OutOfBoundsException( 'For the object no serializer has been registered' ); - } - - return $serializer->serialize( $object ); - } - - /** - * Initiates unserialization of an object - * - * @note Each object is expected to hold the serializer/unserializer reference - * class within in its records otherwise an exception is raised - * - * @since 1.9 - * - * @param array $object - * - * @return mixed - */ - public static function deserialize( array $object ) { - - $deserializer = null; - - if ( isset( $object['serializer'] ) ) { - - switch ( $object['serializer'] ) { - case 'SMW\Serializers\SemanticDataSerializer': - $deserializer = new SemanticDataDeserializer; - break; - default: - $deserializer = null; - } - - } - - if ( !( $deserializer instanceof Deserializer ) ) { - throw new OutOfBoundsException( 'For the object no deserializer has been registered' ); - } - - return $deserializer->deserialize( $object ); - } - -} diff --git a/SemanticMediaWiki/includes/serializer/Serializers/QueryResultSerializer.php b/SemanticMediaWiki/includes/serializer/Serializers/QueryResultSerializer.php deleted file mode 100644 index cd2d3a19..00000000 --- a/SemanticMediaWiki/includes/serializer/Serializers/QueryResultSerializer.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php - -namespace SMW\Serializers; - -use SMW\DataValueFactory; -use SMWDataItem as DataItem; -use SMWPrintRequest; -use SMWResultArray; -use SMWQueryResult as QueryResult; - -use OutOfBoundsException; -use Title; - -/** - * Class for serializing SMWDataItem and SMWQueryResult objects to a context - * independent object consisting of arrays and associative arrays, which can - * be fed directly to json_encode, the MediaWiki API, and similar serializers. - * - * This class is distinct from SMWSerializer and the SMWExpData object - * it takes, in that here semantic context is lost. - * - * @ingroup Serializers - * - * @licence GNU GPL v2+ - * @since 1.7 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class QueryResultSerializer implements Serializer { - - /** - * @see SerializerInterface::serialize - * - * @since 1.9 - * - * @return array - * @throws OutOfBoundsException - */ - public function serialize( $queryResult ) { - - if ( !( $this->isSerializerFor( $queryResult ) ) ) { - throw new OutOfBoundsException( 'Object was not identified as a QueryResult instance' ); - } - - return $this->getSerializedQueryResult( $queryResult ) + array( 'serializer' => __CLASS__, 'version' => 0.5 ); - } - - /** - * @see Serializers::isSerializerFor - * - * @since 1.9 - */ - public function isSerializerFor( $queryResult ) { - return $queryResult instanceof QueryResult; - } - - /** - * Get the serialization for the provided data item. - * - * @since 1.7 - * - * @param SMWDataItem $dataItem - * - * @return mixed - */ - public static function getSerialization( DataItem $dataItem, $printRequest = null ) { - $result = array(); - - switch ( $dataItem->getDIType() ) { - case DataItem::TYPE_WIKIPAGE: - $title = $dataItem->getTitle(); - $result = array( - 'fulltext' => $title->getFullText(), - 'fullurl' => $title->getFullUrl(), - 'namespace' => $title->getNamespace(), - 'exists' => $title->isKnown() - ); - break; - case DataItem::TYPE_NUMBER: - // dataitems and datavalues - // Quantity is a datavalue type that belongs to dataitem - // type number which means in order to identify the correct - // unit, we have re-factor the corresponding datavalue otherwise - // we will not be able to determine the unit - // (unit is part of the datavalue object) - if ( $printRequest !== null && $printRequest->getTypeID() === '_qty' ) { - $diProperty = $printRequest->getData()->getDataItem(); - $dataValue = DataValueFactory::getInstance()->newDataItemValue( $dataItem, $diProperty ); - - $result = array( - 'value' => $dataValue->getNumber(), - 'unit' => $dataValue->getUnit() - ); - } else { - $result = $dataItem->getNumber(); - } - break; - case DataItem::TYPE_GEO: - $result = $dataItem->getCoordinateSet(); - break; - case DataItem::TYPE_TIME: - $result = $dataItem->getMwTimestamp(); - break; - default: - $result = $dataItem->getSerialization(); - break; - } - - return $result; - } - - /** - * Get the serialization for a SMWQueryResult object. - * - * @since 1.7 - * - * @param SMWQueryResult $result - * - * @return array - */ - public static function getSerializedQueryResult( QueryResult $queryResult ) { - $results = array(); - $printRequests = array(); - - foreach ( $queryResult->getPrintRequests() as $printRequest ) { - $printRequests[] = array( - 'label' => $printRequest->getLabel(), - 'typeid' => $printRequest->getTypeID(), - 'mode' => $printRequest->getMode(), - 'format' => $printRequest->getOutputFormat() - ); - } - - /** - * @var DIWikiPage $diWikiPage - * @var SMWPrintRequest $printRequest - */ - foreach ( $queryResult->getResults() as $diWikiPage ) { - - if ( !($diWikiPage->getTitle() instanceof Title ) ) { - continue; - } - - $result = array( 'printouts' => array() ); - - foreach ( $queryResult->getPrintRequests() as $printRequest ) { - $resultArray = new SMWResultArray( $diWikiPage, $printRequest, $queryResult->getStore() ); - - if ( $printRequest->getMode() === SMWPrintRequest::PRINT_THIS ) { - $dataItems = $resultArray->getContent(); - $result += self::getSerialization( array_shift( $dataItems ), $printRequest ); - } else if ( $resultArray->getContent() !== array() ) { - $values = array(); - - foreach ( $resultArray->getContent() as $dataItem ) { - $values[] = self::getSerialization( $dataItem, $printRequest ); - } - $result['printouts'][$printRequest->getLabel()] = $values; - } else { - // For those objects that are empty return an empty array - // to keep the output consistent - $result['printouts'][$printRequest->getLabel()] = array(); - } - } - - $results[$diWikiPage->getTitle()->getFullText()] = $result; - - } - - return array( 'printrequests' => $printRequests, 'results' => $results); - } -} diff --git a/SemanticMediaWiki/includes/serializer/Serializers/SemanticDataSerializer.php b/SemanticMediaWiki/includes/serializer/Serializers/SemanticDataSerializer.php deleted file mode 100644 index 3e4ee080..00000000 --- a/SemanticMediaWiki/includes/serializer/Serializers/SemanticDataSerializer.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -namespace SMW\Serializers; - -use SMW\SemanticData; -use SMWDataItem as DataItem; - -use OutOfBoundsException; - -/** - * SemanticData serializer - * - * @ingroup Serializers - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SemanticDataSerializer implements Serializer { - - /** - * @see Serializer::serialize - * - * @since 1.9 - */ - public function serialize( $semanticData ) { - - if ( !$this->isSerializerFor( $semanticData ) ) { - throw new OutOfBoundsException( 'Object is not supported' ); - } - - return $this->serializeSemanticData( $semanticData ) + array( 'serializer' => __CLASS__, 'version' => 0.1 ); - } - - /** - * @see Serializer::isSerializerFor - * - * @since 1.9 - */ - public function isSerializerFor( $semanticData ) { - return $semanticData instanceof SemanticData; - } - - /** - * @since 1.9 - * - * @return array - */ - protected function serializeSemanticData( SemanticData $semanticData ) { - - $data = array( - 'subject' => $semanticData->getSubject()->getSerialization(), - 'data' => $this->serializeProperty( $semanticData ) - ); - - $subobjects = $this->serializeSubobject( $semanticData->getSubSemanticData() ); - - if ( $subobjects !== array() ) { - $data['sobj'] = $subobjects; - } - - return $data; - } - - /** - * Build property and dataItem serialization record - * - * @return array - */ - protected function serializeProperty( $semanticData ) { - - $properties = array(); - - foreach ( $semanticData->getProperties() as $property ) { - $properties[] = array( - 'property' => $property->getSerialization(), - 'dataitem' => $this->serializeDataItem( $semanticData, $property ) - ); - } - - return $properties; - } - - /** - * Returns DataItem serialization - * - * @note 'type' is added to ensure that during unserialization the type - * definition of the requested data is in alignment with the definition found - * in the system (type changes that can occur during the time between - * serialization and unserialization) - * - * @return array - */ - protected function serializeDataItem( $semanticData, $property ) { - - $dataItems = array(); - - foreach ( $semanticData->getPropertyValues( $property ) as $dataItem ) { - $dataItems[] = array( - 'type' => $dataItem->getDIType(), - 'item' => $dataItem->getSerialization() - ); - } - - return $dataItems; - } - - /** - * Returns all subobjects of a SemanticData instance - * - * @return array - */ - protected function serializeSubobject( $subSemanticData ) { - - $subobjects = array(); - - foreach ( $subSemanticData as $semanticData ) { - $subobjects[] = $this->serializeSemanticData( $semanticData ); - } - - return $subobjects; - } - -} diff --git a/SemanticMediaWiki/includes/specials/SMW_QuerySpecialPage.php b/SemanticMediaWiki/includes/specials/SMW_QuerySpecialPage.php deleted file mode 100644 index 7fcc05cc..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_QuerySpecialPage.php +++ /dev/null @@ -1,170 +0,0 @@ -<?php - -use ParamProcessor\ParamDefinition; -use SMW\ParameterInput; - -/** - * Base class for special pages with ask query interfaces. - * - * Currently contains code that was duplicated in Special:Ask and Special:QueryUI. - * Probably there is more such code to put here. - * - * @since 1.8 - * - * @file - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author mwjames - */ -abstract class SMWQuerySpecialPage extends SpecialPage { - /** - * Display a form section showing the options for a given format, - * based on the getParameters() value for that format's query printer. - * - * @since 1.8 - * - * @param string $format - * @param array $paramValues The current values for the parameters (name => value) - * - * @return string - */ - protected function showFormatOptions( $format, array $paramValues ) { - $definitions = SMWQueryProcessor::getFormatParameters( $format ); - - $optionsHtml = array(); - - /** - * @var ParamProcessor\ParamDefinition $definition - */ - foreach ( $definitions as $name => $definition ) { - // Ignore the format parameter, as we got a special control in the GUI for it already. - if ( $name == 'format' ) { - continue; - } - - // Maybe there is a better way but somehow I couldn't find one therefore - // 'source' display will be omitted where no alternative source was found or - // a source that was marked as default but had no other available options - if ( ( $name == 'source' && count ( $definition->getAllowedValues() ) == 0 ) || ( - $name == 'source' && in_array( 'default', $definition->getAllowedValues() ) && - count ( $definition->getAllowedValues() ) < 2 ) ) { - continue; - } - - $currentValue = array_key_exists( $name, $paramValues ) ? $paramValues[$name] : false; - - $optionsHtml[] = - Html::rawElement( - 'span', - array( - 'class' => $this->isTooltipDisplay() == true ? 'smw-ask-info' : '', - 'word-wrap' => 'break-word', - 'data-info' => $this->msg( $definition->getMessage() )->text() - ), htmlspecialchars( $name ) . ': ' . - $this->showFormatOption( $definition, $currentValue ) - ); - } - - $i = 0; - $n = 0; - $rowHtml = ''; - $resultHtml = ''; - - // Top info text for a collapsed option box - if ( $this->isTooltipDisplay() == true ){ - $resultHtml .= Html::element('div', array( - 'style' => 'margin-bottom:10px;' - ), wfMessage( 'smw-ask-otheroptions-info')->text() - ); - } - - // Table - $resultHtml .= Html::openElement( 'table', array( - 'class' => 'smw-ask-otheroptions', - 'width' => '100%' - ) - ); - $resultHtml .= Html::openElement( 'tbody' ); - - while ( $option = array_shift( $optionsHtml ) ) { - $i++; - - // Collect elements for a row - $rowHtml .= Html::rawElement('td', array(), $option ); - - // Create table row - if ( $i % 3 == 0 ){ - $resultHtml .= Html::rawElement( 'tr', array( - 'style' => 'background: ' . ( $i % 6 == 0 ? 'white' : '#eee' ) - ), $rowHtml - ); - $rowHtml = ''; - $n++; - } - } - - // Ensure left over elements are collected as well - $resultHtml .= Html::rawElement( 'tr', array( - 'style' => 'background: ' . ( $n % 2 == 0 ? '#eee' : 'white' ) - ), $rowHtml - ); - - $resultHtml .= Html::closeElement( 'tbody' ); - $resultHtml .= Html::closeElement( 'table' ); - - return $resultHtml; - } - - /** - * Get the HTML for a single parameter input - * - * @since 1.8 - * - * @param ParamDefinition $definition - * @param mixed $currentValue - * - * @return string - */ - protected function showFormatOption( ParamDefinition $definition, $currentValue ) { - // Init - $description = ''; - - $input = new ParameterInput( $definition ); - $input->setInputName( 'p[' . $definition->getName() . ']' ); - //$input->setInputClass( 'smw-ask-input-' . str_replace( ' ', '-', $definition->getName() ) ); - - if ( $currentValue !== false ) { - $input->setCurrentValue( $currentValue ); - } - - // Parameter description text - if ( !$this->isTooltipDisplay() ) { - $description = Html::rawElement( 'span', array( - 'class' => 'smw-ask-parameter-description' - ), '<br />' . $this->msg( $definition->getMessage() )->text() - ); - } - - return Html::rawElement( 'td', array( - 'overflow' => 'hidden' - ), $input->getHtml() . $description - ); - } - - /** - * Getting Special:Ask user tooltip preference - * - * @since 1.8 - * - * - * @return boolean - */ - protected function isTooltipDisplay() { - // @TODO global - // In case of RequestContext, switch to - // $this->getUser()->getOption( 'smw-prefs-ask-options-tooltip-display' ); - return $GLOBALS['wgUser']->getOption( 'smw-prefs-ask-options-tooltip-display' ); - } -} diff --git a/SemanticMediaWiki/includes/specials/SMW_SpecialAsk.php b/SemanticMediaWiki/includes/specials/SMW_SpecialAsk.php deleted file mode 100644 index 84bbd3ab..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_SpecialAsk.php +++ /dev/null @@ -1,644 +0,0 @@ -<?php - -/** - * This special page for MediaWiki implements a customisable form for - * executing queries outside of articles. - * - * @file SMW_SpecialAsk.php - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - * - * @author Markus Krötzsch - * @author Yaron Koren - * @author Sanyam Goyal - * @author Jeroen De Dauw - * @author mwjames - * - * TODO: Split up the megamoths into sane methods. - */ -class SMWAskPage extends SMWQuerySpecialPage { - - protected $m_querystring = ''; - protected $m_params = array(); - protected $m_printouts = array(); - protected $m_editquery = false; - - protected $params = array(); - - /** - * Constructor. - */ - public function __construct() { - parent::__construct( 'Ask' ); - } - - /** - * Main entrypoint for the special page. - * - * @param string $p - */ - public function execute( $p ) { - global $wgOut, $wgRequest, $smwgQEnabled; - - $this->setHeaders(); - wfProfileIn( 'doSpecialAsk (SMW)' ); - - if ( !$smwgQEnabled ) { - $wgOut->addHTML( '<br />' . wfMessage( 'smw_iq_disabled' )->text() ); - } else { - if ( $wgRequest->getCheck( 'showformatoptions' ) ) { - // handle Ajax action - $format = $wgRequest->getVal( 'showformatoptions' ); - $params = $wgRequest->getArray( 'params' ); - $wgOut->disable(); - echo $this->showFormatOptions( $format, $params ); - } else { - $this->extractQueryParameters( $p ); - $this->makeHTMLResult(); - } - } - - SMWOutputs::commitToOutputPage( $wgOut ); // make sure locally collected output data is pushed to the output! - wfProfileOut( 'doSpecialAsk (SMW)' ); - } - - /** - * This code rather hacky since there are many ways to call that special page, the most involved of - * which is the way that this page calls itself when data is submitted via the form (since the shape - * of the parameters then is governed by the UI structure, as opposed to being governed by reason). - * - * TODO: most of this can probably be killed now we are using Validator - * - * @param string $p - */ - protected function extractQueryParameters( $p ) { - global $wgRequest, $smwgQMaxInlineLimit; - - // First make all inputs into a simple parameter list that can again be parsed into components later. - if ( $wgRequest->getCheck( 'q' ) ) { // called by own Special, ignore full param string in that case - $query_val = $wgRequest->getVal( 'p' ); - - if ( !empty( $query_val ) ) - // p is used for any additional parameters in certain links. - $rawparams = SMWInfolink::decodeParameters( $query_val, false ); - else { - $query_values = $wgRequest->getArray( 'p' ); - - if ( is_array( $query_values ) ) { - foreach ( $query_values as $key => $val ) { - if ( empty( $val ) ) unset( $query_values[$key] ); - } - } - - // p is used for any additional parameters in certain links. - $rawparams = SMWInfolink::decodeParameters( $query_values, false ); - } - } else { // called from wiki, get all parameters - $rawparams = SMWInfolink::decodeParameters( $p, true ); - } - - // Check for q= query string, used whenever this special page calls itself (via submit or plain link): - $this->m_querystring = $wgRequest->getText( 'q' ); - if ( $this->m_querystring !== '' ) { - $rawparams[] = $this->m_querystring; - } - - // Check for param strings in po (printouts), appears in some links and in submits: - $paramstring = $wgRequest->getText( 'po' ); - - if ( $paramstring !== '' ) { // parameters from HTML input fields - $ps = explode( "\n", $paramstring ); // params separated by newlines here (compatible with text-input for printouts) - - foreach ( $ps as $param ) { // add initial ? if omitted (all params considered as printouts) - $param = trim( $param ); - - if ( ( $param !== '' ) && ( $param { 0 } != '?' ) ) { - $param = '?' . $param; - } - - $rawparams[] = $param; - } - } - - // Now parse parameters and rebuilt the param strings for URLs. - list( $this->m_querystring, $this->m_params, $this->m_printouts ) = SMWQueryProcessor::getComponentsFromFunctionParams( $rawparams, false ); - - // Try to complete undefined parameter values from dedicated URL params. - if ( !array_key_exists( 'format', $this->m_params ) ) { - $this->m_params['format'] = 'broadtable'; - } - - if ( !array_key_exists( 'order', $this->m_params ) ) { - $order_values = $wgRequest->getArray( 'order' ); - - if ( is_array( $order_values ) ) { - $this->m_params['order'] = ''; - - foreach ( $order_values as $order_value ) { - if ( $order_value === '' ) $order_value = 'ASC'; - $this->m_params['order'] .= ( $this->m_params['order'] !== '' ? ',' : '' ) . $order_value; - } - } - } - - $this->m_num_sort_values = 0; - - if ( !array_key_exists( 'sort', $this->m_params ) ) { - $sort_values = $wgRequest->getArray( 'sort' ); - if ( is_array( $sort_values ) ) { - $this->m_params['sort'] = implode( ',', $sort_values ); - $this->m_num_sort_values = count( $sort_values ); - } - } - - if ( !array_key_exists( 'offset', $this->m_params ) ) { - $this->m_params['offset'] = $wgRequest->getVal( 'offset' ); - if ( $this->m_params['offset'] === '' ) $this->m_params['offset'] = 0; - } - - if ( !array_key_exists( 'limit', $this->m_params ) ) { - $this->m_params['limit'] = $wgRequest->getVal( 'limit' ); - - if ( $this->m_params['limit'] === '' ) { - $this->m_params['limit'] = ( $this->m_params['format'] == 'rss' ) ? 10 : 20; // Standard limit for RSS. - } - } - - $this->m_params['limit'] = min( $this->m_params['limit'], $smwgQMaxInlineLimit ); - - $this->m_editquery = ( $wgRequest->getVal( 'eq' ) == 'yes' ) || ( $this->m_querystring === '' ); - } - - private function getStoreFromParams( array $params ) { - - $storeId = null; - $source = $params['source']->getValue(); - - if ( $source !== '' ) { - $storeId = $GLOBALS['smwgQuerySources'][$source]; - } - - return \SMW\StoreFactory::getStore( $storeId ); - } - - /** - * TODO: document - */ - protected function makeHTMLResult() { - global $wgOut; - - // TODO: hold into account $smwgAutocompleteInSpecialAsk - - $wgOut->addModules( 'ext.smw.ask' ); - - $result = ''; - $result_mime = false; // output in MW Special page as usual - - // build parameter strings for URLs, based on current settings - $urlArgs['q'] = $this->m_querystring; - - $tmp_parray = array(); - foreach ( $this->m_params as $key => $value ) { - if ( !in_array( $key, array( 'sort', 'order', 'limit', 'offset', 'title' ) ) ) { - $tmp_parray[$key] = $value; - } - } - - $urlArgs['p'] = SMWInfolink::encodeParameters( $tmp_parray ); - $printoutstring = ''; - - /** - * @var SMWPrintRequest $printout - */ - foreach ( $this->m_printouts as $printout ) { - $printoutstring .= $printout->getSerialisation() . "\n"; - } - - if ( $printoutstring !== '' ) { - $urlArgs['po'] = $printoutstring; - } - - if ( array_key_exists( 'sort', $this->m_params ) ) { - $urlArgs['sort'] = $this->m_params['sort']; - } - - if ( array_key_exists( 'order', $this->m_params ) ) { - $urlArgs['order'] = $this->m_params['order']; - } - - if ( $this->m_querystring !== '' ) { - // FIXME: this is a hack - SMWQueryProcessor::addThisPrintout( $this->m_printouts, $this->m_params ); - $params = SMWQueryProcessor::getProcessedParams( $this->m_params, $this->m_printouts ); - $this->m_params['format'] = $params['format']->getValue(); - - $this->params = $params; - - $queryobj = SMWQueryProcessor::createQuery( - $this->m_querystring, - $params, - SMWQueryProcessor::SPECIAL_PAGE , - $this->m_params['format'], - $this->m_printouts - ); - - /** - * @var SMWQueryResult $res - */ - - // Determine query results - $res = $this->getStoreFromParams( $params )->getQueryResult( $queryobj ); - - // Try to be smart for rss/ical if no description/title is given and we have a concept query: - if ( $this->m_params['format'] == 'rss' ) { - $desckey = 'rssdescription'; - $titlekey = 'rsstitle'; - } elseif ( $this->m_params['format'] == 'icalendar' ) { - $desckey = 'icalendardescription'; - $titlekey = 'icalendartitle'; - } else { $desckey = false; } - - if ( ( $desckey ) && ( $queryobj->getDescription() instanceof SMWConceptDescription ) && - ( !isset( $this->m_params[$desckey] ) || !isset( $this->m_params[$titlekey] ) ) ) { - $concept = $queryobj->getDescription()->getConcept(); - - if ( !isset( $this->m_params[$titlekey] ) ) { - $this->m_params[$titlekey] = $concept->getText(); - } - - if ( !isset( $this->m_params[$desckey] ) ) { - // / @bug The current SMWStore will never return SMWConceptValue (an SMWDataValue) here; it might return SMWDIConcept (an SMWDataItem) - $dv = end( \SMW\StoreFactory::getStore()->getPropertyValues( SMWWikiPageValue::makePageFromTitle( $concept ), new SMWDIProperty( '_CONC' ) ) ); - if ( $dv instanceof SMWConceptValue ) { - $this->m_params[$desckey] = $dv->getDocu(); - } - } - } - - $printer = SMWQueryProcessor::getResultPrinter( $this->m_params['format'], SMWQueryProcessor::SPECIAL_PAGE ); - - global $wgRequest; - - $hidequery = $wgRequest->getVal( 'eq' ) == 'no'; - - if ( !$printer->isExportFormat() ) { - if ( $res->getCount() > 0 ) { - if ( $this->m_editquery ) { - $urlArgs['eq'] = 'yes'; - } - elseif ( $hidequery ) { - $urlArgs['eq'] = 'no'; - } - - $navigation = $this->getNavigationBar( $res, $urlArgs ); - $result .= '<div style="text-align: center;">' . "\n" . $navigation . "\n</div>\n"; - $query_result = $printer->getResult( $res, $params, SMW_OUTPUT_HTML ); - - if ( is_array( $query_result ) ) { - $result .= $query_result[0]; - } else { - $result .= $query_result; - } - - $result .= '<div style="text-align: center;">' . "\n" . $navigation . "\n</div>\n"; - } else { - $result = '<div style="text-align: center;">' . wfMessage( 'smw_result_noresults' )->escaped() . '</div>'; - } - } - } - - if ( isset( $printer ) && $printer->isExportFormat() ) { - $wgOut->disable(); - - /** - * @var SMWIExportPrinter $printer - */ - $printer->outputAsFile( $res, $params ); - } else { - if ( $this->m_querystring ) { - $wgOut->setHTMLtitle( $this->m_querystring ); - } else { - $wgOut->setHTMLtitle( wfMessage( 'ask' )->text() ); - } - - $urlArgs['offset'] = $this->m_params['offset']; - $urlArgs['limit'] = $this->m_params['limit']; - - $result = $this->getInputForm( - $printoutstring, - wfArrayToCGI( $urlArgs ) - ) . $result; - - $wgOut->addHTML( $result ); - } - } - - /** - * Generates the Search Box UI - * - * @param string $printoutstring - * @param string $urltail - * - * @return string - */ - protected function getInputForm( $printoutstring, $urltail ) { - global $wgScript; - - $result = ''; - - // Deprecated: Use of SpecialPage::getTitle was deprecated in MediaWiki 1.23 - $title = method_exists( $this, 'getPageTitle') ? $this->getPageTitle() : $this->getTitle(); - - if ( $this->m_editquery ) { - $result .= Html::openElement( 'form', - array( 'action' => $wgScript, 'name' => 'ask', 'method' => 'get' ) ); - $result .= Html::hidden( 'title', $title->getPrefixedDBKey() ); - - // Table for main query and printouts. - $result .= '<table class="smw-ask-query" style="width: 100%;"><tr><th>' . wfMessage( 'smw_ask_queryhead' )->text() . "</th>\n<th>" . wfMessage( 'smw_ask_printhead' )->text() . "<br />\n" . - '<span style="font-weight: normal;">' . wfMessage( 'smw_ask_printdesc' )->text() . '</span>' . "</th></tr>\n" . - '<tr><td style="padding-left: 0px;"><textarea class="smw-ask-query-condition" name="q" cols="20" rows="6">' . htmlspecialchars( $this->m_querystring ) . "</textarea></td>\n" . - '<td style="padding-left: 7px;"><textarea id="add_property" class="smw-ask-query-printout" name="po" cols="20" rows="6">' . htmlspecialchars( $printoutstring ) . '</textarea></td></tr></table>' . "\n"; - - // Format selection - $result .= self::getFormatSelection ( $this->m_params ); - - // @TODO - // Sorting inputs - if ( $GLOBALS['smwgQSortingSupport'] ) { - $result .= '<fieldset class="smw-ask-sorting"><legend>' . wfMessage( 'smw-ask-sorting' )->escaped() . "</legend>\n"; - $result .= self::getSortingOption( $this->m_params ); - $result .= "</fieldset>\n"; - } - - // Other options fieldset - $result .= '<fieldset class="smw-ask-options smwExpandedFieldset"><legend>' . wfMessage( 'smw_ask_otheroptions' )->escaped() . "</legend>\n"; - - // Info text for when the fieldset is collapsed - $result .= Html::element( 'div', array( - 'class' => 'collapsed-info', - 'style' => 'display:none;' - ), wfMessage( 'smw-ask-otheroptions-collapsed-info')->text() - ); - - // Individual options - $result .= "<div id=\"other_options\">" . $this->showFormatOptions( $this->m_params['format'], $this->m_params ) . "</div>"; - $result .= "</fieldset>\n"; - - $urltail = str_replace( '&eq=yes', '', $urltail ) . '&eq=no'; // FIXME: doing it wrong, srysly - - // Submit - $result .= '<br /><input type="submit" value="' . wfMessage( 'smw_ask_submit' )->text() . '"/>' . - '<input type="hidden" name="eq" value="yes"/>' . - Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'Ask' )->getLocalURL( $urltail ), - 'rel' => 'nofollow' - ), - wfMessage( 'smw_ask_hidequery' )->text() - ) . - ' | ' . SMWAskPage::getEmbedToggle() . - ' | <a href="' . htmlspecialchars( wfMessage( 'smw_ask_doculink' )->text() ) . '">' . wfMessage( 'smw_ask_help' )->text() . '</a>' . - "\n</form>"; - } else { // if $this->m_editquery == false - $urltail = str_replace( '&eq=no', '', $urltail ) . '&eq=yes'; - $result .= '<p>' . - Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'Ask' )->getLocalURL( $urltail ), - 'rel' => 'nofollow' - ), - wfMessage( 'smw_ask_editquery' )->text() - ) . - '| ' . SMWAskPage::getEmbedToggle() . - '</p>'; - } - //show|hide inline embed code - $result .= '<div id="inlinequeryembed" style="display: none"><div id="inlinequeryembedinstruct">' . wfMessage( 'smw_ask_embed_instr' )->text() . '</div><textarea id="inlinequeryembedarea" readonly="yes" cols="20" rows="6" onclick="this.select()">' . - '{{#ask:' . htmlspecialchars( $this->m_querystring ) . "\n"; - - foreach ( $this->m_printouts as $printout ) { - $result .= '|' . $printout->getSerialisation() . "\n"; - } - - // Find parameters - foreach ( $this->params as /* IParam */ $param ) { - if ( !$param->wasSetToDefault() ) { - $result .= '|' . htmlspecialchars( $param->getName() ) . '='; - // e.g. sorting returns with an array - $result .= $param->getDefinition()->isList() ? implode( $param->getDefinition()->getDelimiter(), $param->getValue() ) . "\n" : $param->getValue() . "\n"; - } - } - - $result .= '}}</textarea></div><br />'; - - return $result; - } - - /** - * Build the format drop down - * - * @param array - * - * @return string - */ - protected static function getFormatSelection ( $params ) { - $result = ''; - - $printer = SMWQueryProcessor::getResultPrinter( 'broadtable', SMWQueryProcessor::SPECIAL_PAGE ); - $url = SpecialPage::getSafeTitleFor( 'Ask' )->getLocalURL( 'showformatoptions=this.value' ); - - foreach ( $params as $param => $value ) { - if ( $param !== 'format' ) { - $url .= '¶ms[' . rawurlencode( $param ) . ']=' . rawurlencode( $value ); - } - } - - $result .= '<br /><span class="smw-ask-query-format" style=vertical-align:middle;">' . wfMessage( 'smw_ask_format_as' )->text() . ' <input type="hidden" name="eq" value="yes"/>' . "\n" . - Html::openElement( - 'select', - array( - 'class' => 'smw-ask-query-format-selector', - 'id' => 'formatSelector', - 'name' => 'p[format]', - 'data-url' => $url, - ) - ) . "\n" . - ' <option value="broadtable"' . ( $params['format'] == 'broadtable' ? ' selected' : '' ) . '>' . - $printer->getName() . ' (' . wfMessage( 'smw_ask_defaultformat' )->text() . ')</option>' . "\n"; - - $formats = array(); - - foreach ( array_keys( $GLOBALS['smwgResultFormats'] ) as $format ) { - // Special formats "count" and "debug" currently not supported. - if ( $format != 'broadtable' && $format != 'count' && $format != 'debug' ) { - $printer = SMWQueryProcessor::getResultPrinter( $format, SMWQueryProcessor::SPECIAL_PAGE ); - $formats[$format] = $printer->getName(); - } - } - - natcasesort( $formats ); - - foreach ( $formats as $format => $name ) { - $result .= ' <option value="' . $format . '"' . ( $params['format'] == $format ? ' selected' : '' ) . '>' . $name . "</option>\n"; - } - - $result .= "</select></span>\n"; - - return $result; - } - - /** - * Build the sorting/order input - * - * @param array - * - * @return string - */ - protected static function getSortingOption ( $params ) { - $result = ''; - - if ( ! array_key_exists( 'sort', $params ) || ! array_key_exists( 'order', $params ) ) { - $orders = array(); // do not even show one sort input here - } else { - $sorts = explode( ',', $params['sort'] ); - $orders = explode( ',', $params['order'] ); - reset( $sorts ); - } - - foreach ( $orders as $i => $order ) { - $result .= "<div id=\"sort_div_$i\">" . wfMessage( 'smw_ask_sortby' )->text() . ' <input type="text" name="sort[' . $i . ']" value="' . - htmlspecialchars( $sorts[$i] ) . "\" size=\"35\"/>\n" . '<select name="order[' . $i . ']"><option '; - - if ( $order == 'ASC' ) $result .= 'selected="selected" '; - $result .= 'value="ASC">' . wfMessage( 'smw_ask_ascorder' )->text() . '</option><option '; - if ( $order == 'DESC' ) $result .= 'selected="selected" '; - - $result .= 'value="DESC">' . wfMessage( 'smw_ask_descorder' )->text() . "</option></select>\n"; - $result .= '[<a class="smw-ask-delete" data-target="sort_div_' . $i . '" href="#">' . wfMessage( 'delete' )->escaped() . '</a>]' . "\n"; - $result .= "</div>\n"; - } - - $result .= '<div id="sorting_starter" style="display: none">' . wfMessage( 'smw_ask_sortby' )->text() . ' <input type="text" name="sort_num" size="35" />' . "\n"; - $result .= ' <select name="order_num">' . "\n"; - $result .= ' <option value="ASC">' . wfMessage( 'smw_ask_ascorder' )->text() . "</option>\n"; - $result .= ' <option value="DESC">' . wfMessage( 'smw_ask_descorder' )->text() . "</option>\n</select>\n"; - $result .= "</div>\n"; - $result .= '<div id="sorting_main"></div>' . "\n"; - $result .= '<a class="smw-ask-add" href="#">' . wfMessage( 'smw_add_sortcondition' )->escaped() . '</a>' . "\n"; - - return $result; - } - - /** - * TODO: document - * - * @return string - */ - protected static function getEmbedToggle() { - return '<span id="embed_show"><a href="#" rel="nofollow" onclick="' . - "document.getElementById('inlinequeryembed').style.display='block';" . - "document.getElementById('embed_hide').style.display='inline';" . - "document.getElementById('embed_show').style.display='none';" . - "document.getElementById('inlinequeryembedarea').select();" . - '">' . wfMessage( 'smw_ask_show_embed' )->text() . '</a></span>' . - '<span id="embed_hide" style="display: none"><a href="#" rel="nofollow" onclick="' . - "document.getElementById('inlinequeryembed').style.display='none';" . - "document.getElementById('embed_show').style.display='inline';" . - "document.getElementById('embed_hide').style.display='none';" . - '">' . wfMessage( 'smw_ask_hide_embed' )->text() . '</a></span>'; - } - - /** - * Build the navigation for some given query result, reuse url-tail parameters. - * - * @param SMWQueryResult $res - * @param array $urlArgs - * - * @return string - */ - protected function getNavigationBar( SMWQueryResult $res, array $urlArgs ) { - global $smwgQMaxInlineLimit, $wgLang; - - // Bug 49216 - $offset = $res->getQuery()->getOffset(); - $limit = $this->params['limit']->getValue(); - - // Prepare navigation bar. - if ( $offset > 0 ) { - $navigation = Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'Ask' )->getLocalURL( array( - 'offset' => max( 0, $offset - $limit ), - 'limit' => $limit - ) + $urlArgs ), - 'rel' => 'nofollow' - ), - wfMessage( 'smw_result_prev' )->text() - ); - - } else { - $navigation = wfMessage( 'smw_result_prev' )->text(); - } - - // @todo FIXME: i18n: Patchwork text. - $navigation .= - '     <b>' . - wfMessage( 'smw_result_results' )->text() . ' ' . $wgLang->formatNum( $offset + 1 ) . - ' – ' . - $wgLang->formatNum( $offset + $res->getCount() ) . - '</b>    '; - - if ( $res->hasFurtherResults() ) { - $navigation .= Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'Ask' )->getLocalURL( array( - 'offset' => ( $offset + $limit ), - 'limit' => $limit - ) + $urlArgs ), - 'rel' => 'nofollow' - ), - wfMessage( 'smw_result_next' )->text() - ); - } else { - $navigation .= wfMessage( 'smw_result_next' )->text(); - } - - $first = true; - - foreach ( array( 20, 50, 100, 250, 500 ) as $l ) { - if ( $l > $smwgQMaxInlineLimit ) break; - - if ( $first ) { - $navigation .= '        ('; - $first = false; - } else { - $navigation .= ' | '; - } - - if ( $limit != $l ) { - $navigation .= Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'Ask' )->getLocalURL( array( - 'offset' => $offset, - 'limit' => $l - ) + $urlArgs ), - 'rel' => 'nofollow' - ), - $l - ); - } else { - $navigation .= '<b>' . $l . '</b>'; - } - } - - $navigation .= ')'; - - return $navigation; - } -} diff --git a/SemanticMediaWiki/includes/specials/SMW_SpecialBrowse.php b/SemanticMediaWiki/includes/specials/SMW_SpecialBrowse.php deleted file mode 100644 index d8a0eb59..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_SpecialBrowse.php +++ /dev/null @@ -1,428 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - * - * A factbox like view on an article, implemented by a special page. - * - * @author Denny Vrandecic - */ - -/** - * A factbox view on one specific article, showing all the Semantic data about it - * - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - */ -class SMWSpecialBrowse extends SpecialPage { - /// int How many incoming values should be asked for - static public $incomingvaluescount = 8; - /// int How many incoming properties should be asked for - static public $incomingpropertiescount = 21; - /// SMWDataValue Topic of this page - private $subject = null; - /// Text to be set in the query form - private $articletext = ""; - /// bool To display outgoing values? - private $showoutgoing = true; - /// bool To display incoming values? - private $showincoming = false; - /// int At which incoming property are we currently? - private $offset = 0; - - /** - * Constructor - */ - public function __construct() { - global $smwgBrowseShowAll; - parent::__construct( 'Browse', '', true, false, 'default', true ); - if ( $smwgBrowseShowAll ) { - SMWSpecialBrowse::$incomingvaluescount = 21; - SMWSpecialBrowse::$incomingpropertiescount = - 1; - } - } - - /** - * Main entry point for Special Pages - * - * @param[in] $query string Given by MediaWiki - */ - public function execute( $query ) { - global $wgRequest, $wgOut, $smwgBrowseShowAll; - $this->setHeaders(); - // get the GET parameters - $this->articletext = $wgRequest->getVal( 'article' ); - // no GET parameters? Then try the URL - if ( is_null( $this->articletext ) ) { - $params = SMWInfolink::decodeParameters( $query, false ); - reset( $params ); - $this->articletext = current( $params ); - } - - $this->subject = \SMW\DataValueFactory::getInstance()->newTypeIDValue( '_wpg', $this->articletext ); - $offsettext = $wgRequest->getVal( 'offset' ); - $this->offset = ( is_null( $offsettext ) ) ? 0 : intval( $offsettext ); - - $dir = $wgRequest->getVal( 'dir' ); - - if ( $smwgBrowseShowAll ) { - $this->showoutgoing = true; - $this->showincoming = true; - } - - if ( $dir === 'both' || $dir === 'in' ) { - $this->showincoming = true; - } - - if ( $dir === 'in' ) { - $this->showoutgoing = false; - } - - if ( $dir === 'out' ) { - $this->showincoming = false; - } - - $wgOut->addHTML( $this->displayBrowse() ); - SMWOutputs::commitToOutputPage( $wgOut ); // make sure locally collected output data is pushed to the output! - } - - /** - * Create and output HTML including the complete factbox, based on the extracted - * parameters in the execute comment. - * - * @return string A HTML string with the factbox - */ - private function displayBrowse() { - global $wgContLang, $wgOut; - $html = "\n"; - $leftside = !( $wgContLang->isRTL() ); // For right to left languages, all is mirrored - - if ( $this->subject->isValid() ) { - - $html .= $this->displayHead(); - - if ( $this->showoutgoing ) { - $data = \SMW\StoreFactory::getStore()->getSemanticData( $this->subject->getDataItem() ); - $html .= $this->displayData( $data, $leftside ); - $html .= $this->displayCenter(); - } - - if ( $this->showincoming ) { - list( $indata, $more ) = $this->getInData(); - global $smwgBrowseShowInverse; - - if ( !$smwgBrowseShowInverse ) { - $leftside = !$leftside; - } - - $html .= $this->displayData( $indata, $leftside, true ); - $html .= $this->displayBottom( $more ); - } - - $this->articletext = $this->subject->getWikiValue(); - - // Add a bit space between the factbox and the query form - if ( !$this->including() ) { - $html .= "<p>   </p>\n"; - } - } - - if ( !$this->including() ) { - $html .= $this->queryForm(); - } - - $wgOut->addHTML( $html ); - } - - /** - * Creates the HTML table displaying the data of one subject. - * - * @param[in] $data SMWSemanticData The data to be displayed - * @param[in] $left bool Should properties be displayed on the left side? - * @param[in] $incoming bool Is this an incoming? Or an outgoing? - * - * @return A string containing the HTML with the factbox - */ - private function displayData( SMWSemanticData $data, $left = true, $incoming = false ) { - // Some of the CSS classes are different for the left or the right side. - // In this case, there is an "i" after the "smwb-". This is set here. - $ccsPrefix = $left ? 'smwb-' : 'smwb-i'; - - $html = "<table class=\"{$ccsPrefix}factbox\" cellpadding=\"0\" cellspacing=\"0\">\n"; - - $diProperties = $data->getProperties(); - $noresult = true; - foreach ( $diProperties as $key => $diProperty ) { - $dvProperty = \SMW\DataValueFactory::getInstance()->newDataItemValue( $diProperty, null ); - - if ( $dvProperty->isVisible() ) { - $dvProperty->setCaption( $this->getPropertyLabel( $dvProperty, $incoming ) ); - $proptext = $dvProperty->getShortHTMLText( smwfGetLinker() ) . "\n"; - } elseif ( $diProperty->getKey() == '_INST' ) { - $proptext = smwfGetLinker()->specialLink( 'Categories' ); - } elseif ( $diProperty->getKey() == '_REDI' ) { - $proptext = smwfGetLinker()->specialLink( 'Listredirects', 'isredirect' ); - } else { - continue; // skip this line - } - - $head = '<th>' . $proptext . "</th>\n"; - - $body = "<td>\n"; - - $values = $data->getPropertyValues( $diProperty ); - - if ( $incoming && ( count( $values ) >= SMWSpecialBrowse::$incomingvaluescount ) ) { - $moreIncoming = true; - array_pop( $values ); - } else { - $moreIncoming = false; - } - - $first = true; - foreach ( $values as /* SMWDataItem */ $di ) { - if ( $first ) { - $first = false; - } else { - $body .= ', '; - } - - if ( $incoming ) { - $dv = \SMW\DataValueFactory::getInstance()->newDataItemValue( $di, null ); - } else { - $dv = \SMW\DataValueFactory::getInstance()->newDataItemValue( $di, $diProperty ); - } - - $body .= "<span class=\"{$ccsPrefix}value\">" . - $this->displayValue( $dvProperty, $dv, $incoming ) . "</span>\n"; - } - - if ( $moreIncoming ) { // link to the remaining incoming pages: - $body .= Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'SearchByProperty' )->getLocalURL( array( - 'property' => $dvProperty->getWikiValue(), - 'value' => $this->subject->getWikiValue() - ) ) - ), - wfMessage( 'smw_browse_more' )->text() - ); - - } - - $body .= "</td>\n"; - - // display row - $html .= "<tr class=\"{$ccsPrefix}propvalue\">\n" . - ( $left ? ( $head . $body ):( $body . $head ) ) . "</tr>\n"; - $noresult = false; - } // end foreach properties - - if ( $noresult ) { - $html .= "<tr class=\"smwb-propvalue\"><th>   </th><td><em>" . - wfMessage( $incoming ? 'smw_browse_no_incoming':'smw_browse_no_outgoing' )->text() . "</em></td></tr>\n"; - } - $html .= "</table>\n"; - return $html; - } - - /** - * Displays a value, including all relevant links (browse and search by property) - * - * @param[in] $property SMWPropertyValue The property this value is linked to the subject with - * @param[in] $value SMWDataValue The actual value - * @param[in] $incoming bool If this is an incoming or outgoing link - * - * @return string HTML with the link to the article, browse, and search pages - */ - private function displayValue( SMWPropertyValue $property, SMWDataValue $dataValue, $incoming ) { - $linker = smwfGetLinker(); - - $html = $dataValue->getLongHTMLText( $linker ); - - if ( $dataValue->getDataItem() === '_wpg' || $dataValue->getTypeID() === '__sob' ) { - $html .= " " . SMWInfolink::newBrowsingLink( '+', $dataValue->getLongWikiText() )->getHTML( $linker ); - } elseif ( $incoming && $property->isVisible() ) { - $html .= " " . SMWInfolink::newInversePropertySearchLink( '+', $dataValue->getTitle(), $property->getDataItem()->getLabel(), 'smwsearch' )->getHTML( $linker ); - } else { - $html .= $dataValue->getInfolinkText( SMW_OUTPUT_HTML, $linker ); - } - - return $html; - } - - /** - * Displays the subject that is currently being browsed to. - * - * @return A string containing the HTML with the subject line - */ - private function displayHead() { - global $wgOut; - - $wgOut->setHTMLTitle( $this->subject->getTitle() ); - $html = "<table class=\"smwb-factbox\" cellpadding=\"0\" cellspacing=\"0\">\n" . - "<tr class=\"smwb-title\"><td colspan=\"2\">\n" . - $this->subject->getLongHTMLText( smwfGetLinker() ) . "\n" . - "</td></tr>\n</table>\n"; - - return $html; - } - - /** - * Creates the HTML for the center bar including the links with further navigation options. - * - * @return string HTMl with the center bar - */ - private function displayCenter() { - return "<a name=\"smw_browse_incoming\"></a>\n" . - "<table class=\"smwb-factbox\" cellpadding=\"0\" cellspacing=\"0\">\n" . - "<tr class=\"smwb-center\"><td colspan=\"2\">\n" . - ( $this->showincoming ? - $this->linkHere( wfMessage( 'smw_browse_hide_incoming' )->text(), true, false, 0 ): - $this->linkHere( wfMessage( 'smw_browse_show_incoming' )->text(), true, true, $this->offset ) ) . - " \n" . "</td></tr>\n" . "</table>\n"; - } - - /** - * Creates the HTML for the bottom bar including the links with further navigation options. - * - * @param[in] $more bool Are there more inproperties to be displayed? - * @return string HTMl with the bottom bar - */ - private function displayBottom( $more ) { - $html = "<table class=\"smwb-factbox\" cellpadding=\"0\" cellspacing=\"0\">\n" . - "<tr class=\"smwb-center\"><td colspan=\"2\">\n"; - global $smwgBrowseShowAll; - if ( !$smwgBrowseShowAll ) { - if ( ( $this->offset > 0 ) || $more ) { - $offset = max( $this->offset - SMWSpecialBrowse::$incomingpropertiescount + 1, 0 ); - $html .= ( $this->offset == 0 ) ? wfMessage( 'smw_result_prev' )->text(): - $this->linkHere( wfMessage( 'smw_result_prev' )->text(), $this->showoutgoing, true, $offset ); - $offset = $this->offset + SMWSpecialBrowse::$incomingpropertiescount - 1; - // @todo FIXME: i18n patchwork. - $html .= "     <strong>" . wfMessage( 'smw_result_results' )->text() . " " . ( $this->offset + 1 ) . - " – " . ( $offset ) . "</strong>     "; - $html .= $more ? $this->linkHere( wfMessage( 'smw_result_next' )->text(), $this->showoutgoing, true, $offset ):wfMessage( 'smw_result_next' )->text(); - } - } - $html .= " \n" . "</td></tr>\n" . "</table>\n"; - return $html; - } - - /** - * Creates the HTML for a link to this page, with some parameters set. - * - * @param[in] $text string The anchor text for the link - * @param[in] $out bool Should the linked to page include outgoing properties? - * @param[in] $in bool Should the linked to page include incoming properties? - * @param[in] $offset int What is the offset for the incoming properties? - * - * @return string HTML with the link to this page - */ - private function linkHere( $text, $out, $in, $offset ) { - $frag = ( $text == wfMessage( 'smw_browse_show_incoming' )->text() ) ? '#smw_browse_incoming' : ''; - - return Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'Browse' )->getLocalURL( array( - 'offset' => $offset, - 'dir' => $out ? ( $in ? 'both' : 'out' ) : 'in', - 'article' => $this->subject->getLongWikiText() - ) ) . $frag - ), - $text - ); - } - - /** - * Creates a Semantic Data object with the incoming properties instead of the - * usual outproperties. - * - * @return array(SMWSemanticData, bool) The semantic data including all inproperties, and if there are more inproperties left - */ - private function getInData() { - $indata = new SMWSemanticData( $this->subject->getDataItem() ); - $options = new SMWRequestOptions(); - $options->sort = true; - $options->limit = SMWSpecialBrowse::$incomingpropertiescount; - if ( $this->offset > 0 ) $options->offset = $this->offset; - - $inproperties = \SMW\StoreFactory::getStore()->getInProperties( $this->subject->getDataItem(), $options ); - - if ( count( $inproperties ) == SMWSpecialBrowse::$incomingpropertiescount ) { - $more = true; - array_pop( $inproperties ); // drop the last one - } else { - $more = false; - } - - $valoptions = new SMWRequestOptions(); - $valoptions->sort = true; - $valoptions->limit = SMWSpecialBrowse::$incomingvaluescount; - - foreach ( $inproperties as $property ) { - $values = \SMW\StoreFactory::getStore()->getPropertySubjects( $property, $this->subject->getDataItem(), $valoptions ); - foreach ( $values as $value ) { - $indata->addPropertyObjectValue( $property, $value ); - } - } - - return array( $indata, $more ); - } - - /** - * Figures out the label of the property to be used. For outgoing ones it is just - * the text, for incoming ones we try to figure out the inverse one if needed, - * either by looking for an explicitly stated one or by creating a default one. - * - * @param[in] $property SMWPropertyValue The property of interest - * @param[in] $incoming bool If it is an incoming property - * - * @return string The label of the property - */ - private function getPropertyLabel( SMWPropertyValue $property, $incoming = false ) { - global $smwgBrowseShowInverse; - - if ( $incoming && $smwgBrowseShowInverse ) { - $oppositeprop = SMWPropertyValue::makeUserProperty( wfMessage( 'smw_inverse_label_property' )->text() ); - $labelarray = &\SMW\StoreFactory::getStore()->getPropertyValues( $property->getDataItem()->getDiWikiPage(), $oppositeprop->getDataItem() ); - $rv = ( count( $labelarray ) > 0 ) ? $labelarray[0]->getLongWikiText(): - wfMessage( 'smw_inverse_label_default', $property->getWikiValue() )->text(); - } else { - $rv = $property->getWikiValue(); - } - - return $this->unbreak( $rv ); - } - - /** - * Creates the query form in order to quickly switch to a specific article. - * - * @return A string containing the HTML for the form - */ - private function queryForm() { - SMWOutputs::requireResource( 'ext.smw.browse' ); - $title = SpecialPage::getTitleFor( 'Browse' ); - return ' <form name="smwbrowse" action="' . htmlspecialchars( $title->getLocalURL() ) . '" method="get">' . "\n" . - ' <input type="hidden" name="title" value="' . $title->getPrefixedText() . '"/>' . - wfMessage( 'smw_browse_article' )->text() . "<br />\n" . - ' <input type="text" name="article" id="page_input_box" value="' . htmlspecialchars( $this->articletext ) . '" />' . "\n" . - ' <input type="submit" value="' . wfMessage( 'smw_browse_go' )->text() . "\"/>\n" . - " </form>\n"; - } - - /** - * Replace the last two space characters with unbreakable spaces for beautification. - * - * @param[in] $text string Text to be transformed. Does not need to have spaces - * @return string Transformed text - */ - private function unbreak( $text ) { - $nonBreakingSpace = html_entity_decode( ' ', ENT_NOQUOTES, 'UTF-8' ); - $text = preg_replace( '/[\s]/u', $nonBreakingSpace, $text, - 1, $count ); - return $count > 2 ? preg_replace( '/($nonBreakingSpace)/u', ' ', $text, max( 0, $count - 2 ) ):$text; - } -} diff --git a/SemanticMediaWiki/includes/specials/SMW_SpecialOWLExport.php b/SemanticMediaWiki/includes/specials/SMW_SpecialOWLExport.php deleted file mode 100644 index 4dc0601b..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_SpecialOWLExport.php +++ /dev/null @@ -1,186 +0,0 @@ -<?php - -/** - * This special page (Special:ExportRDF) for MediaWiki implements an OWL-export of semantic data, - * gathered both from the annotations in articles, and from metadata already - * present in the database. - * - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - */ -class SMWSpecialOWLExport extends SpecialPage { - - /// Export controller object to be used for serializing data - protected $export_controller; - - public function __construct() { - parent::__construct( 'ExportRDF' ); - } - - public function execute( $page ) { - global $wgOut, $wgRequest; - - $wgOut->setPageTitle( wfMessage( 'exportrdf' )->text() ); - - // see if we can find something to export: - $page = is_null( $page ) ? $wgRequest->getVal( 'page' ) : rawurldecode( $page ); - $pages = false; - - if ( !is_null( $page ) || $wgRequest->getCheck( 'page' ) ) { - $page = is_null( $page ) ? $wgRequest->getCheck( 'text' ) : $page; - - if ( $page !== '' ) { - $pages = array( $page ); - } - } - - if ( $pages === false && $wgRequest->getCheck( 'pages' ) ) { - $pageBlob = $wgRequest->getText( 'pages' ); - - if ( $pageBlob !== '' ) { - $pages = explode( "\n", $wgRequest->getText( 'pages' ) ); - } - } - - if ( $pages !== false ) { - $this->exportPages( $pages ); - return; - } else { - $offset = $wgRequest->getVal( 'offset' ); - - if ( isset( $offset ) ) { - $this->startRDFExport(); - $this->export_controller->printPageList( $offset ); - return; - } else { - $stats = $wgRequest->getVal( 'stats' ); - - if ( isset( $stats ) ) { - $this->startRDFExport(); - $this->export_controller->printWikiInfo(); - return; - } - } - } - - // Nothing exported yet; show user interface: - $this->showForm(); - } - - /** - * Create the HTML user interface for this special page. - */ - protected function showForm() { - global $wgOut, $wgUser, $smwgAllowRecursiveExport, $smwgExportBacklinks, $smwgExportAll; - - $html = '<form name="tripleSearch" action="" method="POST">' . "\n" . - '<p>' . wfMessage( 'smw_exportrdf_docu' )->text() . "</p>\n" . - '<input type="hidden" name="postform" value="1"/>' . "\n" . - '<textarea name="pages" cols="40" rows="10"></textarea><br />' . "\n"; - - if ( $wgUser->isAllowed( 'delete' ) || $smwgAllowRecursiveExport ) { - $html .= '<input type="checkbox" name="recursive" value="1" id="rec"> <label for="rec">' . wfMessage( 'smw_exportrdf_recursive' )->text() . '</label></input><br />' . "\n"; - } - - if ( $wgUser->isAllowed( 'delete' ) || $smwgExportBacklinks ) { - $html .= '<input type="checkbox" name="backlinks" value="1" default="true" id="bl"> <label for="bl">' . wfMessage( 'smw_exportrdf_backlinks' )->text() . '</label></input><br />' . "\n"; - } - - if ( $wgUser->isAllowed( 'delete' ) || $smwgExportAll ) { - $html .= '<br />'; - $html .= '<input type="text" name="date" value="' . date( DATE_W3C, mktime( 0, 0, 0, 1, 1, 2000 ) ) . '" id="date"> <label for="ea">' . wfMessage( 'smw_exportrdf_lastdate' )->text() . '</label></input><br />' . "\n"; - } - - $html .= '<br /><input type="submit" value="' . wfMessage( 'smw_exportrdf_submit' )->text() . "\"/>\n</form>"; - - $wgOut->addHTML( $html ); - } - - /** - * Prepare $wgOut for printing non-HTML data. - */ - protected function startRDFExport() { - global $wgOut, $wgRequest; - - $syntax = $wgRequest->getText( 'syntax' ); - - if ( $syntax === '' ) { - $syntax = $wgRequest->getVal( 'syntax' ); - } - - $wgOut->disable(); - ob_start(); - - if ( $syntax == 'turtle' ) { - $mimetype = 'application/x-turtle'; // may change to 'text/turtle' at some time, watch Turtle development - $serializer = new SMWTurtleSerializer(); - } else { // rdfxml as default - // Only use rdf+xml mimetype if explicitly requested (browsers do - // not support it by default). - // We do not add this parameter to RDF links within the export - // though; it is only meant to help some tools to see that HTML - // included resources are RDF (from there on they should be fine). - $mimetype = ( $wgRequest->getVal( 'xmlmime' ) == 'rdf' ) ? 'application/rdf+xml' : 'application/xml'; - $serializer = new SMWRDFXMLSerializer(); - } - - header( "Content-type: $mimetype; charset=UTF-8" ); - - $this->export_controller = new SMWExportController( $serializer ); - } - - /** - * Export the given pages to RDF. - * @param array $pages containing the string names of pages to be exported - */ - protected function exportPages( $pages ) { - global $wgRequest, $smwgExportBacklinks, $wgUser, $smwgAllowRecursiveExport; - - // Effect: assume "no" from missing parameters generated by checkboxes. - $postform = $wgRequest->getText( 'postform' ) == 1; - - $recursive = 0; // default, no recursion - $rec = $wgRequest->getText( 'recursive' ); - - if ( $rec === '' ) { - $rec = $wgRequest->getVal( 'recursive' ); - } - - if ( ( $rec == '1' ) && ( $smwgAllowRecursiveExport || $wgUser->isAllowed( 'delete' ) ) ) { - $recursive = 1; // users may be allowed to switch it on - } - - $backlinks = $smwgExportBacklinks; // default - $bl = $wgRequest->getText( 'backlinks' ); - - if ( $bl === '' ) { - // TODO: wtf? this does not make a lot of sense... - $bl = $wgRequest->getVal( 'backlinks' ); - } - - if ( ( $bl == '1' ) && ( $wgUser->isAllowed( 'delete' ) ) ) { - $backlinks = true; // admins can always switch on backlinks - } elseif ( ( $bl == '0' ) || ( '' == $bl && $postform ) ) { - $backlinks = false; // everybody can explicitly switch off backlinks - } - - $date = $wgRequest->getText( 'date' ); - if ( $date === '' ) { - $date = $wgRequest->getVal( 'date' ); - } - - if ( $date !== '' ) { - $timeint = strtotime( $date ); - $stamp = date( "YmdHis", $timeint ); - $date = $stamp; - } - - $this->startRDFExport(); - $this->export_controller->enableBacklinks( $backlinks ); - $this->export_controller->printPages( $pages, $recursive, $date ); - } - -} diff --git a/SemanticMediaWiki/includes/specials/SMW_SpecialPageProperty.php b/SemanticMediaWiki/includes/specials/SMW_SpecialPageProperty.php deleted file mode 100644 index c5588a33..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_SpecialPageProperty.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - * - * Special page to show object relation pairs. - * - * @author Denny Vrandecic - */ - -/** - * This special page for Semantic MediaWiki implements a - * view on a object-relation pair, i.e. a page that shows - * all the fillers of a property for a certain page. - * This is typically used for overflow results from other - * dynamic output pages. - * - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - */ -class SMWPageProperty extends SpecialPage { - - /** - * Constructor - */ - public function __construct() { - parent::__construct( 'PageProperty', '', false ); - } - - public function execute( $query ) { - global $wgRequest, $wgOut; - $this->setHeaders(); - - // Get parameters - $pagename = $wgRequest->getVal( 'from' ); - $propname = $wgRequest->getVal( 'type' ); - $limit = $wgRequest->getVal( 'limit', 20 ); - $offset = $wgRequest->getVal( 'offset', 0 ); - - if ( $propname == '' ) { // No GET parameters? Try the URL: - $queryparts = explode( '::', $query ); - $propname = $query; - if ( count( $queryparts ) > 1 ) { - $pagename = $queryparts[0]; - $propname = implode( '::', array_slice( $queryparts, 1 ) ); - } - } - - $subject = \SMW\DataValueFactory::getInstance()->newTypeIDValue( '_wpg', $pagename ); - $pagename = $subject->isValid() ? $subject->getPrefixedText() : ''; - $property = SMWPropertyValue::makeUserProperty( $propname ); - $propname = $property->isValid() ? $property->getWikiValue() : ''; - - // Produce output - $html = ''; - if ( ( $propname === '' ) ) { // no property given, show a message - $html .= wfMessage( 'smw_pp_docu' )->text() . "\n"; - } else { // property given, find and display results - // @todo FIXME: very ugly, needs i18n - $wgOut->setPagetitle( ( $pagename !== '' ? $pagename . ' ':'' ) . $property->getWikiValue() ); - - // get results (get one more, to see if we have to add a link to more) - $options = new SMWRequestOptions(); - $options->limit = $limit + 1; - $options->offset = $offset; - $options->sort = true; - $results = \SMW\StoreFactory::getStore()->getPropertyValues( $pagename !== '' ? $subject->getDataItem() : null, $property->getDataItem(), $options ); - - // prepare navigation bar if needed - $navigation = ''; - if ( ( $offset > 0 ) || ( count( $results ) > $limit ) ) { - if ( $offset > 0 ) { - $navigation .= Html::element( - 'a', - array( - 'href' => $this->getTitle()->getLocalURL( array( - 'offset' => max( 0, $offset - $limit ), - 'limit' => $limit, - 'type' => $propname, - 'from' => $pagename - ) ) - ), - wfMessage( 'smw_result_prev' )->text() - ); - } else { - $navigation = wfMessage( 'smw_result_prev' )->text(); - } - - // @todo FIXME: i18n patchwork. - $navigation .= - '     <b>' . - wfMessage( 'smw_result_results' )->text() . ' ' . - ( $offset + 1 ) . '– ' . ( $offset + min( count( $results ), $limit ) ) . - '</b>    '; - - if ( count( $results ) == ( $limit + 1 ) ) { - $navigation .= Html::element( - 'a', - array( - 'href' => $this->getTitle()->getLocalURL( array( - 'offset' => ( $offset + $limit ), - 'limit' => $limit, - 'type' => $propname, - 'from' => $pagename - ) ) - ), - wfMessage( 'smw_result_next' )->text() - ); - } else { - $navigation .= wfMessage( 'smw_result_next' )->text(); - } - } - - // display results - $html .= '<br />' . $navigation; - if ( count( $results ) == 0 ) { - $html .= wfMessage( 'smw_result_noresults' )->text(); - } else { - $linker = smwfGetLinker(); - $html .= "<ul>\n"; - $count = $limit + 1; - - foreach ( $results as $di ) { - $count--; - if ( $count < 1 ) continue; - - $dv = \SMW\DataValueFactory::getInstance()->newDataItemValue( $di, $property->getDataItem() ); - $html .= '<li>' . $dv->getLongHTMLText( $linker ); // do not show infolinks, the magnifier "+" is ambiguous with the browsing '+' for '_wpg' (see below) - - if ( $property->getDataItem()->findPropertyTypeID() == '_wpg' ) { - $browselink = SMWInfolink::newBrowsingLink( '+', $dv->getLongWikiText() ); - $html .= '  ' . $browselink->getHTML( $linker ); - } - - $html .= "</li> \n"; - } - - $html .= "</ul>\n"; - } - - $html .= $navigation; - } - - // Deprecated: Use of SpecialPage::getTitle was deprecated in MediaWiki 1.23 - $spectitle = method_exists( $this, 'getPageTitle') ? $this->getPageTitle() : $this->getTitle(); - - // Display query form - $html .= '<p> </p>'; - $html .= '<form name="pageproperty" action="' . htmlspecialchars( $spectitle->getLocalURL() ) . '" method="get">' . "\n" . - '<input type="hidden" name="title" value="' . $spectitle->getPrefixedText() . '"/>' ; - $html .= wfMessage( 'smw_pp_from' )->text() . ' <input type="text" name="from" value="' . htmlspecialchars( $pagename ) . '" />' . "   \n"; - $html .= wfMessage( 'smw_pp_type' )->text() . ' <input type="text" name="type" value="' . htmlspecialchars( $propname ) . '" />' . "\n"; - $html .= '<input type="submit" value="' . wfMessage( 'smw_pp_submit' )->text() . "\"/>\n</form>\n"; - - $wgOut->addHTML( $html ); - SMWOutputs::commitToOutputPage( $wgOut ); // make sure locally collected output data is pushed to the output! - } -} diff --git a/SemanticMediaWiki/includes/specials/SMW_SpecialSMWAdmin.php b/SemanticMediaWiki/includes/specials/SMW_SpecialSMWAdmin.php deleted file mode 100644 index 9f71fc77..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_SpecialSMWAdmin.php +++ /dev/null @@ -1,273 +0,0 @@ -<?php - -use SMW\MediaWiki\Jobs\RefreshJob; -use SMW\Settings; -use SMW\StoreFactory; -use SMW\Store; - -/** - * @defgroup SMWSpecialPage - * This group contains all parts of SMW that are maintenance scripts. - * @ingroup SMW - */ - -/** - * @author Markus Krötzsch - * - * This special page for MediaWiki provides an administrative interface - * that allows to execute certain functions related to the maintainance - * of the semantic database. It is restricted to users with siteadmin status. - * - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - */ -class SMWAdmin extends SpecialPage { - - protected $store = null; - - public function __construct() { - parent::__construct( 'SMWAdmin', 'smw-admin' ); - $this->store = StoreFactory::getStore(); - } - - public function setStore( Store $store ) { - $this->store = $store; - } - - public function getStore() { - return $this->store; - } - - public function execute( $par ) { - - if ( !$this->userCanExecute( $this->getUser() ) ) { - // If the user is not authorized, show an error. - $this->displayRestrictionError(); - return; - } - - $this->setHeaders(); - - // FIXME Searching the job table needs to be fixed - // - // SMW shouldn't expose itself to an internal MW DB table at - // this level. If an official Api doesn't provide needed - // functionality, the DB call should be encapsulate within its - // own class - - /**** Get status of refresh job, if any ****/ - $dbr = wfGetDB( DB_SLAVE ); - $row = $dbr->selectRow( 'job', '*', array( 'job_cmd' => 'SMW\RefreshJob' ), __METHOD__ ); - if ( $row !== false ) { // similar to Job::pop_type, but without deleting the job - $title = Title::makeTitleSafe( $row->job_namespace, $row->job_title ); - $blob = (string)$row->job_params !== '' ? unserialize( $row->job_params ) : false; - $refreshjob = Job::factory( $row->job_cmd, $title, $blob, $row->job_id ); - } else { - $refreshjob = null; - } - - /**** Execute actions if any ****/ - switch ( $this->getRequest()->getText( 'action' ) ) { - case 'listsettings': - return $this->actionListSettings(); - case 'idlookup': - return $this->actionIdLookup( $this->getRequest()->getVal( 'objectId' ) ); - case 'updatetables': - return $this->actionUpdateTables(); - case 'refreshstore': - return $this->actionRefreshStore( $refreshjob ); - } - - /**** Normal output ****/ - - $html = '<p>' . wfMessage( 'smw_smwadmin_docu' )->text() . "</p>\n"; - // creating tables and converting contents from older versions - $html .= '<form name="buildtables" action="" method="POST">' . "\n" . - '<input type="hidden" name="action" value="updatetables" />' . "\n"; - $html .= '<br /><h2>' . wfMessage( 'smw_smwadmin_db' )->text() . "</h2>\n" . - '<p>' . wfMessage( 'smw_smwadmin_dbdocu' )->text() . "</p>\n"; - $html .= '<p>' . wfMessage( 'smw_smwadmin_permissionswarn' )->text() . "</p>\n" . - '<input type="hidden" name="udsure" value="yes"/>' . - '<input type="submit" value="' . wfMessage( 'smw_smwadmin_dbbutton' )->text() . '"/></form>' . "\n"; - - $html .= '<br /><h2>' . wfMessage( 'smw_smwadmin_datarefresh' )->text() . "</h2>\n" . - '<p>' . wfMessage( 'smw_smwadmin_datarefreshdocu' )->text() . "</p>\n"; - if ( !is_null( $refreshjob ) ) { - $prog = $refreshjob->getProgress(); - $html .= '<p>' . wfMessage( 'smw_smwadmin_datarefreshprogress' )->text() . "</p>\n" . - '<p><div style="float: left; background: #DDDDDD; border: 1px solid grey; width: 300px; "><div style="background: #AAF; width: ' . - round( $prog * 300 ) . 'px; height: 20px; "> </div></div>  ' . round( $prog * 100, 4 ) . '%</p><br /><br />'; - if ( $GLOBALS['smwgAdminRefreshStore'] ) { - $html .= - '<form name="refreshwiki" action="" method="POST">' . - '<input type="hidden" name="action" value="refreshstore" />' . - '<input type="submit" value="' . wfMessage( 'smw_smwadmin_datarefreshstop' )->escaped() . '" /> ' . - ' <input type="checkbox" name="rfsure" value="stop"/> ' . wfMessage( 'smw_smwadmin_datarefreshstopconfirm' )->escaped() . - '</form>' . "\n"; - } - } elseif ( $GLOBALS['smwgAdminRefreshStore'] ) { - $html .= - '<form name="refreshwiki" action="" method="POST">' . - '<input type="hidden" name="action" value="refreshstore" />' . - '<input type="hidden" name="rfsure" value="yes"/>' . - '<input type="submit" value="' . wfMessage( 'smw_smwadmin_datarefreshbutton' )->text() . '"/>' . - '</form>' . "\n"; - } - - $html .= $this->getSettingsSection(); - $html .= $this->getIdLookupSection(); - $html .= $this->getAnnounceSection(); - $html .= $this->getSupportSection(); - - $this->getOutput()->addHTML( $html ); - } - - protected function getSettingsSection() { - return '<br /><h2>' . $this->msg( 'smw-sp-admin-settings-title' )->text() . "</h2>\n" . - '<p>' . $this->msg( 'smw-sp-admin-settings-docu' )->parse() . "</p>\n". - '<form name="listsettings" action="" method="POST">' . - '<input type="hidden" name="action" value="listsettings" />' . - '<input type="submit" value="' . $this->msg( 'smw-sp-admin-settings-button' )->text() . '"/>' . - '</form>' . "\n"; - } - - protected function getAnnounceSection() { - return '<br /><h2>' . wfMessage( 'smw_smwadmin_announce' )->text() . "</h2>\n" . - '<p>' . wfMessage( 'smw_smwadmin_announcedocu' )->text() . "</p>\n" . - '<p>' . wfMessage( 'smw_smwadmin_announcebutton' )->text() . "</p>\n" . - '<form name="announcewiki" action="http://semantic-mediawiki.org/wiki/Special:SMWRegistry" method="GET">' . - '<input type="hidden" name="url" value="' . $GLOBALS['wgServer'] . str_replace( '$1', '', $GLOBALS['wgArticlePath'] ) . '" />' . - '<input type="hidden" name="return" value="Special:SMWAdmin" />' . - '<input type="submit" value="' . wfMessage( 'smw_smwadmin_announce' )->text() . '"/></form>' . "\n"; - } - - protected function getSupportSection() { - return '<br /><h2>' . wfMessage( 'smw_smwadmin_support' )->text() . "</h2>\n" . - '<p>' . wfMessage( 'smw_smwadmin_supportdocu' )->text() . "</p>\n" . - "<ul>\n" . - '<li>' . wfMessage( 'smw_smwadmin_installfile' )->text() . "</li>\n" . - '<li>' . wfMessage( 'smw_smwadmin_smwhomepage' )->text() . "</li>\n" . - '<li>' . wfMessage( 'smw_smwadmin_mediazilla' )->text() . "</li>\n" . - '<li>' . wfMessage( 'smw_smwadmin_questions' )->text() . "</li>\n" . - "</ul>\n"; - } - - protected function getIdLookupSection() { - - return '<br />' . - Html::element( 'h2', array(), $this->msg( 'smw-sp-admin-idlookup-title' )->text() ) . "\n" . - Html::element( 'p', array(), $this->msg( 'smw-sp-admin-idlookup-docu' )->text() ) . "\n" . - Xml::tags( 'form', array( - 'method' => 'get', - 'action' => $GLOBALS['wgScript'] - ), - Html::hidden( 'title', $this->getContext()->getTitle()->getPrefixedText() ) . - Html::hidden( 'action', 'idlookup' ) . - Xml::inputLabel( $this->msg( 'smw-sp-admin-idlookup-objectid' )->text(), 'objectId', 'objectId', 20, null ) . ' ' . - Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) - ); - } - - protected function actionUpdateTables() { - if ( $GLOBALS['wgRequest']->getText( 'udsure' ) == 'yes' ) { - - $this->printRawOutput( function() { - $result = SMWStore::setupStore(); - if ( $result === true ) { - print '<p><b>' . wfMessage( 'smw_smwadmin_setupsuccess' )->text() . "</b></p>\n"; - } - } ); - - } - } - - protected function actionRefreshStore( $refreshjob ) { - - if ( $GLOBALS['smwgAdminRefreshStore'] ) { - - $sure = $GLOBALS['wgRequest']->getText( 'rfsure' ); - $title = SpecialPage::getTitleFor( 'SMWAdmin' ); - - if ( $sure == 'yes' ) { - if ( is_null( $refreshjob ) ) { // careful, there might be race conditions here - $newjob = new RefreshJob( $title, array( 'spos' => 1, 'prog' => 0, 'rc' => 2 ) ); - $newjob->insert(); - $this->getOutput()->addHTML( '<p>' . wfMessage( 'smw_smwadmin_updatestarted', '<a href="' . htmlspecialchars( $title->getFullURL() ) . '">Special:SMWAdmin</a>' )->text() . '</p>' ); - } else { - $this->getOutput()->addHTML( '<p>' . wfMessage( 'smw_smwadmin_updatenotstarted', '<a href="' . htmlspecialchars( $title->getFullURL() ) . '">Special:SMWAdmin</a>' )->text() . '</p>' ); - } - - } elseif ( $sure == 'stop' ) { - - // FIXME See above comments !! - - $dbw = wfGetDB( DB_MASTER ); - // delete (all) existing iteration jobs - $dbw->delete( 'job', array( 'job_cmd' => 'SMW\RefreshJob' ), __METHOD__ ); - $this->getOutput()->addHTML( '<p>' . wfMessage( 'smw_smwadmin_updatestopped', '<a href="' . htmlspecialchars( $title->getFullURL() ) . '">Special:SMWAdmin</a>' )->text() . '</p>' ); - } else { - $this->getOutput()->addHTML( '<p>' . wfMessage( 'smw_smwadmin_updatenotstopped', '<a href="' . htmlspecialchars( $title->getFullURL() ) . '">Special:SMWAdmin</a>' )->text() . '</p>' ); - } - - } - - } - - protected function actionListSettings() { - $this->printRawOutput( function( $instance ) { - print '<pre>' . $instance->encodeJson( Settings::newFromGlobals()->toArray() ) . '</pre>'; - } ); - } - - protected function actionIdLookup( $objectId ) { - $objectId = (int)$objectId; - - $this->printRawOutput( function( $instance ) use ( $objectId ) { - - $tableName = $instance->getStore()->getObjectIds()->getIdTable(); - - $row = $instance->getStore()->getDatabase()->selectRow( - $tableName, - array( - 'smw_title', - 'smw_namespace', - 'smw_iw', - 'smw_subobject' - ), - 'smw_id=' . $objectId, - __METHOD__ - ); - - print '<pre>' . $instance->encodeJson( array( $objectId, $row ) ) . '</pre>'; - } ); - } - - protected function printRawOutput( $text ) { - $this->getOutput()->disable(); // raw output - ob_start(); - - print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\">\n<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /><title>Semantic MediaWiki</title></head><body><p><pre>"; - // header( "Content-type: text/html; charset=UTF-8" ); - is_callable( $text ) ? $text( $this ) : $text; - print '</pre></p>'; - print '<b> ' . wfMessage( 'smw_smwadmin_return', '<a href="' . htmlspecialchars( SpecialPage::getTitleFor( 'SMWAdmin' )->getFullURL() ) . '">Special:SMWAdmin</a>' )->text() . "</b>\n"; - print '</body></html>'; - - ob_flush(); - flush(); - } - - /** - * @note JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, and - * JSON_UNESCAPED_UNICOD were only added with 5.4 - */ - public function encodeJson( array $input ) { - - if ( defined( 'JSON_PRETTY_PRINT' ) ) { - return json_encode( $input, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); - } - - return FormatJson::encode( $input, true ); - } - -} diff --git a/SemanticMediaWiki/includes/specials/SMW_SpecialSearchByProperty.php b/SemanticMediaWiki/includes/specials/SMW_SpecialSearchByProperty.php deleted file mode 100644 index 4d12797c..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_SpecialSearchByProperty.php +++ /dev/null @@ -1,469 +0,0 @@ -<?php - -/** - * @file - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - * - * A special page to search for entities that have a certain property with - * a certain value. - * - * @author Denny Vrandecic - * @author Daniel Herzig - * @author Markus Kroetzsch - */ - -/** - * This special page for Semantic MediaWiki implements a - * view on a relation-object pair,i.e. a typed backlink. - * For example, it shows me all persons born in Croatia, - * or all winners of the Academy Award for best actress. - * - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - */ -class SMWSearchByProperty extends SpecialPage { - /// string Name of the property searched for - private $propertystring; - /// SMWPropertyValue The property that is searched for - private $property; - /// string Name of the value that is searched for - private $valuestring; - /// SMWDataValue The value that is searched for - private $value; - /// How many results should be displayed - private $limit; - /// At what position are we currently - private $offset; - - /** - * Constructor - */ - public function __construct() { - parent::__construct( 'SearchByProperty' ); - } - - /** - * Main entry point for the special page. - * - * @param string $query Given by MediaWiki - */ - public function execute( $query ) { - global $wgOut; - - $this->setHeaders(); - $this->processParameters( $query ); - $wgOut->addHTML( $this->displaySearchByProperty() ); - $wgOut->addHTML( $this->queryForm() ); - - // push locally collected output data to the output - SMWOutputs::commitToOutputPage( $wgOut ); - } - - /** - * Read and interpret the given parameters. - * - * @since 1.8 - * @param string $query from the web request as given by MW - */ - protected function processParameters( $query ) { - global $wgRequest; - // get the GET parameters - $params = SMWInfolink::decodeParameters( $query, false ); - reset( $params ); - - $inputPropertyString = $wgRequest->getText( 'property', current( $params ) ); - - $inputValueString = $wgRequest->getText( 'value', next( $params ) ); - $inputValueString = str_replace( ' ', ' ', $inputValueString ); - $inputValueString = str_replace( ' ', ' ', $inputValueString ); - - $this->property = SMWPropertyValue::makeUserProperty( $inputPropertyString ); - if ( !$this->property->isValid() ) { - $this->propertystring = $inputPropertyString; - $this->value = null; - $this->valuestring = $inputValueString; - } else { - $this->propertystring = $this->property->getWikiValue(); - $this->value = \SMW\DataValueFactory::getInstance()->newPropertyObjectValue( - $this->property->getDataItem(), - $inputValueString - ); - $this->valuestring = $this->value->isValid() ? - $this->value->getWikiValue() : - $inputValueString; - } - - $limitString = $wgRequest->getVal( 'limit' ); - if ( is_numeric( $limitString ) ) { - $this->limit = intval( $limitString ); - } else { - $this->limit = 20; - } - - $offsetString = $wgRequest->getVal( 'offset' ); - if ( is_numeric( $offsetString ) ) { - $this->offset = intval( $offsetString ); - } else { - $this->offset = 0; - } - } - - /** - * Returns the HTML for the complete search by property. - * - * @todo I18N: some parentheses hardcoded - * @return string HTML of the search by property function - */ - protected function displaySearchByProperty() { - global $wgOut, $smwgSearchByPropertyFuzzy; - $linker = smwfGetLinker(); - - if ( $this->propertystring === '' ) { - return '<p>' . wfMessage( 'smw_sbv_docu' )->text() . "</p>\n"; - } - - if ( is_null( $this->value ) || !$this->value->isValid() ) { - return '<p>' . wfMessage( 'smw_sbv_novalue', $this->property->getShortHTMLText( $linker ) )->text() . "</p>\n"; - } - - $wgOut->setPagetitle( $this->propertystring . ' ' . - $this->value->getShortHTMLText( null ) ); - - $html = ''; - - $exactResults = $this->getExactResults(); - $exactCount = count( $exactResults ); - - if ( $exactCount < ( $this->limit / 3 ) && - $this->value->isNumeric() && $smwgSearchByPropertyFuzzy ) { - - $greaterResults = $this->getNearbyResults( $exactCount, true ); - $smallerResults = $this->getNearbyResults( $exactCount, false ); - - // Calculate how many greater and smaller results should be displayed - $greaterCount = count( $greaterResults ); - $smallerCount = count( $smallerResults ); - - if ( ( $greaterCount + $smallerCount + $exactCount ) > $this->limit ) { - $lhalf = round( ( $this->limit - $exactCount ) / 2 ); - - if ( $lhalf < $greaterCount ) { - if ( $lhalf < $smallerCount ) { - $smallerCount = $lhalf; - $greaterCount = $lhalf; - } else { - $greaterCount = $this->limit - ( $exactCount + $smallerCount ); - } - } else { - $smallerCount = $this->limit - ( $exactCount + $greaterCount ); - } - } - - if ( ( $greaterCount + $smallerCount + $exactCount ) == 0 ) { - $html .= wfMessage( 'smw_result_noresults' )->text(); - } else { - $html .= wfMessage( 'smw_sbv_displayresultfuzzy', $this->property->getShortHTMLText( $linker ), $this->value->getShortHTMLText( $linker ) )->text() . "<br />\n"; - $html .= $this->getResultList( $smallerResults, $smallerCount, false ); - - if ( $exactCount == 0 ) { - //TODO i18n: Hardcoded parentheses. - $html .= "          <em><strong><small>(" . $this->value->getLongHTMLText() . ")</small></strong></em>\n"; - } else { - $html .= $this->getResultList( $exactResults, $exactCount, true, true ); - } - - $html .= $this->getResultList( $greaterResults, $greaterCount, true ); - } - } else { - $html .= wfMessage( 'smw_sbv_displayresult', $this->property->getShortHTMLText( $linker ), $this->value->getShortHTMLText( $linker ) )->text() . "<br />\n"; - - if ( $exactCount == 0 ) { - $html .= wfMessage( 'smw_result_noresults' )->text(); - } else { - if ( $this->offset > 0 || $exactCount > $this->limit ) { - $navi = $this->getNavigationBar( $exactCount ); - } else { - $navi = ''; - } - $html .= $navi . $this->getResultList( $exactResults, $this->limit, true ) . $navi; - } - } - - $html .= '<p> </p>'; - - return $html; - } - - /** - * Creates the HTML for a bullet list with all the results of the set - * query. Values can be highlighted to show exact matches among nearby - * ones. - * - * @todo I18N: some parentheses hardcoded - * - * @since 1.8 (was private displayResults before) - * @param array $results (array of (array of one or two SMWDataValues)) - * @param integer $number How many results should be displayed? -1 for all - * @param boolean $first If less results should be displayed than - * given, should they show the first $number results, or the last - * $number results? - * @param boolean $highlight Should the results be highlighted? - * - * @return string HTML with the bullet list, including header - */ - protected function getResultList( $results, $number, $first, $highlight = false ) { - if ( $number > 0 ) { - $results = $first ? - array_slice( $results, 0 , $number ) : - array_slice( $results, $number ); - } - - $html = ''; - foreach ( $results as $result ) { - $listitem = $result[0]->getLongHTMLText( smwfGetLinker() ); - - // Add browsing link for wikipage results - // Note: non-wikipage results are possible using inverse properties - if ( $result[0]->getTypeID() == '_wpg' ) { - $listitem .= '  ' . SMWInfolink::newBrowsingLink( '+', $result[0]->getLongWikiText() )->getHTML( smwfGetLinker() ); - } - - // Show value if not equal to the value that was searched - // or if the current results are to be highlighted: - if ( array_key_exists( 1, $result ) && - ( $result[1] instanceof SMWDataValue ) && - ( !$this->value->getDataItem()->equals( $result[1]->getDataItem() ) - || $highlight ) ) { - // TODO i18n: Hardcoded parentheses - $listitem .= " <em><small>(" . - $result[1]->getLongHTMLText( smwfGetLinker() ) . - ")</small></em>"; - } - - // Highlight values - if ( $highlight ) { - $listitem = "<strong>$listitem</strong>"; - } - - $html .= "<li>$listitem</li>\n"; - } - - return "<ul>\n$html</ul>\n"; - } - - /** - * Creates the HTML for a navigation bar to show long lists of results. - * Most of the parameters are taken from the object members. - * - * @todo I18N: message patchworking - * - * @param integer $count How many results are currently displayed? - * @return string HTML with the navigation bar - */ - protected function getNavigationBar( $count ) { - global $smwgQMaxInlineLimit; - - if ( $this->offset > 0 ) { - $navigation = Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'SearchByProperty' )->getLocalURL( array( - 'offset' => max( 0, $this->offset - $this->limit ), - 'limit' => $this->limit, - 'property' => $this->property->getWikiValue(), - 'value' => $this->value->getWikiValue() - ) ) - ), - wfMessage( 'smw_result_prev' )->text() - ); - } - else { - $navigation = wfMessage( 'smw_result_prev' )->text(); - } - - // TODO i18n: patchwork messages - $navigation .= - '     <b>' . - wfMessage( 'smw_result_results' )->text() . ' ' . - ( $this->offset + 1 ) . '– ' . - ( $this->offset + min( $count, $this->limit ) ) . - '</b>    '; - - if ( $count > $this->limit ) { - $navigation .= Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'SearchByProperty' )->getLocalURL( array( - 'offset' => $this->offset + $this->limit, - 'limit' => $this->limit, - 'property' => $this->property->getWikiValue(), - 'value' => $this->value->getWikiValue() - ) ) - ), - wfMessage( 'smw_result_next' )->text() - ); - } else { - $navigation .= wfMessage( 'smw_result_next' )->text(); - } - - // Find out which limit values to offer for navigation - $limits = array(); - foreach ( array( 20, 50, 100, 250, 500 ) as $l ) { - if ( $l < $smwgQMaxInlineLimit ) { - $limits[] = $l; - } else { - $limits[] = $smwgQMaxInlineLimit; - break; - } - } - - $first = true; - - foreach ( $limits as $l ) { - if ( $first ) { - $navigation .= '        ('; - $first = false; - } else { - $navigation .= ' ' . wfMessage( 'pipe-separator' )->escaped() . ' '; - } - - if ( $this->limit != $l ) { - $navigation .= Html::element( - 'a', - array( - 'href' => SpecialPage::getSafeTitleFor( 'SearchByProperty' )->getLocalURL( array( - 'offset' => $this->offset, - 'limit' => $l, - 'property' => $this->property->getWikiValue(), - 'value' => $this->value->getWikiValue() - ) ) - ), - $l - ); - } else { - $navigation .= '<b>' . $l . '</b>'; - } - } - - $navigation .= ')'; - - return $navigation; - } - - /** - * Returns all results that have exactly the value on the property. - * - * @return array of array(SMWWikiPageValue, SMWDataValue) with the - * first being the entity, and the second the value - */ - protected function getExactResults() { - $options = new SMWRequestOptions(); - $options->limit = $this->limit + 1; - $options->offset = $this->offset; - $options->sort = true; - - $res = \SMW\StoreFactory::getStore()->getPropertySubjects( - $this->property->getDataItem(), - $this->value->getDataItem(), - $options ); - - $results = array(); - foreach ( $res as $result ) { - $results[] = array( - \SMW\DataValueFactory::getInstance()->newDataItemValue( $result, null ), - $this->value - ); - } - - return $results; - } - - /** - * Returns all results that have a value near to the searched for value - * on the property, ordered, and sorted by ending with the smallest - * one. - * - * @param integer $count How many entities have the exact same value on the property? - * @param integer $greater Should the values be bigger? Set false for smaller values. - * - * @return array of array of SMWWikiPageValue, SMWDataValue with the - * first being the entity, and the second the value - */ - protected function getNearbyResults( $count, $greater = true ) { - $valueDescription = new SMWValueDescription( - $this->value->getDataItem(), - $this->property->getDataItem(), - $greater ? SMW_CMP_GRTR : SMW_CMP_LESS - ); - $someProperty = new SMWSomeProperty( - $this->property->getDataItem(), - $valueDescription - ); - $query = new SMWQuery( $someProperty ); - $query->setLimit( $this->limit ); - $query->sort = true; - $query->sortkeys = array( - $this->property->getDataItem()->getKey() => - ( $greater ? 'ASC' : 'DESC' ) - ); - - // Note: printrequests change the caption of properties they - // get (they expect properties to be given to them). - // Since we want to continue using the property for our - // purposes, we give a clone to the print request. - $printouts = array( - new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, '' ), - new SMWPrintRequest( SMWPrintRequest::PRINT_PROP, '', clone $this->property ) - ); - $query->setExtraPrintouts( $printouts ); - - $queryResults = \SMW\StoreFactory::getStore()->getQueryResult( $query ); - - $result = array(); - while ( $resultArrays = $queryResults->getNext() ) { - $r = array(); - foreach ( $resultArrays as $resultArray ) { - $r[] = $resultArray->getNextDataValue(); - } - // Note: if results have multiple values for the property - // then this code just pick the first, which may not be - // the reason why the result is shown here, i.e., it could - // be out of order. - $result[] = $r; - } - - if ( !$greater ) { - $result = array_reverse( $result ); - } - - return $result; - } - - /** - * Creates the HTML for the query form for this special page. - * - * @return string HTML for the query form - */ - protected function queryForm() { - SMWOutputs::requireResource( 'ext.smw.property' ); - $spectitle = SpecialPage::getTitleFor( 'SearchByProperty' ); - - return '<form name="searchbyproperty" action="' . - htmlspecialchars( $spectitle->getLocalURL() ) . - '" method="get">' . "\n" . - '<input type="hidden" name="title" value="' . - $spectitle->getPrefixedText() . '"/>' . - wfMessage( 'smw_sbv_property' )->text() . - ' <input type="text" id="property_box" name="property" value="' . - htmlspecialchars( $this->propertystring ) . - "\" />   \n" . - wfMessage( 'smw_sbv_value' )->text() . - ' <input type="text" name="value" value="' . - htmlspecialchars( $this->valuestring ) . - "\" />\n" . - '<input type="submit" value="' . - wfMessage( 'smw_sbv_submit' )->text() . - "\"/>\n</form>\n"; - } -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/specials/SMW_SpecialTypes.php b/SemanticMediaWiki/includes/specials/SMW_SpecialTypes.php deleted file mode 100644 index 55e40b4f..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_SpecialTypes.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -use SMW\DataTypeRegistry; -use SMW\DataValueFactory; - -/** - * This special page for MediaWiki provides information about types. Type information is - * stored in the smw_attributes database table, gathered both from the annotations in - * articles, and from metadata already some global variables managed by SMWTypeHandlerFactory, - * and in Type: Wiki pages. This only reports on the Type: Wiki pages. - * - * @file SMW_SpecialTypes.php - * - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - * - * @author Markus Krötzsch - */ -class SMWSpecialTypes extends SpecialPage { - public function __construct() { - parent::__construct( 'Types' ); - } - - public function execute( $param ) { - global $wgOut; - wfProfileIn( 'smwfDoSpecialTypes (SMW)' ); - - $params = SMWInfolink::decodeParameters( $param, false ); - $typeLabel = reset( $params ); - - if ( $typeLabel == false ) { - $wgOut->setPageTitle( wfMessage( 'types' )->text() ); - $html = $this->getTypesList(); - } else { - $typeName = str_replace( '_', ' ', $typeLabel ); - $wgOut->setPageTitle( $typeName ); // Maybe add a better message for this - $html = $this->getTypeProperties( $typeLabel ); - } - - $wgOut->addHTML( $html ); - SMWOutputs::commitToOutputPage( $wgOut ); - - wfProfileOut( 'smwfDoSpecialTypes (SMW)' ); - } - - protected function getTypesList() { - $html = '<p>' . wfMessage( 'smw_types_docu' )->escaped() . "</p><br />\n"; - - $typeLabels = DataTypeRegistry::getInstance()->getKnownTypeLabels(); - asort( $typeLabels, SORT_STRING ); - - $html .= "<ul>\n"; - foreach ( $typeLabels as $typeId => $label ) { - $typeValue = SMWTypesValue::newFromTypeId( $typeId ); - $html .= '<li>' . $typeValue->getLongHTMLText( smwfGetLinker() ) . "</li>\n"; - } - $html .= "</ul>\n"; - - return $html; - } - - protected function getTypeProperties( $typeLabel ) { - global $wgRequest, $smwgTypePagingLimit; - - if ( $smwgTypePagingLimit <= 0 ) return ''; // not too useful, but we comply to this request - - $from = $wgRequest->getVal( 'from' ); - $until = $wgRequest->getVal( 'until' ); - $typeValue = DataValueFactory::getInstance()->newTypeIDValue( '__typ', $typeLabel ); - - if ( !$typeValue->isValid() ) { - return $this->msg( 'smw-special-types-no-such-type' )->escaped(); - } - - $store = \SMW\StoreFactory::getStore(); - $options = SMWPageLister::getRequestOptions( $smwgTypePagingLimit, $from, $until ); - $diWikiPages = $store->getPropertySubjects( new SMWDIProperty( '_TYPE' ), $typeValue->getDataItem(), $options ); - - if ( !$options->ascending ) { - $diWikiPages = array_reverse( $diWikiPages ); - } - - $result = ''; - - if ( count( $diWikiPages ) > 0 ) { - $pageLister = new SMWPageLister( $diWikiPages, null, $smwgTypePagingLimit, $from, $until ); - - $title = $this->getTitleFor( 'Types', $typeLabel ); - $title->setFragment( '#SMWResults' ); // Make navigation point to the result list. - $navigation = $pageLister->getNavigationLinks( $title ); - - $resultNumber = min( $smwgTypePagingLimit, count( $diWikiPages ) ); - $typeName = $typeValue->getLongWikiText(); - - $result .= "<a name=\"SMWResults\"></a><div id=\"mw-pages\">\n" . - '<h2>' . wfMessage( 'smw_type_header', $typeName )->text() . "</h2>\n<p>" . - wfMessage( 'smw_typearticlecount' )->numParams( $resultNumber )->text() . "</p>\n" . - $navigation . $pageLister->formatList() . $navigation . "\n</div>"; - } - - return $result; - } -} diff --git a/SemanticMediaWiki/includes/specials/SMW_SpecialURIResolver.php b/SemanticMediaWiki/includes/specials/SMW_SpecialURIResolver.php deleted file mode 100644 index 46eb24ef..00000000 --- a/SemanticMediaWiki/includes/specials/SMW_SpecialURIResolver.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/** - * This special page solves the URI crisis - * without the need of changing code deep in - * MediaWiki were no hook has ever seen light. - * - * @file - * @ingroup SpecialPage - * - * @ingroup SMWSpecialPage - * @ingroup SpecialPage - * - * @author Denny Vrandecic - */ -class SMWURIResolver extends SpecialPage { - - /** - * Constructor - */ - public function __construct() { - parent::__construct( 'URIResolver', '', false ); - } - - function execute( $query ) { - global $wgOut; - - wfProfileIn( 'SpecialURIResolver::execute (SMW)' ); - - if ( is_null( $query ) || trim( $query ) === '' ) { - if ( stristr( $_SERVER['HTTP_ACCEPT'], 'RDF' ) ) { - $wgOut->redirect( SpecialPage::getTitleFor( 'ExportRDF' )->getFullURL( array( 'stats' => '1' ) ), '303' ); - } else { - $this->setHeaders(); - $wgOut->addHTML( - '<p>' . - wfMessage( 'smw_uri_doc', 'http://www.w3.org/2001/tag/issues.html#httpRange-14' )->parse() . - '</p>' - ); - } - } else { - $query = SMWExporter::decodeURI( $query ); - $query = str_replace( '_', '%20', $query ); - $query = urldecode( $query ); - $title = Title::newFromText( $query ); - - // In case the title doesn't exists throw an error page - if ( $title === null ) { - $wgOut->showErrorPage( 'badtitle', 'badtitletext' ); - } else { - $wgOut->redirect( stristr( $_SERVER['HTTP_ACCEPT'], 'RDF' ) - ? SpecialPage::getTitleFor( 'ExportRDF', $title->getPrefixedText() )->getFullURL( array( 'xmlmime' => 'rdf' ) ) - : $title->getFullURL(), '303' ); - } - } - - wfProfileOut( 'SpecialURIResolver::execute (SMW)' ); - } -} diff --git a/SemanticMediaWiki/includes/specials/SpecialConcepts.php b/SemanticMediaWiki/includes/specials/SpecialConcepts.php deleted file mode 100644 index 791a4421..00000000 --- a/SemanticMediaWiki/includes/specials/SpecialConcepts.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -namespace SMW; - -use SMWThingDescription; -use SMWSomeProperty; -use SMWPageLister; - -use Html; - -/** - * Special page that lists available concepts - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Special page that lists available concepts - * - * @ingroup SpecialPage - */ -class SpecialConcepts extends SpecialPage { - - /** - * @see SpecialPage::__construct - * @codeCoverageIgnore - */ - public function __construct() { - parent::__construct( 'Concepts' ); - } - - /** - * Returns concept pages - * - * @since 1.9 - * - * @param integer $limit - * @param integer $from - * @param integer $until - * - * @return DIWikiPage[] - */ - public function getResults( $limit, $from, $until ) { - $description = new SMWSomeProperty( new DIProperty( '_CONC' ), new SMWThingDescription() ); - $query = SMWPageLister::getQuery( $description, $limit, $from, $until ); - return $this->getStore()->getQueryResult( $query )->getResults(); - } - - /** - * Returns html - * - * @since 1.9 - * - * @param DIWikiPage[] $diWikiPages - * @param integer $limit - * @param integer $from - * @param integer $until - * - * @return string - */ - public function getHtml( $diWikiPages, $limit, $from, $until ) { - $resultNumber = min( $limit, count( $diWikiPages ) ); - $pageLister = new SMWPageLister( $diWikiPages, null, $limit, $from, $until ); - $key = $resultNumber == 0 ? 'smw-sp-concept-empty' : 'smw-sp-concept-count'; - - // Deprecated: Use of SpecialPage::getTitle was deprecated in MediaWiki 1.23 - $title = method_exists( $this, 'getPageTitle') ? $this->getPageTitle() : $this->getTitle(); - - return Html::rawElement( - 'span', - array( 'class' => 'smw-sp-concept-docu' ), - $this->msg( 'smw-sp-concept-docu' )->parse() - ) . - Html::rawElement( - 'div', - array( 'id' => 'mw-pages'), - Html::element( - 'h2', - array(), - $this->msg( 'smw-sp-concept-header' )->text() - ) . - Html::element( - 'span', - array( 'class' => $key ), - $this->msg( $key, $resultNumber )->parse() - ) . ' ' . - $pageLister->getNavigationLinks( $title ) . - $pageLister->formatList() - ); - } - - /** - * Executes and outputs results for available concepts - * - * @since 1.9 - * - * @param array $param - */ - public function execute( $param ) { - Profiler::In( __METHOD__ ); - - $this->getOutput()->setPageTitle( $this->msg( 'concepts' )->text() ); - - $from = $this->getRequest()->getVal( 'from' , '' ); - $until = $this->getRequest()->getVal( 'until', '' ); - $limit = $this->getRequest()->getVal( 'limit', 50 ); - - $diWikiPages = $this->getResults( $limit, $from, $until ); - $diWikiPages = $until !== '' ? array_reverse( $diWikiPages ) : $diWikiPages; - - $this->getOutput()->addHTML( $this->getHtml( $diWikiPages, $limit, $from , $until ) ); - - Profiler::Out( __METHOD__ ); - } -} diff --git a/SemanticMediaWiki/includes/specials/SpecialPage.php b/SemanticMediaWiki/includes/specials/SpecialPage.php deleted file mode 100644 index bbd6b535..00000000 --- a/SemanticMediaWiki/includes/specials/SpecialPage.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -namespace SMW; - -/** - * Semantic MediaWiki SpecialPage base class - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ - -/** - * Semantic MediaWiki SpecialPage base class - * - * @ingroup SpecialPage - * @codeCoverageIgnore - */ -class SpecialPage extends \SpecialPage { - - /** @var Store */ - protected $store = null; - - /** @var Settings */ - protected $settings = null; - - /** - * @see SpecialPage::__construct - * - * @since 1.9 - * - * @param $name - * @param $restriction - */ - public function __construct( $name = '', $restriction = '' ) { - parent::__construct( $name, $restriction ); - $this->store = StoreFactory::getStore(); - } - - /** - * Sets store instance - * - * @since 1.9 - * - * @param Store $store - */ - public function setStore( Store $store ) { - $this->store = $store; - return $this; - } - - /** - * Returns store object - * - * @since 1.9 - * - * @return Store - */ - public function getStore() { - return $this->store; - } - - /** - * Sets Settings object - * - * @since 1.9 - * - * @param Settings $settings - */ - public function setSettings( Settings $settings ) { - $this->settings = $settings; - return $this; - } - - /** - * Returns Settings object - * - * @since 1.9 - * - * @return Store - */ - public function getSettings() { - - if ( $this->settings === null ) { - $this->settings = Settings::newFromGlobals(); - } - - return $this->settings; - } - -} diff --git a/SemanticMediaWiki/includes/specials/SpecialProperties.php b/SemanticMediaWiki/includes/specials/SpecialProperties.php deleted file mode 100644 index d29ffe4f..00000000 --- a/SemanticMediaWiki/includes/specials/SpecialProperties.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -namespace SMW; - -use SMWOutputs; - -/** - * Special page (Special:Properties) for MediaWiki shows all - * used properties - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author mwjames - */ - -/** - * This special page for MediaWiki shows all used properties. - * - * @ingroup SpecialPage - */ -class SpecialProperties extends SpecialPage { - - /** - * @see SpecialPage::__construct - * @codeCoverageIgnore - */ - public function __construct() { - parent::__construct( 'Properties' ); - } - - /** - * @see SpecialPage::execute - */ - public function execute( $param ) { - Profiler::In( __METHOD__ ); - - $out = $this->getOutput(); - - $out->setPageTitle( $this->msg( 'properties' )->text() ); - - $page = new PropertiesQueryPage( $this->getStore(), $this->getSettings() ); - $page->setContext( $this->getContext() ); - - list( $limit, $offset ) = $this->getLimitOffset(); - $page->doQuery( $offset, $limit, $this->getRequest()->getVal( 'property' ) ); - - // Ensure locally collected output data is pushed to the output! - SMWOutputs::commitToOutputPage( $out ); - - Profiler::Out( __METHOD__ ); - } - - /** - * FIXME MW 1.24 wfCheckLimits was deprecated in MediaWiki 1.24 - */ - private function getLimitOffset() { - - if ( method_exists( $this->getRequest(), 'getLimitOffset' ) ) { - return $this->getRequest()->getLimitOffset(); - } - - return wfCheckLimits(); - } - -} diff --git a/SemanticMediaWiki/includes/specials/SpecialSemanticStatistics.php b/SemanticMediaWiki/includes/specials/SpecialSemanticStatistics.php deleted file mode 100644 index eb66418e..00000000 --- a/SemanticMediaWiki/includes/specials/SpecialSemanticStatistics.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -namespace SMW; - -/** - * Class for the Special:SemanticStatistics page - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Daniel M. Herzig - * @author Jeroen De Dauw - */ - -/** - * Class for the Special:SemanticStatistics page - * - * @ingroup SpecialPage - */ -class SpecialSemanticStatistics extends SpecialPage { - - /** - * @see SpecialPage::__construct - * @codeCoverageIgnore - */ - public function __construct() { - parent::__construct( 'SemanticStatistics' ); - } - - /** - * @see SpecialPage::execute - */ - public function execute( $param ) { - Profiler::In( __METHOD__ ); - - $semanticStatistics = $this->getStore()->getStatistics(); - $context = $this->getContext(); - $out = $this->getOutput(); - - $out->setPageTitle( $context->msg( 'semanticstatistics' )->text() ); - $out->addHTML( $context->msg( 'smw_semstats_text' - )->numParams( - $semanticStatistics['PROPUSES'], - $semanticStatistics['USEDPROPS'], - $semanticStatistics['OWNPAGE'], - $semanticStatistics['DECLPROPS'] - )->parseAsBlock() - ); - - Profiler::Out( __METHOD__ ); - } -} diff --git a/SemanticMediaWiki/includes/specials/SpecialUnusedProperties.php b/SemanticMediaWiki/includes/specials/SpecialUnusedProperties.php deleted file mode 100644 index 845e5fe3..00000000 --- a/SemanticMediaWiki/includes/specials/SpecialUnusedProperties.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -namespace SMW; - -use SMWOutputs; - -/** - * Special page (Special:UnusedProperties) for MediaWiki shows all - * unused properties - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author mwjames - */ - -/** - * This special page (Special:UnusedProperties) for MediaWiki shows all unused - * properties. - * - * @ingroup SpecialPage - */ -class SpecialUnusedProperties extends SpecialPage { - - /** - * @see SpecialPage::__construct - * @codeCoverageIgnore - */ - public function __construct() { - parent::__construct( 'UnusedProperties' ); - } - - /** - * @see SpecialPage::execute - */ - public function execute( $param ) { - Profiler::In( __METHOD__ ); - - $out = $this->getOutput(); - - $out->setPageTitle( $this->msg( 'unusedproperties' )->text() ); - - $page = new UnusedPropertiesQueryPage( $this->getStore(), $this->getSettings() ); - $page->setContext( $this->getContext() ); - - list( $limit, $offset ) = $this->getLimitOffset(); - $page->doQuery( $offset, $limit ); - - // Ensure locally collected output data is pushed to the output! - SMWOutputs::commitToOutputPage( $out ); - - Profiler::Out( __METHOD__ ); - } - - /** - * FIXME MW 1.24 wfCheckLimits was deprecated in MediaWiki 1.24 - */ - private function getLimitOffset() { - - if ( method_exists( $this->getRequest(), 'getLimitOffset' ) ) { - return $this->getRequest()->getLimitOffset(); - } - - return wfCheckLimits(); - } - -} diff --git a/SemanticMediaWiki/includes/specials/SpecialWantedProperties.php b/SemanticMediaWiki/includes/specials/SpecialWantedProperties.php deleted file mode 100644 index 2f82173c..00000000 --- a/SemanticMediaWiki/includes/specials/SpecialWantedProperties.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -namespace SMW; - -use SMWOutputs; - -/** - * Special page (Special:WantedProperties) for MediaWiki shows all - * wanted properties - * - * @file - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author mwjames - */ - -/** - * This special page (Special:WantedProperties) for MediaWiki shows all wanted - * properties (used but not having a page). - * - * @ingroup SpecialPage - */ -class SpecialWantedProperties extends SpecialPage { - - /** - * @see SpecialPage::__construct - * @codeCoverageIgnore - */ - public function __construct() { - parent::__construct( 'WantedProperties' ); - } - - /** - * @see SpecialPage::execute - */ - public function execute( $param ) { - Profiler::In( __METHOD__ ); - - $out = $this->getOutput(); - - $out->setPageTitle( $this->msg( 'wantedproperties' )->text() ); - - $page = new WantedPropertiesQueryPage( $this->getStore(), $this->getSettings() ); - $page->setContext( $this->getContext() ); - - list( $limit, $offset ) = $this->getLimitOffset(); - $page->doQuery( $offset, $limit ); - - // Ensure locally collected output data is pushed to the output! - // ?? still needed !! - SMWOutputs::commitToOutputPage( $out ); - - Profiler::Out( __METHOD__ ); - } - - /** - * FIXME MW 1.24 wfCheckLimits was deprecated in MediaWiki 1.24 - */ - private function getLimitOffset() { - - if ( method_exists( $this->getRequest(), 'getLimitOffset' ) ) { - return $this->getRequest()->getLimitOffset(); - } - - return wfCheckLimits(); - } - -} diff --git a/SemanticMediaWiki/includes/src/Annotator/CategoryPropertyAnnotator.php b/SemanticMediaWiki/includes/src/Annotator/CategoryPropertyAnnotator.php deleted file mode 100644 index 5e393d11..00000000 --- a/SemanticMediaWiki/includes/src/Annotator/CategoryPropertyAnnotator.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -namespace SMW\Annotator; - -use SMW\PropertyAnnotator; -use SMW\DIProperty; -use SMW\DIWikiPage; -use SMW\Application; - -/** - * Handling category annotation - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class CategoryPropertyAnnotator extends PropertyAnnotatorDecorator { - - /** - * @var array - */ - protected $categories; - - /** - * @var array|null - */ - protected $hiddenCategories = null; - - /** - * @since 1.9 - * - * @param PropertyAnnotator $propertyAnnotator - * @param array $categories - */ - public function __construct( PropertyAnnotator $propertyAnnotator, array $categories ) { - parent::__construct( $propertyAnnotator ); - $this->categories = $categories; - } - - protected function addPropertyValues() { - - $settings = Application::getInstance()->getSettings(); - $namespace = $this->getSemanticData()->getSubject()->getNamespace(); - - foreach ( $this->categories as $catname ) { - - if ( !$settings->get( 'smwgShowHiddenCategories' ) && $this->isHiddenCategory( $catname ) ) { - continue; - } - - if ( $settings->get( 'smwgCategoriesAsInstances' ) && ( $namespace !== NS_CATEGORY ) ) { - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( DIProperty::TYPE_CATEGORY ), - new DIWikiPage( $catname, NS_CATEGORY, '' ) - ); - } - - if ( $settings->get( 'smwgUseCategoryHierarchy' ) && ( $namespace === NS_CATEGORY ) ) { - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( DIProperty::TYPE_SUBCATEGORY ), - new DIWikiPage( $catname, NS_CATEGORY, '' ) - ); - } - } - } - - protected function isHiddenCategory( $catName ) { - - if ( $this->hiddenCategories === null ) { - $wikipage = Application::getInstance()->newPageCreator()->createPage( $this->getSemanticData()->getSubject()->getTitle() ); - $this->hiddenCategories = $wikipage->getHiddenCategories(); - } - - foreach ( $this->hiddenCategories as $hiddenCategory ) { - - if ( $hiddenCategory->getText() === $catName ) { - return true; - }; - - } - - return false; - } - -} diff --git a/SemanticMediaWiki/includes/src/Annotator/NullPropertyAnnotator.php b/SemanticMediaWiki/includes/src/Annotator/NullPropertyAnnotator.php deleted file mode 100644 index 8dd88d56..00000000 --- a/SemanticMediaWiki/includes/src/Annotator/NullPropertyAnnotator.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -namespace SMW\Annotator; - -use SMW\PropertyAnnotator; -use SMW\SemanticData; - -/** - * Root object representing the initial data transfer object to interact with - * a Decorator - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class NullPropertyAnnotator implements PropertyAnnotator { - - /** - * @var SemanticData - */ - private $semanticData; - - /** - * @since 1.9 - * - * @param SemanticData $semanticData - */ - public function __construct( SemanticData $semanticData ) { - $this->semanticData = $semanticData; - } - - /** - * @see PropertyAnnotator::getSemanticData - * - * @since 1.9 - */ - public function getSemanticData() { - return $this->semanticData; - } - - /** - * @see PropertyAnnotator::addAnnotation - * - * @since 1.9 - */ - public function addAnnotation() { - return $this; - } - -} diff --git a/SemanticMediaWiki/includes/src/Annotator/PredefinedPropertyAnnotator.php b/SemanticMediaWiki/includes/src/Annotator/PredefinedPropertyAnnotator.php deleted file mode 100644 index 000d5c33..00000000 --- a/SemanticMediaWiki/includes/src/Annotator/PredefinedPropertyAnnotator.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -namespace SMW\Annotator; - -use SMW\Application; -use SMW\PropertyAnnotator; -use SMW\PageInfo; -use SMW\DIProperty; -use SMW\DIWikiPage; - -use SMWDataItem as DataItem; -use SMWDIBlob as DIBlob; -use SMWDIBoolean as DIBoolean; -use SMWDITime as DITime; - -/** - * Handling predefined property annotations - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class PredefinedPropertyAnnotator extends PropertyAnnotatorDecorator { - - /** - * @var PageInfo - */ - private $pageInfo; - - /** - * @since 1.9 - * - * @param PropertyAnnotator $propertyAnnotator - * @param PageInfo $pageInfo - */ - public function __construct( PropertyAnnotator $propertyAnnotator, PageInfo $pageInfo ) { - parent::__construct( $propertyAnnotator ); - $this->pageInfo = $pageInfo; - } - - protected function addPropertyValues() { - - $predefinedProperties = Application::getInstance()->getSettings()->get( 'smwgPageSpecialProperties' ); - $cachedProperties = array(); - - foreach ( $predefinedProperties as $propertyId ) { - - if ( $this->isRegisteredPropertyId( $propertyId, $cachedProperties ) ) { - continue; - } - - $propertyDI = new DIProperty( $propertyId ); - - if ( $this->getSemanticData()->getPropertyValues( $propertyDI ) !== array() ) { - $cachedProperties[ $propertyId ] = true; - continue; - } - - $dataItem = $this->createDataItemByPropertyId( $propertyId ); - - if ( $dataItem instanceof DataItem ) { - $cachedProperties[ $propertyId ] = true; - $this->getSemanticData()->addPropertyObjectValue( $propertyDI, $dataItem ); - } - } - } - - protected function isRegisteredPropertyId( $propertyId, $cachedProperties ) { - return ( DIProperty::getPredefinedPropertyTypeId( $propertyId ) === '' ) || - array_key_exists( $propertyId, $cachedProperties ); - } - - protected function createDataItemByPropertyId( $propertyId ) { - - $dataItem = null; - - switch ( $propertyId ) { - case DIProperty::TYPE_MODIFICATION_DATE : - $dataItem = DITime::newFromTimestamp( $this->pageInfo->getModificationDate() ); - break; - case DIProperty::TYPE_CREATION_DATE : - $dataItem = DITime::newFromTimestamp( $this->pageInfo->getCreationDate() ); - break; - case DIProperty::TYPE_NEW_PAGE : - $dataItem = new DIBoolean( $this->pageInfo->isNewPage() ); - break; - case DIProperty::TYPE_LAST_EDITOR : - $dataItem = $this->pageInfo->getLastEditor() ? DIWikiPage::newFromTitle( $this->pageInfo->getLastEditor() ) : null; - break; - case DIProperty::TYPE_MEDIA : - $dataItem = $this->pageInfo->isFilePage() ? new DIBlob( $this->pageInfo->getMediaType() ) : null; - break; - case DIProperty::TYPE_MIME : - $dataItem = $this->pageInfo->isFilePage() ? new DIBlob( $this->pageInfo->getMimeType() ) : null; - break; - } - - return $dataItem; - } - -} diff --git a/SemanticMediaWiki/includes/src/Annotator/PropertyAnnotatorDecorator.php b/SemanticMediaWiki/includes/src/Annotator/PropertyAnnotatorDecorator.php deleted file mode 100644 index 34c48057..00000000 --- a/SemanticMediaWiki/includes/src/Annotator/PropertyAnnotatorDecorator.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -namespace SMW\Annotator; - -use SMW\PropertyAnnotator; - -/** - * Decorator that contains the reference to the invoked PropertyAnnotator - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -abstract class PropertyAnnotatorDecorator implements PropertyAnnotator { - - /** - * @var PropertyAnnotator - */ - protected $propertyAnnotator; - - /** - * @since 1.9 - * - * @param PropertyAnnotator $propertyAnnotator - */ - public function __construct( PropertyAnnotator $propertyAnnotator ) { - $this->propertyAnnotator = $propertyAnnotator; - } - - /** - * @see PropertyAnnotator::getSemanticData - * - * @since 1.9 - * - * @return SemanticData - */ - public function getSemanticData() { - return $this->propertyAnnotator->getSemanticData(); - } - - /** - * @see PropertyAnnotator::addAnnotation - * - * @since 1.9 - * - * @return PropertyAnnotator - */ - public function addAnnotation() { - - $this->propertyAnnotator->addAnnotation(); - $this->addPropertyValues(); - - return $this; - } - - /** - * @since 1.9 - */ - protected abstract function addPropertyValues(); - -} diff --git a/SemanticMediaWiki/includes/src/Annotator/PropertyAnnotatorFactory.php b/SemanticMediaWiki/includes/src/Annotator/PropertyAnnotatorFactory.php deleted file mode 100644 index 03e3af3d..00000000 --- a/SemanticMediaWiki/includes/src/Annotator/PropertyAnnotatorFactory.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -namespace SMW\Annotator; - -use SMW\MediaWiki\PageInfoProvider; -use SMw\MediaWiki\RedirectTargetFinder; -use SMW\SemanticData; -use SMW\PageInfo; - -use Title; -use WikiPage; -use Revision; -use User; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class PropertyAnnotatorFactory { - - /** - * @since 2.0 - * - * @param WikiPage $wkiPage - * @param Revision|null $revision - * @param User|null $user - * - * @return PageInfoProvider - */ - public function newPageInfoProvider( WikiPage $wkiPage, Revision $revision = null, User $user = null ) { - return new PageInfoProvider( $wkiPage, $revision, $user ); - } - - /** - * @since 2.0 - * - * @param SemanticData $semanticData - * - * @return NullPropertyAnnotator - */ - public function newNullPropertyAnnotator( SemanticData $semanticData ) { - return new NullPropertyAnnotator( $semanticData ); - } - - /** - * @since 2.0 - * - * @param SemanticData $semanticData - * @param RedirectTargetFinder $redirectTargetFinder - * - * @return RedirectPropertyAnnotator - */ - public function newRedirectPropertyAnnotator( SemanticData $semanticData, RedirectTargetFinder $redirectTargetFinder ) { - return new RedirectPropertyAnnotator( - $this->newNullPropertyAnnotator( $semanticData ), - $redirectTargetFinder - ); - } - - /** - * @since 2.0 - * - * @param SemanticData $semanticData - * @param PageInfo $pageInfo - * - * @return PredefinedPropertyAnnotator - */ - public function newPredefinedPropertyAnnotator( SemanticData $semanticData, PageInfo $pageInfo ) { - return new PredefinedPropertyAnnotator( - $this->newNullPropertyAnnotator( $semanticData ), - $pageInfo - ); - } - - /** - * @since 2.0 - * - * @param SemanticData $semanticData - * @param string $sortkey - * - * @return SortkeyPropertyAnnotator - */ - public function newSortkeyPropertyAnnotator( SemanticData $semanticData, $sortkey ) { - return new SortkeyPropertyAnnotator( - $this->newNullPropertyAnnotator( $semanticData ), - $sortkey - ); - } - - /** - * @since 2.0 - * - * @param SemanticData $semanticData - * @param array $categories - * - * @return CategoryPropertyAnnotator - */ - public function newCategoryPropertyAnnotator( SemanticData $semanticData, array $categories ) { - return new CategoryPropertyAnnotator( - $this->newNullPropertyAnnotator( $semanticData ), - $categories - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/Annotator/RedirectPropertyAnnotator.php b/SemanticMediaWiki/includes/src/Annotator/RedirectPropertyAnnotator.php deleted file mode 100644 index 08b73a48..00000000 --- a/SemanticMediaWiki/includes/src/Annotator/RedirectPropertyAnnotator.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -namespace SMW\Annotator; - -use SMW\MediaWiki\RedirectTargetFinder; -use SMW\PropertyAnnotator; -use SMW\DIProperty; -use SMW\DIWikiPage; - -use ContentHandler; -use Title; - -/** - * Handling redirect annotation - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class RedirectPropertyAnnotator extends PropertyAnnotatorDecorator { - - /** - * @var RedirectTargetFinder - */ - private $redirectTargetFinder; - - /** - * @since 1.9 - * - * @param PropertyAnnotator $propertyAnnotator - * @param RedirectTargetFinder $redirectTargetFinder - */ - public function __construct( PropertyAnnotator $propertyAnnotator, RedirectTargetFinder $redirectTargetFinder ) { - parent::__construct( $propertyAnnotator ); - $this->redirectTargetFinder = $redirectTargetFinder; - } - - /** - * @see PropertyAnnotatorDecorator::addPropertyValues - */ - protected function addPropertyValues() { - - if ( !$this->redirectTargetFinder->hasTarget() ) { - return; - } - - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( '_REDI' ), - DIWikiPage::newFromTitle( $this->redirectTargetFinder->getTarget(), '__red' ) - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/Annotator/SortkeyPropertyAnnotator.php b/SemanticMediaWiki/includes/src/Annotator/SortkeyPropertyAnnotator.php deleted file mode 100644 index ee3802e7..00000000 --- a/SemanticMediaWiki/includes/src/Annotator/SortkeyPropertyAnnotator.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -namespace SMW\Annotator; - -use SMW\DIProperty; -use SMW\PropertyAnnotator; - -use SMWDIBlob as DIBlob; - -/** - * Handling sort key annotation - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SortkeyPropertyAnnotator extends PropertyAnnotatorDecorator { - - /** - * @var string - */ - private $defaultSort; - - /** - * @since 1.9 - * - * @param PropertyAnnotator $propertyAnnotator - * @param string $defaultSort - */ - public function __construct( PropertyAnnotator $propertyAnnotator, $defaultSort ) { - parent::__construct( $propertyAnnotator ); - $this->defaultSort = $defaultSort; - } - - protected function addPropertyValues() { - - $sortkey = $this->defaultSort ? $this->defaultSort : str_replace( '_', ' ', $this->getSemanticData()->getSubject()->getDBkey() ); - - $this->getSemanticData()->addPropertyObjectValue( - new DIProperty( DIProperty::TYPE_SORTKEY ), - new DIBlob( $sortkey ) - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/Application.php b/SemanticMediaWiki/includes/src/Application.php deleted file mode 100644 index ea95345e..00000000 --- a/SemanticMediaWiki/includes/src/Application.php +++ /dev/null @@ -1,202 +0,0 @@ -<?php - -namespace SMW; - -use SMW\MediaWiki\Jobs\JobFactory; -use SMW\Annotator\PropertyAnnotatorFactory; -use SMW\MediaWiki\MagicWordFinder; -use SMW\MediaWiki\RedirectTargetFinder; -use SMW\Factbox\FactboxBuilder; - -use ParserOutput; -use Title; - -/** - * Application instances access for internal and external use - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class Application { - - /** - * @var Application - */ - private static $instance = null; - - /** - * @var DependencyBuilder - */ - private $builder = null; - - /** - * @since 2.0 - */ - protected function __construct( DependencyBuilder $builder = null ) { - $this->builder = $builder; - } - - /** - * @since 2.0 - * - * @return Application - */ - public static function getInstance() { - - if ( self::$instance === null ) { - self::$instance = new self( self::registerBuilder() ); - } - - return self::$instance; - } - - /** - * @since 2.0 - */ - public static function clear() { - self::$instance = null; - } - - /** - * @since 2.0 - * - * @param string $objectName - * @param Closure|array $objectSignature - * - * @return Application - */ - public function registerObject( $objectName, $objectSignature ) { - $this->builder->getContainer()->registerObject( $objectName, $objectSignature ); - return $this; - } - - /** - * @since 2.0 - * - * @return SerializerFactory - */ - public function newSerializerFactory() { - return new SerializerFactory(); - } - - /** - * @since 2.0 - * - * @return FactboxBuilder - */ - public function newFactboxBuilder() { - return new FactboxBuilder(); - } - - - /** - * @since 2.0 - * - * @return PropertyAnnotatorFactory - */ - public function newPropertyAnnotatorFactory() { - return new PropertyAnnotatorFactory(); - } - - /** - * @since 2.0 - * - * @return JobFactory - */ - public function newJobFactory() { - return $this->builder->newObject( 'JobFactory' ); - } - - /** - * @since 2.0 - * - * @return Store - */ - public function getStore() { - return $this->builder->newObject( 'Store' ); - } - - /** - * @since 2.0 - * - * @return Settings - */ - public function getSettings() { - return $this->builder->newObject( 'Settings' ); - } - - /** - * @since 2.0 - * - * @return TitleCreator - */ - public function newTitleCreator() { - return $this->builder->newObject( 'TitleCreator' ); - } - - /** - * @since 2.0 - * - * @return PageCreator - */ - public function newPageCreator() { - return $this->builder->newObject( 'PageCreator' ); - } - - /** - * @since 2.0 - * - * @return CacheHandler - */ - public function getCache() { - return $this->builder->newObject( 'CacheHandler' ); - } - - /** - * @since 2.0 - * - * @return InTextAnnotationParser - */ - public function newInTextAnnotationParser( ParserData $parserData ) { - return new InTextAnnotationParser( - $parserData, - new MagicWordFinder(), - new RedirectTargetFinder() - ); - } - - /** - * @since 2.0 - * - * @return ParserData - */ - public function newParserData( Title $title, ParserOutput $parserOutput ) { - return $this->builder->newObject( 'ParserData', array( - 'Title' => $title, - 'ParserOutput' => $parserOutput - ) ); - } - - /** - * @since 2.0 - * - * @return ContentParser - */ - public function newContentParser( Title $title ) { - return $this->builder->newObject( 'ContentParser', array( - 'Title' => $title - ) ); - } - - private static function registerBuilder( DependencyBuilder $builder = null ) { - - if ( $builder === null ) { - $builder = new SimpleDependencyBuilder( new SharedDependencyContainer() ); - } - - return $builder; - } - -} diff --git a/SemanticMediaWiki/includes/src/Configuration/Configuration.php b/SemanticMediaWiki/includes/src/Configuration/Configuration.php deleted file mode 100644 index 11deba51..00000000 --- a/SemanticMediaWiki/includes/src/Configuration/Configuration.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -namespace SMW\Configuration; - -use InvalidArgumentException; - -/** - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9.1 - * - * @author mwjames - */ -class Configuration { - - /** @var Configuration */ - protected static $instance = null; - - /** @var array */ - protected $container = null; - - /** - * @since 1.9.1 - * - * @return Configuration - */ - public static function getInstance() { - - if ( self::$instance === null ) { - self::$instance = new self(); - } - - return self::$instance->setContainer( $GLOBALS ); - } - - /** - * @since 1.9.1 - */ - public static function clear() { - self::$instance = null; - } - - /** - * @since 1.9.1 - * - * @param string $key - * - * @return mixed - */ - public function get( $key ) { - - if ( is_string( $key ) && $this->contains( $key ) ) { - return $this->lookup( $key ); - } - - throw new InvalidArgumentException( 'Configuration key is unkown' ); - } - - /** - * @since 2.0 - * - * @param string $key - * @param mixed $value - */ - public function set( $key, $value ) { - - if ( is_string( $key ) ) { - $this->container[ $key ] = $value; - } - - return $this; - } - - protected function setContainer( $container ) { - $this->container = $container; - return $this; - } - - protected function contains( $key ) { - return isset( $this->container[$key] ) || array_key_exists( $key, $this->container ); - } - - protected function lookup( $key ) { - return $this->container[$key]; - } - -} diff --git a/SemanticMediaWiki/includes/src/CurlRequest.php b/SemanticMediaWiki/includes/src/CurlRequest.php deleted file mode 100644 index 7c9d163c..00000000 --- a/SemanticMediaWiki/includes/src/CurlRequest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -namespace SMW; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class CurlRequest implements HttpRequest { - - private $handle = null; - - /** - * @since 2.0 - * - * @param $handle - */ - public function __construct( $handle ) { - $this->handle = $handle; - } - - /** - * @since 2.0 - * - * @param $name - * @param $value - * - * @return HttpRequest - */ - public function setOption( $name, $value ) { - curl_setopt( $this->handle, $name, $value ); - return $this; - } - - /** - * @since 2.0 - * - * @param $name - * - * @return mixed - */ - public function getInfo( $name ) { - return curl_getinfo( $this->handle, $name ); - } - - /** - * @since 2.0 - * - * @return string - */ - public function getLastError() { - return curl_error( $this->handle ); - } - - /** - * @since 2.0 - * - * @return integer - */ - public function getLastErrorCode() { - return curl_errno( $this->handle ); - } - - /** - * @since 2.0 - * - * @return mixed - */ - public function execute() { - return curl_exec( $this->handle ); - } - -} - diff --git a/SemanticMediaWiki/includes/src/Factbox/Factbox.php b/SemanticMediaWiki/includes/src/Factbox/Factbox.php deleted file mode 100644 index 67482487..00000000 --- a/SemanticMediaWiki/includes/src/Factbox/Factbox.php +++ /dev/null @@ -1,365 +0,0 @@ -<?php - -namespace SMW; - -use SMWInfolink; -use SMWOutputs; - -use IContextSource; -use ParserOutput; -use Sanitizer; -use Title; -use Html; - -/** - * Class handling the "Factbox" content rendering - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class Factbox { - - /** @var Store */ - protected $store; - - /** @var ParserData */ - protected $parserData; - - /** @var Settings */ - protected $settings; - - /** @var TableFormatter */ - protected $tableFormatter; - - /** @var IContextSource */ - protected $context; - - /** @var boolean */ - protected $isVisible = false; - - /** @var string */ - protected $content = null; - - /** - * @since 1.9 - * - * @param Store $store - * @param IParserData $parserData - * @param Settings $settings - * @param IContextSource $context - */ - public function __construct( - Store $store, - ParserData $parserData, - Settings $settings, - IContextSource $context - ) { - $this->store = $store; - $this->parserData = $parserData; - $this->settings = $settings; - $this->context = $context; - } - - /** - * Builds content suitable for rendering a Factbox and - * updating the ParserOuput accordingly - * - * @since 1.9 - * - * @return Factbox - */ - public function doBuild() { - - $this->content = $this->fetchContent( $this->getMagicWords() ); - - if ( $this->content !== '' ) { - $this->parserData->getOutput()->addModules( $this->getModules() ); - $this->parserData->updateOutput(); - $this->isVisible = true; - } - - return $this; - } - - /** - * Returns Title object - * - * @since 1.9 - * - * @return string|null - */ - public function getTitle() { - return $this->parserData->getTitle(); - } - - /** - * Returns content - * - * @since 1.9 - * - * @return string|null - */ - public function getContent() { - return $this->content; - } - - /** - * Returns if content is visible - * - * @since 1.9 - * - * @return boolean - */ - public function isVisible() { - return $this->isVisible; - } - - /** - * Returns magic words attached to the ParserOutput object - * - * @since 1.9 - * - * @return string|null - */ - protected function getMagicWords() { - - $parserOutput = $this->parserData->getOutput(); - - // Prior MW 1.21 mSMWMagicWords is used (see SMW\ParserTextProcessor) - if ( method_exists( $parserOutput, 'getExtensionData' ) ) { - $smwMagicWords = $parserOutput->getExtensionData( 'smwmagicwords' ); - $mws = $smwMagicWords === null ? array() : $smwMagicWords; - } else { - // @codeCoverageIgnoreStart - $mws = isset( $parserOutput->mSMWMagicWords ) ? $parserOutput->mSMWMagicWords : array(); - // @codeCoverageIgnoreEnd - } - - if ( in_array( 'SMW_SHOWFACTBOX', $mws ) ) { - $showfactbox = SMW_FACTBOX_NONEMPTY; - } elseif ( in_array( 'SMW_NOFACTBOX', $mws ) ) { - $showfactbox = SMW_FACTBOX_HIDDEN; - } elseif ( $this->context->getRequest()->getCheck( 'wpPreview' ) ) { - $showfactbox = $this->settings->get( 'smwgShowFactboxEdit' ); - } else { - $showfactbox = $this->settings->get( 'smwgShowFactbox' ); - } - - return $showfactbox; - } - - /** - * Returns required resource modules - * - * @since 1.9 - * - * @return array - */ - protected function getModules() { - return array( - 'ext.smw.style' - ); - } - - /** - * Returns content found for a given ParserOutput object and if the required - * custom data was not available then semantic data are retrieved from - * the store for a given subject. - * - * The method checks whether the given setting of $showfactbox requires - * displaying the given data at all. - * - * @since 1.9 - * - * @return integer $showFactbox - * - * @return string|null - */ - protected function fetchContent( $showFactbox = SMW_FACTBOX_NONEMPTY ) { - - if ( $showFactbox === SMW_FACTBOX_HIDDEN ) { - return ''; - } - - $semanticData = $this->parserData->getData(); - - if ( $semanticData === null || $semanticData->stubObject || $this->isEmpty( $semanticData ) ) { - $semanticData = $this->store->getSemanticData( $this->parserData->getSubject() ); - } - - if ( $showFactbox === SMW_FACTBOX_SPECIAL && !$semanticData->hasVisibleSpecialProperties() ) { - // show only if there are special properties - return ''; - } else if ( $showFactbox === SMW_FACTBOX_NONEMPTY && !$semanticData->hasVisibleProperties() ) { - // show only if non-empty - return ''; - } - - return $this->createTable( $semanticData ); - } - - /** - * Ensure that the SemanticData container is really empty and not filled - * with a single "pseudo" property that obscures from re-reading the data - * - * MW's internal Parser does iterate the ParserOuput object several times - * which can leave a '_SKEY' property while in fact the the container is - * empty. - * - * @since 1.9 - * - * @param SemanticData $semanticData - * - * @return boolean - */ - protected function isEmpty( SemanticData $semanticData ) { - - $property = new DIProperty( '_SKEY' ); - - foreach( $semanticData->getPropertyValues( $property ) as $dataItem ) { - $semanticData->removePropertyObjectValue( $property, $dataItem ); - } - - return $semanticData->isEmpty(); - } - - /** - * Returns a formatted factbox table - * - * @since 1.9 - * - * @param SMWSemanticData $semanticData - * - * @return string|null - */ - protected function createTable( SemanticData $semanticData ) { - Profiler::In( __METHOD__ ); - - $this->tableFormatter = new TableFormatter(); - $text = ''; - - // Hook deprecated with SMW 1.9 and will vanish with SMW 1.11 - wfRunHooks( 'smwShowFactbox', array( &$text, $semanticData ) ); - - // Hook since 1.9 - if ( wfRunHooks( 'SMW::Factbox::showContent', array( &$text, $semanticData ) ) ) { - - $this->getTableHeader( $semanticData->getSubject() ); - $this->getTableContent( $semanticData ); - - $text .= Html::rawElement( 'div', - array( 'class' => 'smwfact' ), - $this->tableFormatter->getHeaderItems() . - $this->tableFormatter->getTable( array( 'class' => 'smwfacttable' ) ) - ); - } - - Profiler::Out( __METHOD__ ); - return $text; - } - - /** - * Renders a table header for a given subject - * - * @since 1.9 - * - * @param DIWikiPage $subject - */ - protected function getTableHeader( DIWikiPage $subject ) { - - $dataValue = DataValueFactory::getInstance()->newDataItemValue( $subject, null ); - - $browselink = SMWInfolink::newBrowsingLink( - $dataValue->getText(), - $dataValue->getWikiValue(), - 'swmfactboxheadbrowse' - ); - - $this->tableFormatter->addHeaderItem( 'span', - $this->context->msg( 'smw_factbox_head', $browselink->getWikiText() )->inContentLanguage()->text(), - array( 'class' => 'smwfactboxhead' ) - ); - - $rdflink = SMWInfolink::newInternalLink( - $this->context->msg( 'smw_viewasrdf' )->inContentLanguage()->text(), - $subject->getTitle()->getPageLanguage()->getNsText( NS_SPECIAL ) . ':ExportRDF/' . $dataValue->getWikiValue(), - 'rdflink' - ); - - $this->tableFormatter->addHeaderItem( 'span', - $rdflink->getWikiText(), - array( 'class' => 'smwrdflink' ) - ); - } - - /** - * Renders table content for a given SMWSemanticData object - * - * @since 1.9 - * - * @param SMWSemanticData $semanticData - */ - protected function getTableContent( SemanticData $semanticData ) { - Profiler::In( __METHOD__ ); - - // Do exclude some tags from processing otherwise the display - // can become distorted due to unresolved/open tags (see Bug 23185) - $excluded = array( 'table', 'tr', 'th', 'td', 'dl', 'dd', 'ul', 'li', 'ol', 'b', 'sup', 'sub' ); - $attributes = array(); - - foreach ( $semanticData->getProperties() as $propertyDi ) { - $propertyDv = DataValueFactory::getInstance()->newDataItemValue( $propertyDi, null ); - - if ( !$propertyDi->isShown() ) { - // showing this is not desired, hide - continue; - } elseif ( $propertyDi->isUserDefined() ) { - // User defined property (@note the preg_replace is a slight - // hack to ensure that the left column does not get too narrow) - $propertyDv->setCaption( preg_replace( '/[ ]/u', ' ', $propertyDv->getWikiValue(), 2 ) ); - $attributes['property'] = array( 'class' => 'smwpropname' ); - $attributes['values'] = array( 'class' => 'smwprops' ); - } elseif ( $propertyDv->isVisible() ) { - // Predefined property - $attributes['property'] = array( 'class' => 'smwspecname' ); - $attributes['values'] = array( 'class' => 'smwspecs' ); - } else { - // predefined, internal property - // @codeCoverageIgnoreStart - continue; - // @codeCoverageIgnoreEnd - } - - $valuesHtml = array(); - foreach ( $semanticData->getPropertyValues( $propertyDi ) as $dataItem ) { - - $dataValue = DataValueFactory::getInstance()->newDataItemValue( $dataItem, $propertyDi ); - - if ( $dataValue->isValid() ) { - $valuesHtml[] = Sanitizer::removeHTMLtags( - $dataValue->getLongWikiText( true ) , null, array(), array(), $excluded - ) . $dataValue->getInfolinkText( SMW_OUTPUT_WIKI ); - } - } - - // Invoke table content - $this->tableFormatter->addTableCell( - $propertyDv->getShortWikiText( true ), - $attributes['property'] - ); - - $this->tableFormatter->addTableCell( - $this->context->getLanguage()->listToText( $valuesHtml ), - $attributes['values'] - ); - - $this->tableFormatter->addTableRow(); - } - - Profiler::Out( __METHOD__ ); - } -} diff --git a/SemanticMediaWiki/includes/src/Factbox/FactboxBuilder.php b/SemanticMediaWiki/includes/src/Factbox/FactboxBuilder.php deleted file mode 100644 index 48f60274..00000000 --- a/SemanticMediaWiki/includes/src/Factbox/FactboxBuilder.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -namespace SMW\Factbox; - -use SMW\FactboxCache; -use SMW\Factbox; -use SMW\ParserData; -use SMW\Application; - -use OutputPage; -use IContextSource; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class FactboxBuilder { - - /** - * @since 2.0 - * - * @param OutputPage $outputPage - * - * @return FactboxCache - */ - public function newFactboxCache( OutputPage $outputPage ) { - return new FactboxCache( $outputPage ); - } - - /** - * @since 2.0 - * - * @param ParserData $parserData - * @param IContextSource $context - * - * @return Factbox - */ - public function newFactbox( ParserData $parserData, IContextSource $context ) { - return new Factbox( - Application::getInstance()->getStore(), - $parserData, - Application::getInstance()->getSettings(), - $context - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/Factbox/FactboxCache.php b/SemanticMediaWiki/includes/src/Factbox/FactboxCache.php deleted file mode 100644 index 8a14e40c..00000000 --- a/SemanticMediaWiki/includes/src/Factbox/FactboxCache.php +++ /dev/null @@ -1,234 +0,0 @@ -<?php - -namespace SMW; - -use ParserOutput; -use OutputPage; -use Title; -use Html; - -/** - * Factbox output caching - * - * Enable ($smwgFactboxUseCache) to use a CacheStore to avoid unaltered - * content being re-parsed every time the OutputPage hook is executed - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class FactboxCache { - - /** - * @var OutputPage - */ - protected $outputPage = null; - - /** - * @var boolean - */ - protected $isCached = false; - - /** - * @since 1.9 - * - * @param OutputPage &$outputPage - * - * @return FactboxCache - */ - public function __construct( OutputPage &$outputPage ) { - $this->outputPage = $outputPage; - } - - /** - * Prepare and update the OutputPage property - * - * Factbox content is either retrived from a CacheStore or re-parsed from - * the Factbox object - * - * Altered content is tracked using the revision Id, getLatestRevID() only - * changes after a content modification has occurred. - * - * Cached content is stored in an associative array following: - * { 'revId' => $revisionId, 'text' => (...) } - * - * @since 1.9 - * - * @param ParserOutput $parserOutput - */ - public function process( ParserOutput $parserOutput ) { - - Profiler::In( __METHOD__ ); - - $title = $this->outputPage->getTitle(); - $revId = $this->getRevisionId( $title ); - $resultMapper = $this->newResultMapper( $title->getArticleID() ); - $content = $resultMapper->fetchFromCache(); - - if ( $this->cacheIsAvailableFor( $revId, $content ) ) { - - $this->isCached = true; - $this->outputPage->mSMWFactboxText = $content['text']; - - } else { - - $this->isCached = false; - - $text = $this->rebuild( - $title, - $parserOutput, - $this->outputPage->getContext() - ); - - $resultMapper->recache( array( - 'revId' => $revId, - 'text' => $text - ) ); - - $this->outputPage->mSMWFactboxText = $text; - } - - Profiler::Out( __METHOD__ ); - } - - /** - * Returns parsed Factbox content from either the OutputPage property - * or from the CacheStore - * - * @since 1.9 - * - * @return string - */ - public function retrieveContent() { - - $text = ''; - $title = $this->outputPage->getTitle(); - - if ( $title instanceof Title && ( $title->isSpecialPage() || $title->isDeleted() ) ) { - return $text; - } - - if ( isset( $this->outputPage->mSMWFactboxText ) ) { - $text = $this->outputPage->mSMWFactboxText; - } else if ( $title instanceof Title ) { - $content = $this->newResultMapper( $title->getArticleID() )->fetchFromCache(); - $text = isset( $content['text'] ) ? $content['text'] : ''; - } - - return $text; - } - - /** - * Returns whether or not results have been cached - * - * @since 1.9 - * - * @return boolean - */ - public function isCached() { - return $this->isCached; - } - - /** - * Returns a CacheIdGenerator object - * - * @since 1.9 - * - * @return CacheIdGenerator - */ - public static function newCacheId( $pageId ) { - return new CacheIdGenerator( $pageId, 'factbox' ); - } - - /** - * Returns a CacheableResultMapper object - * - * @since 1.9 - * - * @param integer $pageId - * - * @return CacheableResultMapper - */ - public function newResultMapper( $pageId ) { - - $settings = Application::getInstance()->getSettings(); - - return new CacheableResultMapper( new SimpleDictionary( array( - 'id' => $pageId, - 'prefix' => 'factbox', - 'type' => $settings->get( 'smwgCacheType' ), - 'enabled' => $settings->get( 'smwgFactboxUseCache' ), - 'expiry' => 0 - ) ) ); - } - - /** - * Return a revisionId either from the WebRequest object (display an old - * revision or permalink etc.) or from the title object - * - * @since 1.9 - * - * @param Title $title - * - * @return integer - */ - protected function getRevisionId( Title $title ) { - - if ( $this->outputPage->getContext()->getRequest()->getCheck( 'oldid' ) ) { - return (int)$this->outputPage->getContext()->getRequest()->getVal( 'oldid' ); - } - - return $title->getLatestRevID(); - } - - /** - * Processing and reparsing of the Factbox content - * - * @since 1.9 - * - * @param Factbox $factbox - * - * @return string|null - */ - protected function rebuild( Title $title, ParserOutput $parserOutput, $requestContext ) { - - $text = null; - $application = Application::getInstance(); - - $factbox = $application->newFactboxBuilder()->newFactbox( - $application->newParserData( $title, $parserOutput ), - $requestContext - ); - - if ( $factbox->doBuild()->isVisible() ) { - - $contentParser = $application->newContentParser( $title ); - $contentParser->parse( $factbox->getContent() ); - - $text = $contentParser->getOutput()->getText(); - } - - return $text; - } - - protected function cacheIsAvailableFor( $revId, $content ) { - - if ( Application::getInstance()->getSettings()->get( 'smwgShowFactbox' ) === SMW_FACTBOX_HIDDEN ) { - return false; - } - - if ( $this->outputPage->getContext()->getRequest()->getVal( 'action' ) === 'edit' ) { - return false; - } - - if ( $revId !== 0 && isset( $content['revId'] ) && ( $content['revId'] === $revId ) && $content['text'] !== null ) { - return true; - } - - return false; - } - -} diff --git a/SemanticMediaWiki/includes/src/HttpRequest.php b/SemanticMediaWiki/includes/src/HttpRequest.php deleted file mode 100644 index 80c353b5..00000000 --- a/SemanticMediaWiki/includes/src/HttpRequest.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -namespace SMW; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -interface HttpRequest { - - /** - * @since 2.0 - * - * @param $name - * @param $value - */ - public function setOption( $name, $value ); - - /** - * @since 2.0 - * - * @param $name - */ - public function getInfo( $name ); - - /** - * @since 2.0 - */ - public function getLastError(); - - /** - * @since 2.0 - */ - public function getLastErrorCode(); - - /** - * @since 2.0 - */ - public function execute(); - -} diff --git a/SemanticMediaWiki/includes/src/InTextAnnotationParser.php b/SemanticMediaWiki/includes/src/InTextAnnotationParser.php deleted file mode 100644 index 72fe6798..00000000 --- a/SemanticMediaWiki/includes/src/InTextAnnotationParser.php +++ /dev/null @@ -1,319 +0,0 @@ -<?php - -namespace SMW; - -use SMW\MediaWiki\MagicWordFinder; -use SMW\MediaWiki\RedirectTargetFinder; - -use SMW\Application; - -use SMWOutputs; - -use MagicWord; -use Title; -use Html; - -/** - * Class collects all functions for wiki text parsing / processing that are - * relevant for SMW - * - * This class is contains all functions necessary for parsing wiki text before - * it is displayed or previewed while identifying SMW related annotations. - * - * @note Settings involve smwgNamespacesWithSemanticLinks, smwgLinksInValues, - * smwgInlineErrors - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author Denny Vrandecic - * @author mwjames - */ -class InTextAnnotationParser { - - /** - * @var ParserData - */ - protected $parserData; - - /** - * @var MagicWordFinder - */ - protected $magicWordFinder; - - /** - * @var RedirectTargetFinder - */ - protected $redirectTargetFinder; - - /** - * @var Settings - */ - protected $settings = null; - - /** - * @var boolean - */ - protected $isEnabledNamespace; - - /** - * Internal state for switching SMW link annotations off/on during parsing - * ([[SMW::on]] and [[SMW:off]]) - * @var boolean - */ - protected $isAnnotation = true; - - /** - * @since 1.9 - * - * @param ParserData $parserData - * @param MagicWordFinder $magicWordFinder - * @param RedirectTargetFinder $redirectTargetFinder - */ - public function __construct( ParserData $parserData, MagicWordFinder $magicWordFinder, RedirectTargetFinder $redirectTargetFinder ) { - $this->parserData = $parserData; - $this->magicWordFinder = $magicWordFinder; - $this->redirectTargetFinder = $redirectTargetFinder; - } - - /** - * Parsing text before an article is displayed or previewed, strip out - * semantic properties and add them to the ParserOutput object - * - * @since 1.9 - * - * @param string &$text - */ - public function parse( &$text ) { - - $title = $this->parserData->getTitle(); - $this->settings = Application::getInstance()->getSettings(); - - $this->magicWordFinder->setOutput( $this->parserData->getOutput() ); - $this->stripMagicWords( $text ); - - $this->isEnabledNamespace = NamespaceExaminer::newFromArray( $this->settings->get( 'smwgNamespacesWithSemanticLinks' ) )->isSemanticEnabled( $title->getNamespace() ); - $this->findRedirectTarget( $text ); - - $linksInValues = $this->settings->get( 'smwgLinksInValues' ); - $text = preg_replace_callback( - $this->getRegexpPattern( $linksInValues ), - $linksInValues ? 'self::process' : 'self::preprocess', - $text - ); - - $this->parserData->getOutput()->addModules( $this->getModules() ); - $this->parserData->updateOutput(); - - SMWOutputs::commitToParserOutput( $this->parserData->getOutput() ); - } - - protected function findRedirectTarget( $text ) { - - if ( $this->isEnabledNamespace ) { - - $propertyAnnotator = Application::getInstance()->newPropertyAnnotatorFactory()->newRedirectPropertyAnnotator( - $this->parserData->getSemanticData(), - $this->redirectTargetFinder->findTarget( $text ) - ); - - $propertyAnnotator->addAnnotation(); - } - } - - /** - * Returns required resource modules - * - * @since 1.9 - * - * @return array - */ - protected function getModules() { - return array( - 'ext.smw.style', - 'ext.smw.tooltips' - ); - } - - /** - * $smwgLinksInValues (default = false) determines which regexp pattern - * is returned, either a more complex (lib PCRE may cause segfaults if text - * is long) or a simpler (no segfaults found for those, but no links - * in values) pattern. - * - * If enabled (SMW accepts inputs like [[property::Some [[link]] in value]]), - * this may lead to PHP crashes (!) when very long texts are - * used as values. This is due to limitations in the library PCRE that - * PHP uses for pattern matching. - * - * @since 1.9 - * - * @param boolean $linksInValues - * - * @return string - */ - protected function getRegexpPattern( $linksInValues ) { - if ( $linksInValues ) { - return '/\[\[ # Beginning of the link - (?:([^:][^]]*):[=:])+ # Property name (or a list of those) - ( # After that: - (?:[^|\[\]] # either normal text (without |, [ or ]) - |\[\[[^]]*\]\] # or a [[link]] - |\[[^]]*\] # or an [external link] - )*) # all this zero or more times - (?:\|([^]]*))? # Display text (like "text" in [[link|text]]), optional - \]\] # End of link - /xu'; - } else { - return '/\[\[ # Beginning of the link - (?:([^:][^]]*):[=:])+ # Property name (or a list of those) - ([^\[\]]*) # content: anything but [, |, ] - \]\] # End of link - /xu'; - } - } - - /** - * A method that precedes the process() callback, it takes care of separating - * value and caption (instead of leaving this to a more complex regexp). - * - * @since 1.9 - * - * @param array $semanticLink expects (linktext, properties, value|caption) - * - * @return string - */ - protected function preprocess( array $semanticLink ) { - $value = ''; - $caption = false; - - if ( array_key_exists( 2, $semanticLink ) ) { - $parts = explode( '|', $semanticLink[2] ); - if ( array_key_exists( 0, $parts ) ) { - $value = $parts[0]; - } - if ( array_key_exists( 1, $parts ) ) { - $caption = $parts[1]; - } - } - - if ( $caption !== false ) { - return $this->process( array( $semanticLink[0], $semanticLink[1], $value, $caption ) ); - } else { - return $this->process( array( $semanticLink[0], $semanticLink[1], $value ) ); - } - } - - /** - * This callback function strips out the semantic attributes from a wiki - * link. - * - * @since 1.9 - * - * @param array $semanticLink expects (linktext, properties, value|caption) - * - * @return string - */ - protected function process( array $semanticLink ) { - wfProfileIn( __METHOD__ ); - - if ( array_key_exists( 1, $semanticLink ) ) { - $property = $semanticLink[1]; - } else { - $property = ''; - } - - if ( array_key_exists( 2, $semanticLink ) ) { - $value = $semanticLink[2]; - } else { - $value = ''; - } - - if ( $value === '' ) { // silently ignore empty values - wfProfileOut( __METHOD__ ); - return ''; - } - - if ( $property == 'SMW' ) { - switch ( $value ) { - case 'on': - $this->isAnnotation = true; - break; - case 'off': - $this->isAnnotation = false; - break; - } - wfProfileOut( __METHOD__ ); - return ''; - } - - if ( array_key_exists( 3, $semanticLink ) ) { - $valueCaption = $semanticLink[3]; - } else { - $valueCaption = false; - } - - // Extract annotations and create tooltip. - $properties = preg_split( '/:[=:]/u', $property ); - - wfProfileOut( __METHOD__ ); - return $this->addPropertyValue( $properties, $value, $valueCaption ); - } - - /** - * Adds property values to the ParserOutput instance - * - * @since 1.9 - * - * @param array $properties - * - * @return string - */ - protected function addPropertyValue( array $properties, $value, $valueCaption ) { - wfProfileIn( __METHOD__ ); - - $subject = $this->parserData->getData()->getSubject(); - - // Add properties to the semantic container - foreach ( $properties as $property ) { - $dataValue = DataValueFactory::getInstance()->newPropertyValue( - $property, - $value, - $valueCaption, - $subject - ); - - if ( $this->isEnabledNamespace && $this->isAnnotation ) { - $this->parserData->addDataValue( $dataValue ); - } - } - - // Return the text representation - $result = $dataValue->getShortWikitext( true ); - - // If necessary add an error text - if ( ( $this->settings->get( 'smwgInlineErrors' ) && - $this->isEnabledNamespace && $this->isAnnotation ) && - ( !$dataValue->isValid() ) ) { - $result .= $dataValue->getErrorText(); - } - - wfProfileOut( __METHOD__ ); - return $result; - } - - protected function stripMagicWords( &$text ) { - - $words = array(); - - foreach ( array( 'SMW_NOFACTBOX', 'SMW_SHOWFACTBOX' ) as $magicWord ) { - $words = $words + $this->magicWordFinder->matchAndRemove( $magicWord, $text ); - } - - $this->magicWordFinder->setMagicWords( $words ); - - return $words; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Api/ApiQueryResultFormatter.php b/SemanticMediaWiki/includes/src/MediaWiki/Api/ApiQueryResultFormatter.php deleted file mode 100644 index 363771e0..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Api/ApiQueryResultFormatter.php +++ /dev/null @@ -1,211 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Api; - -use InvalidArgumentException; -use SMWQueryResult; - -/** - * This class handles the Api related query result formatting - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class ApiQueryResultFormatter { - - /** - * @var Integer|boolean - */ - protected $continueOffset = false; - - /** - * @var String - */ - protected $type; - - /** - * @var Boolean - */ - protected $isRawMode = false; - - /** - * @since 1.9 - * - * @param SMWQueryResult $queryResult - */ - public function __construct( SMWQueryResult $queryResult ) { - $this->queryResult = $queryResult; - } - - /** - * Sets whether the formatter requested raw data and is used in connection - * with ApiQueryResultFormatter::setIndexedTagName - * - * @see ApiResult::getIsRawMode - * - * @since 1.9 - * - * @param boolean $isRawMode - */ - public function setIsRawMode( $isRawMode ) { - $this->isRawMode = $isRawMode; - } - - /** - * Returns an offset used for continuation support - * - * @since 1.9 - * - * @return integer - */ - public function getContinueOffset() { - return $this->continueOffset; - } - - /** - * Returns the result type - * - * @since 1.9 - * - * @return string - */ - public function getType() { - return $this->type; - } - - /** - * Returns formatted result - * - * @since 1.9 - * - * @return array - */ - public function getResult() { - return $this->result; - } - - /** - * Result formatting - * - * @since 1.9 - */ - public function doFormat() { - - if ( $this->queryResult->getErrors() !== array() ) { - $this->result = $this->formatErrors( $this->queryResult->getErrors() ); - } else { - $this->result = $this->formatResults( $this->queryResult->toArray() ); - - if ( $this->queryResult->hasFurtherResults() ) { - $this->continueOffset = $this->result['meta']['count'] + $this->result['meta']['offset']; - } - } - } - - /** - * Formatting a result array to support JSON/XML standards - * - * @since 1.9 - * - * @param array $queryResult - * - * @return array - */ - protected function formatResults( array $queryResult ) { - - $this->type = 'query'; - $results = array(); - - if ( !$this->isRawMode ) { - return $queryResult; - } - - foreach ( $queryResult['results'] as $subjectName => $subject ) { - $serialized = array(); - - foreach ( $subject as $key => $value ) { - - if ( $key === 'printouts' ) { - $printouts = array(); - - foreach ( $subject['printouts'] as $property => $values ) { - - if ( (array)$values === $values ) { - $this->setIndexedTagName( $values, 'value' ); - $printouts[] = array_merge( array( 'label' => $property ), $values ); - } - - } - - $serialized['printouts'] = $printouts; - $this->setIndexedTagName( $serialized['printouts'], 'property' ); - - } else { - $serialized[$key] = $value; - } - } - - $results[] = $serialized; - } - - if ( $results !== array() ) { - $queryResult['results'] = $results; - $this->setIndexedTagName( $queryResult['results'], 'subject' ); - } - - $this->setIndexedTagName( $queryResult['printrequests'], 'printrequest' ); - $this->setIndexedTagName( $queryResult['meta'], 'meta' ); - - return $queryResult; - } - - /** - * Formatting an error array in order to support JSON/XML - * - * @since 1.9 - * - * @param array $errors - * - * @return array - */ - protected function formatErrors( array $errors ) { - - $this->type = 'error'; - $result['query'] = $errors; - - $this->setIndexedTagName( $result['query'], 'info' ); - - return $result; - } - - /** - * Add '_element' to an array - * - * @note Copied from ApiResult::setIndexedTagName to avoid having a - * constructor injection in order to be able to access this method - * - * @see ApiResult::setIndexedTagName - * - * @since 1.9 - * - * @param array &$arr - * @param string $tag - */ - protected function setIndexedTagName( &$arr, $tag ) { - - if ( !$this->isRawMode ) { - return; - } - - if ( $arr === null || $tag === null || !is_array( $arr ) || is_array( $tag ) ) { - throw new InvalidArgumentException( "{$tag} was incompatible with the requirements" ); - } - - $arr['_element'] = $tag; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Api/ApiRequestParameterFormatter.php b/SemanticMediaWiki/includes/src/MediaWiki/Api/ApiRequestParameterFormatter.php deleted file mode 100644 index d5880d1d..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Api/ApiRequestParameterFormatter.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Api; - -use SMW\SimpleDictionary; - -use SMWPropertyValue; -use SMWPrintRequest; - -/** - * This class handles Api related request parameter formatting - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -final class ApiRequestParameterFormatter { - - /** - * @var array - */ - protected $requestParameters = array(); - - /** - * @var ObjectDictionary - */ - protected $results = null; - - /** - * @since 1.9 - * - * @param array $requestParameters - */ - public function __construct( array $requestParameters ) { - $this->requestParameters = $requestParameters; - } - - /** - * Return formatted request parameters for the AskApi - * - * @since 1.9 - * - * @return array - */ - public function getAskApiParameters() { - - if ( $this->results === null ) { - $this->results = isset( $this->requestParameters['query'] ) ? preg_split( "/(?<=[^\|])\|(?=[^\|])/", $this->requestParameters['query'] ) : array(); - } - - return $this->results; - } - - /** - * Return formatted request parameters AskArgsApi - * - * @since 1.9 - * - * @return array - */ - public function getAskArgsApiParameter( $key ) { - - if ( $this->results === null ) { - $this->results = $this->formatAskArgs(); - } - - return $this->results->get( $key ); - } - - /** - * Return formatted request parameters - * - * @since 1.9 - * - * @return ObjectDictionary - */ - protected function formatAskArgs() { - - $result = new SimpleDictionary(); - - // Set defaults - $result->set( 'conditions', array() ); - $result->set( 'printouts' , array() ); - $result->set( 'parameters', array() ); - - if ( isset( $this->requestParameters['parameters'] ) && is_array( $this->requestParameters['parameters'] ) ) { - $result->set( 'parameters', $this->formatParameters() ); - } - - if ( isset( $this->requestParameters['conditions'] ) && is_array( $this->requestParameters['conditions'] ) ) { - $result->set( 'conditions', implode( ' ', array_map( 'self::formatConditions', $this->requestParameters['conditions'] ) ) ); - } - - if ( isset( $this->requestParameters['printouts'] ) && is_array( $this->requestParameters['printouts'] ) ) { - $result->set( 'printouts', array_map( 'self::formatPrintouts', $this->requestParameters['printouts'] ) ); - } - - return $result; - } - - /** - * Format parameters - * - * @since 1.9 - * - * @return string - */ - protected function formatParameters() { - - $parameters = array(); - - foreach ( $this->requestParameters['parameters'] as $param ) { - $parts = explode( '=', $param, 2 ); - - if ( count( $parts ) == 2 ) { - $parameters[$parts[0]] = $parts[1]; - } - } - - return $parameters; - } - - /** - * Format conditions - * - * @since 1.9 - * - * @param string $condition - * - * @return string - */ - protected function formatConditions( $condition ) { - return "[[$condition]]"; - } - - /** - * Format printout and returns a SMWPrintRequest object - * - * @since 1.9 - * - * @param string $printout - * - * @return SMWPrintRequest - */ - protected function formatPrintouts( $printout ) { - return new SMWPrintRequest( - SMWPrintRequest::PRINT_PROP, - $printout, - SMWPropertyValue::makeUserProperty( $printout ) - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Api/Ask.php b/SemanticMediaWiki/includes/src/MediaWiki/Api/Ask.php deleted file mode 100644 index 21da820d..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Api/Ask.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Api; - -use SMWQueryProcessor; - -use ApiBase; - -/** - * API module to query SMW by providing a query in the ask language. - * - * @ingroup Api - * - * @license GNU GPL v2+ - * @since 1.6.2 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author mwjames - */ -class Ask extends Query { - - /** - * @see ApiBase::execute - */ - public function execute() { - - $parameterFormatter = new ApiRequestParameterFormatter( $this->extractRequestParams() ); - - list( $queryString, $parameters, $printouts ) = SMWQueryProcessor::getComponentsFromFunctionParams( $parameterFormatter->getAskApiParameters(), false ); - - $queryResult = $this->getQueryResult( $this->getQuery( - $queryString, - $printouts, - $parameters - ) ); - - $this->addQueryResult( $queryResult ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getAllowedParams - * - * @return array - */ - public function getAllowedParams() { - return array( - 'query' => array( - ApiBase::PARAM_TYPE => 'string', - ApiBase::PARAM_REQUIRED => true, - ), - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getParamDescription - * - * @return array - */ - public function getParamDescription() { - return array( - 'query' => 'The query string in ask-language' - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getDescription - * - * @return array - */ - public function getDescription() { - return array( - 'API module to query SMW by providing a query in the ask language.' - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getExamples - * - * @return array - */ - protected function getExamples() { - return array( - 'api.php?action=ask&query=[[Modification%20date::%2B]]|%3FModification%20date|sort%3DModification%20date|order%3Ddesc', - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getVersion - * - * @return string - */ - public function getVersion() { - return __CLASS__ . '-' . SMW_VERSION; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Api/AskArgs.php b/SemanticMediaWiki/includes/src/MediaWiki/Api/AskArgs.php deleted file mode 100644 index 79bdc710..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Api/AskArgs.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Api; - -use SMWPropertyValue; -use SMWPrintRequest; - -use ApiBase; - -/** - * API module to query SMW by providing a query specified as - * a list of conditions, printouts and parameters. - * - * @license GNU GPL v2+ - * @since 1.6.2 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class AskArgs extends Query { - - /** - * @see ApiBase::execute - */ - public function execute() { - - $parameterFormatter = new ApiRequestParameterFormatter( $this->extractRequestParams() ); - - $queryResult = $this->getQueryResult( $this->getQuery( - $parameterFormatter->getAskArgsApiParameter( 'conditions' ), - $parameterFormatter->getAskArgsApiParameter( 'printouts' ), - $parameterFormatter->getAskArgsApiParameter( 'parameters' ) - ) ); - - $this->addQueryResult( $queryResult ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getAllowedParams - * - * @return array - */ - public function getAllowedParams() { - return array( - 'conditions' => array( - ApiBase::PARAM_TYPE => 'string', - ApiBase::PARAM_ISMULTI => true, - ApiBase::PARAM_REQUIRED => true, - ), - 'printouts' => array( - ApiBase::PARAM_TYPE => 'string', - ApiBase::PARAM_DFLT => '', - ApiBase::PARAM_ISMULTI => true, - ), - 'parameters' => array( - ApiBase::PARAM_TYPE => 'string', - ApiBase::PARAM_DFLT => '', - ApiBase::PARAM_ISMULTI => true, - ), - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getParamDescription - * - * @return array - */ - public function getParamDescription() { - return array( - 'conditions' => 'The query conditions, i.e. the requirements for a subject to be included', - 'printouts' => 'The query printouts, i.e. the properties to show per subject', - 'parameters' => 'The query parameters, i.e. all non-condition and non-printout arguments', - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getDescription - * - * @return array - */ - public function getDescription() { - return array( - 'API module to query SMW by providing a query specified as a list of conditions, printouts and parameters.' - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getExamples - * - * @return array - */ - protected function getExamples() { - return array( - 'api.php?action=askargs&conditions=Modification%20date::%2B&printouts=Modification%20date¶meters=|sort%3DModification%20date|order%3Ddesc', - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getVersion - * - * @return string - */ - public function getVersion() { - return __CLASS__ . '-' . SMW_VERSION; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Api/BrowseBySubject.php b/SemanticMediaWiki/includes/src/MediaWiki/Api/BrowseBySubject.php deleted file mode 100644 index d456137e..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Api/BrowseBySubject.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Api; - -use SMW\Application; -use SMW\DIWikiPage; -use SMW\DIProperty; - -use Title; -use ApiBase; - -/** - * Browse a subject api module - * - * @note Browsing of a subobject subject is limited to its "parent" subject, - * meaning that a request for a "Foo#_ed5a9979db6609b32733eda3fb747d21" subject - * will produce information for "Foo" as a whole including its subobjects - * because MW's WebRequest (responsible for handling request data sent by a - * browser) will eliminate any fragments (indicated by "#") to an Api consumer - * - * @ingroup Api - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class BrowseBySubject extends ApiBase { - - /** - * @var Title - */ - private $title; - - /** - * @see ApiBase::execute - */ - public function execute() { - - $params = $this->extractRequestParams(); - - $application = Application::getInstance(); - - try { - $this->title = $application->newTitleCreator()->createFromText( $params['subject'] )->findRedirect()->getTitle(); - } catch ( \Exception $e ) { - $this->dieUsageMsg( array( 'invalidtitle', $this->title ) ); - } - - $semanticData = $application->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) ); - - $this->getResult()->addValue( - null, - 'query', - $this->doFormat( $application->newSerializerFactory()->serialize( $semanticData ) ) - ); - } - - protected function doFormat( $serialized ) { - - $this->addIndexTags( $serialized ); - - if ( isset( $serialized['sobj'] ) ) { - - $this->getResult()->setIndexedTagName( $serialized['sobj'], 'subobject' ); - - foreach ( $serialized['sobj'] as $key => &$value ) { - $this->addIndexTags( $value ); - } - } - - return $serialized; - } - - protected function addIndexTags( &$serialized ) { - - if ( isset( $serialized['data'] ) && is_array( $serialized['data'] ) ) { - - $this->getResult()->setIndexedTagName( $serialized['data'], 'property' ); - - foreach ( $serialized['data'] as $key => $value ) { - if ( isset( $serialized['data'][ $key ]['dataitem'] ) && is_array( $serialized['data'][ $key ]['dataitem'] ) ) { - $this->getResult()->setIndexedTagName( $serialized['data'][ $key ]['dataitem'], 'value' ); - } - } - } - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getAllowedParams - * - * @return array - */ - public function getAllowedParams() { - return array( - 'subject' => array( - ApiBase::PARAM_TYPE => 'string', - ApiBase::PARAM_ISMULTI => false, - ApiBase::PARAM_REQUIRED => true, - ) - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getParamDescription - * - * @return array - */ - public function getParamDescription() { - return array( - 'subject' => 'The subject to be queried', - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getDescription - * - * @return array - */ - public function getDescription() { - return array( - 'API module to query a subject.' - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getExamples - * - * @return array - */ - protected function getExamples() { - return array( - 'api.php?action=browsebysubject&subject=Main_Page', - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getVersion - * - * @return string - */ - public function getVersion() { - return __CLASS__ . '-' . SMW_VERSION; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Api/Info.php b/SemanticMediaWiki/includes/src/MediaWiki/Api/Info.php deleted file mode 100644 index 4443c155..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Api/Info.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Api; - -use SMW\Application; - -use ApiBase; - -/** - * API module to obtain info about the SMW install, primarily targeted at - * usage by the SMW registry. - * - * @ingroup Api - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class Info extends ApiBase { - - /** - * @see ApiBase::execute - */ - public function execute() { - - $params = $this->extractRequestParams(); - $requestedInfo = $params['info']; - $resultInfo = array(); - - if ( in_array( 'propcount', $requestedInfo ) - || in_array( 'usedpropcount', $requestedInfo ) - || in_array( 'proppagecount', $requestedInfo ) - || in_array( 'querycount', $requestedInfo ) - || in_array( 'querysize', $requestedInfo ) - || in_array( 'formatcount', $requestedInfo ) - || in_array( 'conceptcount', $requestedInfo ) - || in_array( 'subobjectcount', $requestedInfo ) - || in_array( 'declaredpropcount', $requestedInfo ) ) { - - $semanticStats = Application::getInstance()->getStore()->getStatistics(); - - $map = array( - 'propcount' => 'PROPUSES', - 'usedpropcount' => 'USEDPROPS', - 'declaredpropcount' => 'DECLPROPS', - 'proppagecount' => 'OWNPAGE', - 'querycount' => 'QUERY', - 'querysize' => 'QUERYSIZE', - 'conceptcount' => 'CONCEPTS', - 'subobjectcount' => 'SUBOBJECTS', - ); - - foreach ( $map as $apiName => $smwName ) { - if ( in_array( $apiName, $requestedInfo ) ) { - $resultInfo[$apiName] = $semanticStats[$smwName]; - } - } - - if ( in_array( 'formatcount', $requestedInfo ) ) { - $resultInfo['formatcount'] = array(); - foreach ( $semanticStats['QUERYFORMATS'] as $name => $count ) { - $resultInfo['formatcount'][$name] = $count; - } - } - } - - $this->getResult()->addValue( null, 'info', $resultInfo ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getAllowedParams - * - * @return array - */ - public function getAllowedParams() { - return array( - 'info' => array( - ApiBase::PARAM_DFLT => 'propcount|usedpropcount|declaredpropcount', - ApiBase::PARAM_ISMULTI => true, - ApiBase::PARAM_TYPE => array( - 'propcount', - 'usedpropcount', - 'declaredpropcount', - 'proppagecount', - 'querycount', - 'querysize', - 'formatcount', - 'conceptcount', - 'subobjectcount' - ) - ), - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getParamDescription - * - * @return array - */ - public function getParamDescription() { - return array( - 'info' => 'The info to provide.' - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getDescription - * - * @return array - */ - public function getDescription() { - return array( - 'API module get info about this SMW install.' - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getExamples - * - * @return array - */ - protected function getExamples() { - return array( - 'api.php?action=smwinfo&info=proppagecount|propcount', - ); - } - - /** - * @codeCoverageIgnore - * @see ApiBase::getVersion - * - * @return string - */ - public function getVersion() { - return __CLASS__ . ': $Id$'; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Api/Query.php b/SemanticMediaWiki/includes/src/MediaWiki/Api/Query.php deleted file mode 100644 index a1677a14..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Api/Query.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Api; - -use SMW\Application; - -use SMWQueryProcessor; -use SMWQueryResult; -use SMWQuery; - -use ApiBase; - -/** - * Base for API modules that query SMW - * - * @ingroup Api - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author mwjames - */ -abstract class Query extends ApiBase { - - /** - * Returns a query object for the provided query string and list of printouts. - * - * @since 1.6.2 - * - * @param string $queryString - * @param array $printouts - * @param array $parameters - * - * @return SMWQuery - */ - protected function getQuery( $queryString, array $printouts, array $parameters = array() ) { - - SMWQueryProcessor::addThisPrintout( $printouts, $parameters ); - - return SMWQueryProcessor::createQuery( - $queryString, - SMWQueryProcessor::getProcessedParams( $parameters, $printouts ), - SMWQueryProcessor::SPECIAL_PAGE, - '', - $printouts - ); - } - - /** - * Run the actual query and return the result. - * - * @since 1.6.2 - * - * @param SMWQuery $query - * - * @return SMWQueryResult - */ - protected function getQueryResult( SMWQuery $query ) { - return Application::getInstance()->getStore()->getQueryResult( $query ); - } - - /** - * Add the query result to the API output. - * - * @since 1.6.2 - * - * @param SMWQueryResult $queryResult - */ - protected function addQueryResult( SMWQueryResult $queryResult ) { - - $result = $this->getResult(); - - $resultFormatter = new ApiQueryResultFormatter( $queryResult ); - $resultFormatter->setIsRawMode( $result->getIsRawMode() ); - $resultFormatter->doFormat(); - - if ( $resultFormatter->getContinueOffset() ) { - $result->disableSizeCheck(); - $result->addValue( null, 'query-continue-offset', $resultFormatter->getContinueOffset() ); - $result->enableSizeCheck(); - } - - $result->addValue( - null, - $resultFormatter->getType(), - $resultFormatter->getResult() - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Database.php b/SemanticMediaWiki/includes/src/MediaWiki/Database.php deleted file mode 100644 index 4e302f3e..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Database.php +++ /dev/null @@ -1,348 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use SMW\DBConnectionProvider; - -use DBError; -use ResultWrapper; -use UnexpectedValueException; -use RuntimeException; - -/** - * This adapter class covers MW DB specific operations. Changes to the - * interface are likely therefore this class should not be used other than by - * SMW itself. - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class Database { - - /** @var DatabaseBase */ - protected $readDBConnection = null; - protected $writeDBConnection = null; - - public function __construct( DBConnectionProvider $readDBConnection, DBConnectionProvider $writeDBConnection = null ) { - $this->readDBConnection = $readDBConnection; - $this->writeDBConnection = $writeDBConnection; - } - - /** - * @since 1.9.1 - * - * @return DatabaseBase - */ - public function acquireReadConnection() { - return $this->readDBConnection->getConnection(); - } - - /** - * @since 1.9.1 - * - * @return DatabaseBase - * @throws RuntimeException - */ - public function acquireWriteConnection() { - - if ( $this->writeDBConnection instanceof DBConnectionProvider ) { - return $this->writeDBConnection->getConnection(); - } - - throw new RuntimeException( 'Expected a DBConnectionProvider instance' ); - } - - /** - * @see DatabaseBase::getType - * - * @since 1.9.1 - * - * @return string - */ - public function getType() { - return $this->acquireReadConnection()->getType(); - } - - /** - * @see DatabaseBase::tableName - * - * @since 1.9.0.2 - * - * @param string $tableName - * - * @return string - */ - public function tableName( $tableName ) { - - if ( $this->getType() == 'sqlite' ) { - return $tableName; - } - - return $this->acquireReadConnection()->tableName( $tableName ); - } - - /** - * @see DatabaseBase::addQuotes - * - * @since 1.9.0.2 - * - * @param string $tableName - * - * @return string - */ - public function addQuotes( $value ) { - return $this->acquireReadConnection()->addQuotes( $value ); - } - - /** - * @see DatabaseBase::fetchObject - * - * @since 1.9.1 - * - * @param ResultWrapper $res - * - * @return string - */ - public function fetchObject( $res ) { - return $this->acquireReadConnection()->fetchObject( $res ); - } - - /** - * @see DatabaseBase::numRows - * - * @since 1.9.0.2 - * - * @param mixed $results - * - * @return integer - */ - public function numRows( $results ) { - return $this->acquireReadConnection()->numRows( $results ); - } - - /** - * @see DatabaseBase::freeResult - * - * @since 1.9.0.2 - * - * @param ResultWrapper $res - */ - public function freeResult( $res ) { - $this->acquireReadConnection()->freeResult( $res ); - } - - /** - * @see DatabaseBase::select - * - * @since 1.9.0.2 - * - * @param string $tableName - * @param $fields - * @param $conditions - * @param array $options - * - * @return ResultWrapper - * @throws UnexpectedValueException - */ - public function select( $tableName, $fields, $conditions = '', $fname, array $options = array() ) { - - try { - $results = $this->acquireReadConnection()->select( - $tableName, - $fields, - $conditions, - $fname, - $options - ); - } catch ( DBError $e ) { - throw new RuntimeException ( - $e->getMessage() . "\n" . - $e->getTraceAsString() - ); - } - - if ( $results instanceof ResultWrapper ) { - return $results; - } - - throw new UnexpectedValueException ( - 'Expected a ResultWrapper for ' . "\n" . - $tableName . "\n" . - $fields . "\n" . - $conditions - ); - } - - /** - * @see DatabaseBase::query - * - * @since 1.9.1 - * - * @param string $sql - * @param $fname - * @param $ignoreException - * - * @return ResultWrapper - * @throws RuntimeException - */ - public function query( $sql, $fname = __METHOD__, $ignoreException = false ) { - - if ( $this->getType() == 'postgres' ) { - $sql = str_replace( 'IGNORE', '', $sql ); - $sql = str_replace( 'DROP TEMPORARY TABLE', 'DROP TABLE IF EXISTS', $sql ); - } - - if ( $this->getType() == 'sqlite' ) { - $sql = str_replace( 'IGNORE', '', $sql ); - $sql = str_replace( 'TEMPORARY', 'TEMP', $sql ); - $sql = str_replace( 'ENGINE=MEMORY', '', $sql ); - $sql = str_replace( 'DROP TEMP', 'DROP', $sql ); - $sql = str_replace( 'TRUNCATE TABLE', 'DELETE FROM', $sql ); - } - - try { - $results = $this->acquireWriteConnection()->query( - $sql, - $fname, - $ignoreException - ); - } catch ( DBError $e ) { - throw new RuntimeException ( - $e->getMessage() . "\n" . - $e->getTraceAsString() - ); - } - - return $results; - } - - /** - * @see DatabaseBase::selectRow - * - * @since 1.9.1 - */ - public function selectRow( $table, $vars, $conds, $fname = __METHOD__, - $options = array(), $joinConditions = array() ) { - - return $this->acquireReadConnection()->selectRow( - $table, - $vars, - $conds, - $fname, - $options, - $joinConditions - ); - } - - /** - * @see DatabaseBase::affectedRows - * - * @since 1.9.1 - * - * @return int - */ - function affectedRows() { - return $this->acquireReadConnection()->affectedRows(); - } - - /** - * @see DatabaseBase::makeSelectOptions - * - * @since 1.9.1 - * - * @param array $options - * - * @return array - */ - public function makeSelectOptions( $options ) { - return $this->acquireReadConnection()->makeSelectOptions( $options ); - } - - /** - * @see DatabaseBase::nextSequenceValue - * - * @since 1.9.1 - * - * @param string $seqName - * - * @return int|null - */ - public function nextSequenceValue( $seqName ) { - return $this->acquireWriteConnection()->nextSequenceValue( $seqName ); - } - - /** - * @see DatabaseBase::insertId - * - * @since 1.9.1 - * - * @return int - */ - function insertId() { - return (int)$this->acquireWriteConnection()->insertId(); - } - - /** - * @see DatabaseBase::insert - * - * @since 1.9.1 - */ - public function insert( $table, $rows, $fname = __METHOD__, $options = array() ) { - return $this->acquireWriteConnection()->insert( $table, $rows, $fname, $options ); - } - - /** - * @see DatabaseBase::update - * - * @since 1.9.1 - */ - function update( $table, $values, $conds, $fname = __METHOD__, $options = array() ) { - return $this->acquireWriteConnection()->update( $table, $values, $conds, $fname, $options ); - } - - /** - * @see DatabaseBase::delete - * - * @since 1.9.1 - */ - public function delete( $table, $conds, $fname = __METHOD__ ) { - return $this->acquireWriteConnection()->delete( $table, $conds, $fname ); - } - - /** - * @see DatabaseBase::makeList - * - * @since 1.9.1 - */ - public function makeList( $data, $mode ) { - return $this->acquireWriteConnection()->makeList( $data, $mode ); - } - - /** - * @see DatabaseBase::tableExists - * - * @since 1.9.1 - * - * @param string $table - * @param string $fname - * - * @return bool - */ - public function tableExists( $table, $fname = __METHOD__ ) { - return $this->acquireWriteConnection()->tableExists( $table, $fname ); - } - - /** - * @see DatabaseBase::selectField - * - * @since 1.9.2 - */ - public function selectField( $table, $fieldName, $conditions = '', $fname = __METHOD__, $options = array() ) { - return $this->acquireReadConnection()->selectField( $table, $fieldName, $conditions, $fname, $options ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/DirectDBConnectionProvider.php b/SemanticMediaWiki/includes/src/MediaWiki/DirectDBConnectionProvider.php deleted file mode 100644 index 1c28fa16..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/DirectDBConnectionProvider.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use SMW\DBConnectionProvider; - -use DatabaseBase; -use RuntimeException; - -/** - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9.1 - * - * @author mwjames - */ -class DirectDBConnectionProvider implements DBConnectionProvider { - - /** @var DatabaseBase|null */ - protected $connection = null; - - /** - * @since 1.9.1 - * - * @param DatabaseBase $connection - * - * @return DBConnectionProvider - */ - public function setConnection( DatabaseBase $connection ) { - $this->connection = $connection; - return $this; - } - - /** - * @see DBConnectionProvider::getConnection - * - * @since 1.9.1 - * - * @return DatabaseBase - * @throws RuntimeException - */ - public function getConnection() { - - if ( $this->connection instanceof DatabaseBase ) { - return $this->connection; - } - - throw new RuntimeException( 'Expected a DatabaseBase instance' ); - } - - /** - * @see DBConnectionProvider::releaseConnection - * - * @since 1.9.1 - */ - public function releaseConnection() {} - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/EditInfoProvider.php b/SemanticMediaWiki/includes/src/MediaWiki/EditInfoProvider.php deleted file mode 100644 index 59cb88fd..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/EditInfoProvider.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use WikiPage; -use Revision; -use User; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class EditInfoProvider { - - /** - * @var WikiPage - */ - private $wikiPage = null; - - /** - * @var Revision - */ - private $revision = null; - - /** - * @var User - */ - private $user = null; - - /** - * @var ParserOutput - */ - private $parserOutput = null; - - /** - * @since 1.9 - * - * @param WikiPage $wikiPage - * @param Revision $revision - * @param User|null $user - */ - public function __construct( WikiPage $wikiPage, Revision $revision, User $user = null ) { - $this->wikiPage = $wikiPage; - $this->revision = $revision; - $this->user = $user; - } - - /** - * @since 2.0 - * - * @return ParserOutput|null - */ - public function getOutput() { - return $this->parserOutput; - } - - /** - * @since 2.0 - * - * @return EditInfoProvider - */ - public function fetchEditInfo() { - - $editInfo = $this->hasContentForEditMethod() ? $this->prepareContentForEdit() : $this->prepareTextForEdit(); - - $this->parserOutput = isset( $editInfo->output ) ? $editInfo->output : null; - - return $this; - } - - /** - * FIXME MW 1.21- - */ - protected function hasContentForEditMethod() { - return method_exists( 'WikiPage', 'prepareContentForEdit' ); - } - - private function prepareContentForEdit() { - $content = $this->revision->getContent(); - - return $this->wikiPage->prepareContentForEdit( - $content, - null, - $this->user, - $content->getContentHandler()->getDefaultFormat() - ); - } - - private function prepareTextForEdit() { - return $this->wikiPage->prepareTextForEdit( - $this->revision->getRawText(), - null, - $this->user - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticleDelete.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticleDelete.php deleted file mode 100644 index bd9895d2..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticleDelete.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\MediaWiki\Jobs\DeleteSubjectJob; -use SMW\Application; - -/** - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleDelete - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class ArticleDelete { - - /** - * @var Wikipage - */ - protected $wikiPage = null; - - /** - * @since 2.0 - * - * @param Wikipage $wikiPage - */ - public function __construct( &$wikiPage, &$user, &$reason, &$error ) { - $this->wikiPage = $wikiPage; - $this->user = $user; - $this->reason = $reason; - $this->error = $error; - } - - /** - * @since 2.0 - * - * @return true - */ - public function process() { - - $settings = Application::getInstance()->getSettings(); - - $deleteSubjectJob = new DeleteSubjectJob( $this->wikiPage->getTitle(), array( - 'asDeferredJob' => $settings->get( 'smwgDeleteSubjectAsDeferredJob' ), - 'withAssociates' => $settings->get( 'smwgDeleteSubjectWithAssociatesRefresh' ) - ) ); - - $deleteSubjectJob->execute(); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticleFromTitle.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticleFromTitle.php deleted file mode 100644 index 553113d3..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticleFromTitle.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\ConceptPage as ConceptPage; -use SMWPropertyPage as PropertyPage; - -use Title; -use Page; - -/** - * Register special classes for displaying semantic content on Property and - * Concept pages. - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleFromTitle - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class ArticleFromTitle { - - /** - * @var Title - */ - private $title = null; - - /** - * @var Page - */ - private $article = null; - - /** - * @since 2.0 - * - * @param Title &$title - * @param Page|null &$article - */ - public function __construct( Title &$title, Page &$article = null ) { - $this->title = &$title; - $this->article = &$article; - } - - /** - * @since 2.0 - * - * @return true - */ - public function process() { - - if ( $this->title->getNamespace() === SMW_NS_PROPERTY ) { - $this->article = new PropertyPage( $this->title ); - } elseif ( $this->title->getNamespace() === SMW_NS_CONCEPT ) { - $this->article = new ConceptPage( $this->title ); - } - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticlePurge.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticlePurge.php deleted file mode 100644 index 65581464..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ArticlePurge.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\FactboxCache; -use SMW\Application; -use SMW\CacheIdGenerator; - -use WikiPage; - -/** - * A function hook being executed before running "&action=purge" - * - * A temporary cache entry is created to mark and identify the - * Article that has been purged. - * - * @see http://www.mediawiki.org/wiki/Manual:Hooks/ArticlePurge - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class ArticlePurge { - - /** - * @var WikiPage - */ - protected $wikiPage = null; - - /** - * @since 1.9 - * - * @param WikiPage $wikiPage - */ - public function __construct( WikiPage &$wikiPage ) { - $this->wikiPage = $wikiPage; - } - - /** - * @since 1.9 - * - * @return CacheIdGenerator - */ - public static function newCacheId( $pageId ) { - return new CacheIdGenerator( $pageId, 'autorefresh' ); - } - - /** - * @see FunctionHook::process - * - * @since 1.9 - * - * @return true - */ - public function process() { - - $pageId = $this->wikiPage->getTitle()->getArticleID(); - - /** - * @var Settings $settings - */ - $settings = Application::getInstance()->getSettings(); - - /** - * @var CacheHandler $cache - */ - $cache = Application::getInstance()->getCache(); - - $cache->setCacheEnabled( $pageId > 0 ) - ->setKey( $this->newCacheId( $pageId ) ) - ->set( $settings->get( 'smwgAutoRefreshOnPurge' ) ); - - $cache->setCacheEnabled( $settings->get( 'smwgFactboxCacheRefreshOnPurge' ) ) - ->setKey( FactboxCache::newCacheId( $pageId ) ) - ->delete(); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BaseTemplateToolbox.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BaseTemplateToolbox.php deleted file mode 100644 index c3b7b379..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BaseTemplateToolbox.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; -use SMW\NamespaceExaminer; - -use SMWInfolink as Infolink; - -use SpecialPage; -use Title; - -/** - * Hook: Called by BaseTemplate when building the toolbox array and - * returning it for the skin to output. - * - * Add a link to the toolbox to view the properties of the current page in - * Special:Browse. The links has the CSS id "t-smwbrowselink" so that it can be - * skinned or hidden with all standard mechanisms (also by individual users - * with custom CSS). - * - * @see http://www.mediawiki.org/wiki/Manual:Hooks/BaseTemplateToolbox - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class BaseTemplateToolbox { - - /** - * @var SkinTemplate - */ - private $skinTemplate; - - /** - * @var array - */ - private $toolbox; - - /** - * @since 1.9 - * - * @param $skinTemplate - * @param &$toolbox - */ - public function __construct( $skinTemplate, &$toolbox ) { - $this->skinTemplate = $skinTemplate; - $this->toolbox =& $toolbox; - } - - /** - * @since 1.9 - * - * @return boolean - */ - public function process() { - return $this->canPerformUpdate( $this->skinTemplate->getSkin()->getTitle() ) ? $this->performUpdate() : true; - } - - protected function canPerformUpdate( Title $title ) { - return !$title->isSpecialPage() && - Application::getInstance()->getSettings()->get( 'smwgToolboxBrowseLink' ) && - $this->isEnabledNamespace( $title ) && - $this->skinTemplate->data['isarticle']; - } - - protected function performUpdate() { - - $this->toolbox['smw-browse'] = array( - 'text' => $this->skinTemplate->getSkin()->msg( 'smw_browselink' )->text(), - 'href' => SpecialPage::getTitleFor( 'Browse', $this->encodePrefixedDBkey() )->getLocalUrl(), - 'id' => 't-smwbrowselink', - 'rel' => 'smw-browse' - ); - - return true; - } - - private function encodePrefixedDBkey() { - return Infolink::encodeParameters( array( $this->skinTemplate->getSkin()->getTitle()->getPrefixedDBkey() ), true ); - } - - private function isEnabledNamespace( Title $title ) { - return NamespaceExaminer::newFromArray( - Application::getInstance()->getSettings()->get( 'smwgNamespacesWithSemanticLinks' ) )->isSemanticEnabled( $title->getNamespace() ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BeforeDisplayNoArticleText.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BeforeDisplayNoArticleText.php deleted file mode 100644 index 608fd1b4..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BeforeDisplayNoArticleText.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\DIProperty; - -use Title; - -/** - * Before displaying noarticletext or noarticletext-nopermission messages - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforeDisplayNoArticleText - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class BeforeDisplayNoArticleText { - - /** - * @var Page - */ - private $article; - - /** - * @since 2.0 - * - * @param Page $article - */ - public function __construct( $article ) { - $this->article = $article; - } - - /** - * @since 2.0 - * - * @return boolean - */ - public function process() { - - // Avoid having "noarticletext" info being generated for predefined - // properties as we are going to display an introductory text - if ( $this->article->getTitle()->getNamespace() === SMW_NS_PROPERTY ) { - return DIProperty::newFromUserLabel( $this->article->getTitle()->getText() )->isUserDefined(); - } - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BeforePageDisplay.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BeforePageDisplay.php deleted file mode 100644 index 6cc36be2..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/BeforePageDisplay.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use OutputPage; -use Skin; -use Title; -use SpecialPage; - -/** - * BeforePageDisplay hook which allows last minute changes to the - * output page, e.g. adding of CSS or JavaScript - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class BeforePageDisplay { - - /** - * @var OutputPage - */ - protected $outputPage = null; - - /** - * @var Skin - */ - protected $skin = null; - - /** - * @since 1.9 - * - * @param OutputPage &$outputPage - * @param Skin &$skin - */ - public function __construct( OutputPage &$outputPage, Skin &$skin ) { - $this->outputPage = $outputPage; - $this->skin = $skin; - } - - /** - * @since 1.9 - * - * @return boolean - */ - public function process() { - - $title = $this->outputPage->getTitle(); - - // Add style resources to avoid unstyled content - $this->outputPage->addModules( array( 'ext.smw.style' ) ); - - // Add export link to the head - if ( $title instanceof Title && !$title->isSpecialPage() ) { - $linkarr['rel'] = 'ExportRDF'; - $linkarr['type'] = 'application/rdf+xml'; - $linkarr['title'] = $title->getPrefixedText(); - $linkarr['href'] = SpecialPage::getTitleFor( 'ExportRDF', $title->getPrefixedText() )->getLocalUrl( 'xmlmime=rdf' ); - $this->outputPage->addLink( $linkarr ); - } - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ExtensionSchemaUpdates.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ExtensionSchemaUpdates.php deleted file mode 100644 index e9164508..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ExtensionSchemaUpdates.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use DatabaseUpdater; - -/** - * Schema update to set up the needed database tables - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/LoadExtensionSchemaUpdates - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class ExtensionSchemaUpdates { - - /** - * @var DatabaseUpdater - */ - protected $updater = null; - - /** - * @since 2.0 - * - * @param DatabaseUpdater $updater = null - */ - public function __construct( DatabaseUpdater $updater = null ) { - $this->updater = $updater; - } - - /** - * @since 2.0 - * - * @return true - */ - public function process() { - - $this->updater->addExtensionUpdate( array( 'SMWStore::setupStore' ) ); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ExtensionTypes.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ExtensionTypes.php deleted file mode 100644 index 0902e99d..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ExtensionTypes.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -/** - * Called when generating the extensions credits, use this to change the tables headers - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ExtensionTypes - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class ExtensionTypes { - - /** - * @var array - */ - private $extensionTypes = array(); - - /** - * @since 2.0 - * - * @param array $extensionTypes - */ - public function __construct( array &$extensionTypes ) { - $this->extensionTypes =& $extensionTypes; - } - - /** - * @since 2.0 - * - * @return boolean - */ - public function process() { - - if ( !is_array( $this->extensionTypes ) ) { - $this->extensionTypes = array(); - } - - $this->extensionTypes = array_merge( - array( 'semantic' => wfMessage( 'version-semantic' )->text() ), - $this->extensionTypes - ); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/FileUpload.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/FileUpload.php deleted file mode 100644 index 3b068188..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/FileUpload.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; - -use File; - -/** - * Fires when a local file upload occurs - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/FileUpload - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9.1 - * - * @author mwjames - */ -class FileUpload { - - /** - * @var File - */ - private $file = null; - - /** - * @var Application - */ - private $application = null; - - private $fileReUploadStatus = false; - - /** - * @since 1.9.1 - * - * @param File $file - * @param boolean $fileReUploadStatus - */ - public function __construct( File $file, $fileReUploadStatus = false ) { - $this->file = $file; - $this->fileReUploadStatus = $fileReUploadStatus; - } - - /** - * @since 1.9.1 - * - * @return true - */ - public function process() { - return $this->file->getTitle() ? $this->performUpdate() : true; - } - - protected function performUpdate() { - - $this->application = Application::getInstance(); - - $parserData = $this->application - ->newParserData( $this->file->getTitle(), $this->makeParserOutput() ); - - $pageInfoProvider = $this->application - ->newPropertyAnnotatorFactory() - ->newPageInfoProvider( $this->makeFilePage() ); - - $propertyAnnotator = $this->application - ->newPropertyAnnotatorFactory() - ->newPredefinedPropertyAnnotator( $parserData->getSemanticData(), $pageInfoProvider ); - - $propertyAnnotator->addAnnotation(); - - $parserData->updateOutput(); - $parserData->updateStore(); - - return true; - } - - private function makeParserOutput() { - - $contentParser = $this->application->newContentParser( $this->file->getTitle() ); - $contentParser->parse(); - - return $contentParser->getOutput(); - } - - private function makeFilePage() { - - $filePage = $this->application->newPageCreator()->createFilePage( $this->file->getTitle() ); - $filePage->setFile( $this->file ); - - $filePage->smwFileReUploadStatus = $this->fileReUploadStatus; - - return $filePage; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/GetPreferences.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/GetPreferences.php deleted file mode 100644 index 9962be58..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/GetPreferences.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use User; -use Xml; - -/** - * Hook: GetPreferences adds user preference - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/GetPreferences - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class GetPreferences { - - /** - * @var User - */ - private $user = null; - - /** - * @var array - */ - private $preferences; - - /** - * @since 2.0 - * - * @param User $user - * @param array $preferences - */ - public function __construct( User $user, &$preferences ) { - $this->user = $user; - $this->preferences =& $preferences; - } - - /** - * @since 2.0 - * - * @return true - */ - public function process() { - - // Intro text - $this->preferences['smw-prefs-intro'] = - array( - 'type' => 'info', - 'label' => ' ', - 'default' => Xml::tags( 'tr', array(), - Xml::tags( 'td', array( 'colspan' => 2 ), - wfMessage( 'smw-prefs-intro-text' )->parseAsBlock() ) ), - 'section' => 'smw', - 'raw' => 1, - 'rawrow' => 1, - ); - - // Option to enable tooltip info - $this->preferences['smw-prefs-ask-options-tooltip-display'] = array( - 'type' => 'toggle', - 'label-message' => 'smw-prefs-ask-options-tooltip-display', - 'section' => 'smw/ask-options', - ); - - // Preference to set option box be collapsed by default - $this->preferences['smw-prefs-ask-options-collapsed-default'] = array( - 'type' => 'toggle', - 'label-message' => 'smw-prefs-ask-options-collapsed-default', - 'section' => 'smw/ask-options', - ); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/InternalParseBeforeLinks.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/InternalParseBeforeLinks.php deleted file mode 100644 index 176d4f12..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/InternalParseBeforeLinks.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; - -use Parser; -use Title; - -/** - * Hook: InternalParseBeforeLinks is used to process the expanded wiki - * code after <nowiki>, HTML-comments, and templates have been treated. - * - * This method will be called before an article is displayed or previewed. - * For display and preview we strip out the semantic properties and append them - * at the end of the article. - * - * @note MW 1.20+ see InternalParseBeforeSanitize - * - * @see http://www.mediawiki.org/wiki/Manual:Hooks/InternalParseBeforeLinks - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class InternalParseBeforeLinks { - - /** - * @var Parser - */ - protected $parser = null; - - /** - * @var string - */ - protected $text; - - /** - * @since 1.9 - * - * @param Parser $parser - * @param string $text - */ - public function __construct( Parser &$parser, &$text ) { - $this->parser = $parser; - $this->text =& $text; - } - - /** - * @since 1.9 - * - * @return true - */ - public function process() { - return $this->canPerformUpdate() ? $this->performUpdate() : true; - } - - protected function canPerformUpdate() { - - if ( !$this->parser->getTitle()->isSpecialPage() ) { - return true; - } - - $isEnabledSpecialPage = Application::getInstance()->getSettings()->get( 'smwgEnabledSpecialPage' ); - - foreach ( $isEnabledSpecialPage as $specialPage ) { - if ( $this->parser->getTitle()->isSpecial( $specialPage ) ) { - return true; - } - } - - return false; - } - - protected function performUpdate() { - - /** - * @var ParserData $parserData - */ - $parserData = Application::getInstance()->newParserData( - $this->parser->getTitle(), - $this->parser->getOutput() - ); - - /** - * Performs [[link::syntax]] parsing and adding of property annotations - * to the ParserOutput - * - * @var InTextAnnotationParser - */ - $inTextAnnotationParser = Application::getInstance()->newInTextAnnotationParser( $parserData ); - $inTextAnnotationParser->parse( $this->text ); - - $this->parser->getOutput()->setProperty( - 'smw-semanticdata-status', - $parserData->getSemanticData()->getProperties() !== array() - ); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/LinksUpdateConstructed.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/LinksUpdateConstructed.php deleted file mode 100644 index 446ff712..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/LinksUpdateConstructed.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; -use SMW\ContentParser; -use SMW\SemanticData; - -use LinksUpdate; - -/** - * LinksUpdateConstructed hook is called at the end of LinksUpdate() - * - * @see http://www.mediawiki.org/wiki/Manual:Hooks/LinksUpdateConstructed - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class LinksUpdateConstructed { - - /** - * @var LinksUpdate - */ - protected $linksUpdate = null; - - /** - * @var Application - */ - private $application = null; - - /** - * @since 1.9 - * - * @param LinksUpdate $linksUpdate - */ - public function __construct( LinksUpdate $linksUpdate ) { - $this->linksUpdate = $linksUpdate; - } - - /** - * @since 1.9 - * - * @return true - */ - public function process() { - - $this->application = Application::getInstance(); - - /** - * @var ParserData $parserData - */ - $parserData = $this->application - ->newParserData( $this->linksUpdate->getTitle(), $this->linksUpdate->getParserOutput() ); - - if ( $parserData->getSemanticData()->isEmpty() && - ( $semanticData = $this->refetchSemanticData() ) instanceOf SemanticData ) { - $parserData->setSemanticData( $semanticData ); - } - - $parserData->updateStore(); - - return true; - } - - /** - * #347 showed that an external process (e.g. RefreshLinksJob) can inject a - * ParserOutput without/cleared SemanticData which forces the Store updater - * to create an empty container that will clear all existing data. - * - * To ensure that for a Title and its current revision an empty ParserOutput - * object is really meant to be "empty" (e.g. delete action initiated by a - * human) the content is re-parsed in order to fetch the newest available data - * - * @note Parsing is expensive but it is more expensive to loose data or to - * expect that an external process adheres the object contract - */ - private function refetchSemanticData() { - wfDebug( __METHOD__ . ' Empty SemanticData / re-parsing: ' . $this->linksUpdate->getTitle()->getPrefixedDBkey() . "\n" ); - - $contentParser = $this->application->newContentParser( $this->linksUpdate->getTitle() ); - $parserOutput = $contentParser->parse()->getOutput(); - - if ( $parserOutput === null ) { - return null; - } - - if ( method_exists( $parserOutput, 'getExtensionData' ) ) { - return $parserOutput->getExtensionData( 'smwdata' ); - } - - return $parserOutput->mSMWData; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/NewRevisionFromEditComplete.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/NewRevisionFromEditComplete.php deleted file mode 100644 index 2224ee0e..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/NewRevisionFromEditComplete.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\MediaWiki\EditInfoProvider; -use SMW\Application; - -use ParserOutput; -use Title; - -/** - * Hook: NewRevisionFromEditComplete called when a revision was inserted - * due to an edit - * - * Fetch additional information that is related to the saving that has just happened, - * e.g. regarding the last edit date. In runs where this hook is not triggered, the - * last DB entry (of MW) will be used to fill such properties. - * - * Called from LocalFile.php, SpecialImport.php, Article.php, Title.php - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/NewRevisionFromEditComplete - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class NewRevisionFromEditComplete { - - /** - * @var WikiPage - */ - private $wikiPage = null; - - /** - * @var Revision - */ - private $revision = null; - - /** - * @var integer - */ - private $baseId = null; - - /** - * @var User|null - */ - private $user = null; - - /** - * @var ParserOutput|null - */ - private $parserOutput = null; - - /** - * @since 1.9 - * - * @param WikiPage $article the article edited - * @param Revision $rev the new revision. Revision object - * @param $baseId the revision ID this was based off, if any - * @param User $user the revision author. User object - */ - public function __construct( $wikiPage, $revision, $baseId, $user = null ) { - $this->wikiPage = $wikiPage; - $this->revision = $revision; - $this->baseId = $baseId; - $this->user = $user; - } - - /** - * @since 1.9 - * - * @return boolean - */ - public function process() { - return $this->getParserOutputFromEditInfo() instanceof ParserOutput ? $this->performUpdate() : true; - } - - protected function getParserOutputFromEditInfo() { - $editInfoProvider = new EditInfoProvider( $this->wikiPage, $this->revision, $this->user ); - return $this->parserOutput = $editInfoProvider->fetchEditInfo()->getOutput(); - } - - protected function performUpdate() { - - $application = Application::getInstance(); - - $parserData = $application - ->newParserData( $this->wikiPage->getTitle(), $this->parserOutput ); - - $pageInfoProvider = $application - ->newPropertyAnnotatorFactory() - ->newPageInfoProvider( $this->wikiPage, $this->revision, $this->user ); - - $propertyAnnotator = $application - ->newPropertyAnnotatorFactory() - ->newPredefinedPropertyAnnotator( $parserData->getSemanticData(), $pageInfoProvider ); - - $propertyAnnotator->addAnnotation(); - $parserData->updateOutput(); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/OutputPageParserOutput.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/OutputPageParserOutput.php deleted file mode 100644 index 79dc6589..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/OutputPageParserOutput.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; -use SMW\NamespaceExaminer; - -use ParserOutput; -use OutputPage; -use Title; - -use SMWOutputs; - -/** - * OutputPageParserOutput hook is called after parse, before the HTML is - * added to the output - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/OutputPageParserOutput - * - * @note This hook copies SMW's custom data from the given ParserOutput object to - * the given OutputPage object, since otherwise it is not possible to access - * it later on to build a Factbox. - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class OutputPageParserOutput { - - /** - * @var OutputPage - */ - protected $outputPage = null; - - /** - * @var ParserOutput - */ - protected $parserOutput = null; - - /** - * @since 1.9 - * - * @param OutputPage $outputPage - * @param ParserOutput $parserOutput - */ - public function __construct( OutputPage &$outputPage, ParserOutput $parserOutput ) { - $this->outputPage = $outputPage; - $this->parserOutput = $parserOutput; - } - - /** - * @see FunctionHook::process - * - * @since 1.9 - * - * @return true - */ - public function process() { - return $this->canPerformUpdate() ? $this->performUpdate() : true; - } - - protected function canPerformUpdate() { - - $title = $this->outputPage->getTitle(); - - if ( $title->isSpecialPage() || - $title->isRedirect() || - !$this->isEnabledNamespace( $title ) ) { - return false; - } - - if ( isset( $this->outputPage->mSMWFactboxText ) && $this->outputPage->getContext()->getRequest()->getCheck( 'wpPreview' ) ) { - return false; - } - - return true; - } - - protected function performUpdate() { - - $factboxCache = Application::getInstance()->newFactboxBuilder()->newFactboxCache( $this->outputPage ); - $factboxCache->process( $this->getParserOutput() ); - - return true; - } - - protected function getParserOutput() { - - if ( $this->outputPage->getContext()->getRequest()->getInt( 'oldid' ) ) { - - $text = $this->parserOutput->getText(); - - $parserData = Application::getInstance()->newParserData( - $this->outputPage->getTitle(), - $this->parserOutput - ); - - $inTextAnnotationParser = Application::getInstance()->newInTextAnnotationParser( $parserData ); - $inTextAnnotationParser->parse( $text ); - - return $parserData->getOutput(); - } - - return $this->parserOutput; - } - - private function isEnabledNamespace( Title $title ) { - return NamespaceExaminer::newFromArray( - Application::getInstance()->getSettings()->get( 'smwgNamespacesWithSemanticLinks' ) )->isSemanticEnabled( $title->getNamespace() - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ParserAfterTidy.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ParserAfterTidy.php deleted file mode 100644 index a1f77f4a..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ParserAfterTidy.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; - -use Parser; -use Title; - -/** - * Hook: ParserAfterTidy to add some final processing to the - * fully-rendered page output - * - * @see http://www.mediawiki.org/wiki/Manual:Hooks/ParserAfterTidy - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class ParserAfterTidy { - - /** - * @var Parser - */ - private $parser = null; - - /** - * @var string - */ - private $text; - - /** - * @since 1.9 - * - * @param Parser $parser - * @param string $text - */ - public function __construct( Parser &$parser, &$text ) { - $this->parser = $parser; - $this->text =& $text; - } - - /** - * @since 1.9 - * - * @return true - */ - public function process() { - return $this->canPerformUpdate() ? $this->performUpdate() : true; - } - - protected function canPerformUpdate() { - - if ( $this->parser->getTitle()->isSpecialPage() ) { - return false; - } - - if ( $this->parser->getOutput()->getProperty( 'smw-semanticdata-status' ) || - $this->parser->getOutput()->getCategoryLinks() || - $this->parser->getDefaultSort() ) { - return true; - } - - return false; - } - - protected function performUpdate() { - - $this->application = Application::getInstance(); - - $parserData = $this->application - ->newParserData( $this->parser->getTitle(), $this->parser->getOutput() ); - - $propertyAnnotator = $this->application - ->newPropertyAnnotatorFactory() - ->newSortkeyPropertyAnnotator( $parserData->getSemanticData(), $this->parser->getDefaultSort() ); - - $propertyAnnotator->addAnnotation(); - - $propertyAnnotator = $this->application - ->newPropertyAnnotatorFactory() - ->newCategoryPropertyAnnotator( $parserData->getSemanticData(), $this->parser->getOutput()->getCategoryLinks() ); - - $propertyAnnotator->addAnnotation(); - - $parserData->updateOutput(); - - $this->forceManualUpdateDueToPagePurge( $parserData ); - - return true; - } - - /** - * @note Article purge: In case an article was manually purged/moved - * the store is updated as well; for all other cases LinksUpdateConstructed - * will handle the store update - */ - protected function forceManualUpdateDueToPagePurge( $parserData ) { - - $cache = $this->application->getCache(); - - $cache->setKey( ArticlePurge::newCacheId( $this->parser->getTitle()->getArticleID() ) ); - - if( $cache->get() ) { - $cache->delete(); - $parserData->updateStore(); - } - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/README.md b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/README.md deleted file mode 100644 index 0f56b3ad..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/README.md +++ /dev/null @@ -1,39 +0,0 @@ -[Hooks][hooks] are so-called event handlers that allow custom code to be executed. Semantic MediaWiki (SMW) uses several of those hooks to enable specific process logic to be integrated with MediaWiki. SMW currently uses the following hooks: - -#### ArticlePurge -ArticlePurge is executed during a manual purge action of an article and depending on available settings is being used to track a page refresh. - -#### BeforePageDisplay -BeforePageDisplay allows last minute changes to the output page and is being used to render a ExportRDF link into each individual article. - -#### InternalParseBeforeLinks -InternalParseBeforeLinks is used to process and expand text content, and in case of SMW it is used to identify and resolve the property annotation syntax ([[link::syntax]]), returning a modified content component and storing annotations within the ParserOutput object. - -#### LinksUpdateConstructed -LinksUpdateConstructed is called at the end of LinksUpdate and is being used to initiate a store update for data that were held by the ParserOutput object. - -#### NewRevisionFromEditComplete -NewRevisionFromEditComplete called when a new revision was inserted due to an edit and used to update the ParserOuput with the latests special property annotation. - -#### ParserAfterTidy -ParserAfterTidy is used to re-introduce content, update base annotations (e.g. special properties, categories etc.) and in case of a manual article purge initiates a store update (LinksUpdateConstructed wouldn't work because it acts only on link changes and therefore would not trigger a LinksUpdateConstructed event). - -#### SpecialStatsAddExtra -SpecialStatsAddExtra is used to add additional statistic being shown at Special:Statistics. - -#### SkinAfterContent -Extend the display with content from the Factbox. - -#### OutputPageParserOutput -Rendering the Factbox and updating the FactboxCache. - -#### TitleMoveComplete -Update the Store after an article has been deleted. - -#### ResourceLoaderGetConfigVars - -#### GetPreferences - -#### SkinTemplateNavigation - -[hooks]: https://www.mediawiki.org/wiki/Hooks "Manual:Hooks"
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ResourceLoaderGetConfigVars.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ResourceLoaderGetConfigVars.php deleted file mode 100644 index 9f9413a1..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ResourceLoaderGetConfigVars.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMWQueryProcessor; -use MWNamespace; - -/** - * Hook: ResourceLoaderGetConfigVars called right before - * ResourceLoaderStartUpModule::getConfig and exports static configuration - * variables to JavaScript. Things that depend on the current - * page/request state should use MakeGlobalVariablesScript instead - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderGetConfigVars - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class ResourceLoaderGetConfigVars { - - /** - * @var array - */ - protected $vars; - - /** - * @since 2.0 - * - * @param array $vars - */ - public function __construct( array &$vars ) { - $this->vars =& $vars; - } - - /** - * @since 1.9 - * - * @return boolean - */ - public function process() { - - $this->vars['smw-config'] = array( - 'version' => SMW_VERSION, - 'settings' => array( - 'smwgQMaxLimit' => $GLOBALS['smwgQMaxLimit'], - 'smwgQMaxInlineLimit' => $GLOBALS['smwgQMaxInlineLimit'], - ) - ); - - // Available semantic namespaces - foreach ( array_keys( $GLOBALS['smwgNamespacesWithSemanticLinks'] ) as $ns ) { - $name = MWNamespace::getCanonicalName( $ns ); - $this->vars['smw-config']['settings']['namespace'][$name] = $ns; - } - - foreach ( array_keys( $GLOBALS['smwgResultFormats'] ) as $format ) { - // Special formats "count" and "debug" currently not supported. - if ( $format != 'broadtable' && $format != 'count' && $format != 'debug' ) { - $printer = SMWQueryProcessor::getResultPrinter( $format, SMWQueryProcessor::SPECIAL_PAGE ); - $this->vars['smw-config']['formats'][$format] = $printer->getName(); - } - } - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ResourceLoaderTestModules.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ResourceLoaderTestModules.php deleted file mode 100644 index 9a1ef0d8..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/ResourceLoaderTestModules.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use ResourceLoader; - -/** - * Add new JavaScript/QUnit testing modules - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderTestModules - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class ResourceLoaderTestModules { - - /** - * @var ResourceLoader - */ - private $resourceLoader; - - /** - * @var array - */ - private $testModules; - - /** - * @var string - */ - private $installPath; - - /** - * @var string - */ - private $basePath; - - /** - * @since 2.0 - * - * @param ResourceLoader $resourceLoader object - * @param array $testModules array of JavaScript testing modules - * @param string $basePath - * @param string $installPath - */ - public function __construct( ResourceLoader &$resourceLoader, array &$testModules, $basePath, $installPath ) { - $this->resourceLoader = $resourceLoader; - $this->testModules =& $testModules; - $this->basePath = $basePath; - $this->installPath = $installPath; - } - - /** - * @since 1.9 - * - * @return boolean - */ - public function process() { - - $this->testModules['qunit']['ext.smw.tests'] = array( - 'scripts' => array( - 'tests/qunit/smw/ext.smw.test.js', - 'tests/qunit/smw/util/ext.smw.util.tooltip.test.js', - - // dataItem tests - 'tests/qunit/smw/data/ext.smw.dataItem.wikiPage.test.js', - 'tests/qunit/smw/data/ext.smw.dataItem.uri.test.js', - 'tests/qunit/smw/data/ext.smw.dataItem.time.test.js', - 'tests/qunit/smw/data/ext.smw.dataItem.property.test.js', - 'tests/qunit/smw/data/ext.smw.dataItem.unknown.test.js', - 'tests/qunit/smw/data/ext.smw.dataItem.number.test.js', - 'tests/qunit/smw/data/ext.smw.dataItem.text.test.js', - - // dataValues - 'tests/qunit/smw/data/ext.smw.dataValue.quantity.test.js', - - // Api / Query - 'tests/qunit/smw/data/ext.smw.data.test.js', - 'tests/qunit/smw/api/ext.smw.api.test.js', - 'tests/qunit/smw/query/ext.smw.query.test.js', - ), - 'dependencies' => array( - 'ext.smw', - 'ext.smw.tooltip', - 'ext.smw.query', - 'ext.smw.data', - 'ext.smw.api' - ), - 'position' => 'top', - 'localBasePath' => $this->basePath, - 'remoteExtPath' => '..' . substr( $this->basePath, strlen( $this->installPath ) ), - ); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SkinAfterContent.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SkinAfterContent.php deleted file mode 100644 index 91dd6823..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SkinAfterContent.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; - -use OutputPage; -use Title; -use Skin; - -/** - * SkinAfterContent hook to add text after the page content and - * article metadata - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/SkinAfterContent - * - * @note This hook is used for inserting the Factbox text after the - * article contents (including categories). - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SkinAfterContent { - - /** - * @var string - */ - protected $data = null; - - /** - * @var Skin - */ - protected $skin = null; - - /** - * @since 1.9 - * - * @param string $data - * @param Skin|null $skin - */ - public function __construct( &$data, Skin $skin = null ) { - $this->data =& $data; - $this->skin = $skin; - } - - /** - * @since 1.9 - * - * @return true - */ - public function process() { - - $factboxCache = Application::getInstance()->newFactboxBuilder()->newFactboxCache( $this->skin->getOutput() ); - $this->data .= $factboxCache->retrieveContent(); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SkinTemplateNavigation.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SkinTemplateNavigation.php deleted file mode 100644 index 09fd3e22..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SkinTemplateNavigation.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SkinTemplate; - -/** - * Alter the structured navigation links in SkinTemplates. - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/SkinTemplateNavigation - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class SkinTemplateNavigation { - - /** - * @var SkinTemplate - */ - private $skinTemplate = null; - - /** - * @var array - */ - private $links; - - /** - * @since 2.0 - * - * @param SkinTemplate $skinTemplate - * @param array $links - */ - public function __construct( SkinTemplate &$skinTemplate, array &$links ) { - $this->skinTemplate = $skinTemplate; - $this->links =& $links; - } - - /** - * @since 2.0 - * - * @return true - */ - public function process() { - - if ( $this->skinTemplate->getUser()->isAllowed( 'purge' ) ) { - $this->links['actions']['purge'] = array( - 'class' => false, - 'text' => $this->skinTemplate->msg( 'smw_purge' )->text(), - 'href' => $this->skinTemplate->getTitle()->getLocalUrl( array( 'action' => 'purge' ) ) - ); - } - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SpecialStatsAddExtra.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SpecialStatsAddExtra.php deleted file mode 100644 index 5f39951b..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/SpecialStatsAddExtra.php +++ /dev/null @@ -1,133 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; -use SMW\DataTypeRegistry; - -use Language; - -/** - * Add extra statistic at the end of Special:Statistics - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/SpecialStatsAddExtra - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class SpecialStatsAddExtra { - - /** - * @var array - */ - protected $extraStats = null; - - /** - * @var string - */ - protected $version = null; - - /** - * @var Language - */ - protected $userLanguage; - - /** - * @var string[] - */ - protected $legacyMessageMapper = array( - 'PROPUSES' => 'smw-statistics-property-instance', - 'USEDPROPS' => 'smw-statistics-property-total-legacy', - 'OWNPAGE' => 'smw-statistics-property-page', - 'DECLPROPS' => 'smw-statistics-property-type', - 'SUBOBJECTS' => 'smw-statistics-subobject-count', - 'QUERY' => 'smw-statistics-query-inline', - 'CONCEPTS' => 'smw-statistics-concept-count-legacy' - ); - - /** - * @var string[] - */ - protected $messageMapper = array( - 'PROPUSES' => 'smw-statistics-property-instance', - 'USEDPROPS' => 'smw-statistics-property-total', - 'OWNPAGE' => 'smw-statistics-property-page', - 'DECLPROPS' => 'smw-statistics-property-type', - 'SUBOBJECTS' => 'smw-statistics-subobject-count', - 'QUERY' => 'smw-statistics-query-inline', - 'CONCEPTS' => 'smw-statistics-concept-count' - ); - - /** - * @since 1.9 - * - * @param array &$extraStats - * @param string $version - * @param Language $userLanguage User language - */ - public function __construct( array &$extraStats, $version, Language $userLanguage ) { - $this->extraStats =& $extraStats; - $this->version = $version; - $this->userLanguage = $userLanguage; - } - - /** - * @since 1.9 - * - * @return true - */ - public function process() { - return version_compare( $this->version, '1.21', '<' ) ? $this->copyLegacyStatistics() : $this->copyStatistics(); - } - - /** - * @since 1.9 - * - * @return true - */ - protected function copyStatistics() { - - $statistics = Application::getInstance()->getStore()->getStatistics(); - - $this->extraStats['smw-statistics'] = array(); - - foreach ( $this->messageMapper as $key => $message ) { - - if ( isset( $statistics[$key] ) ) { - $this->extraStats['smw-statistics'][ $message ] = $statistics[$key]; - } - } - - $count = count( DataTypeRegistry::getInstance()->getKnownTypeLabels() ); - $this->extraStats['smw-statistics']['smw-statistics-datatype-count'] = $count; - - return true; - - } - - /** - * Legacy approach to display statistical items for all MW 1.21- versions - * - * @since 1.9 - * - * @return true - */ - protected function copyLegacyStatistics() { - - $statistics = Application::getInstance()->getStore()->getStatistics(); - - foreach ( $this->legacyMessageMapper as $key => $message ) { - - if ( isset( $statistics[$key] ) ) { - $this->extraStats[wfMessage( $message )->text()] = $this->userLanguage->formatNum( $statistics[$key] ); - } - } - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/TitleIsAlwaysKnown.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/TitleIsAlwaysKnown.php deleted file mode 100644 index cfe68426..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/TitleIsAlwaysKnown.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\DIProperty; - -use Title; - -/** - * Allows overriding default behaviour for determining if a page exists - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/TitleIsAlwaysKnown - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class TitleIsAlwaysKnown { - - /** - * @var Title - */ - private $title; - - /** - * @var mixed - */ - private $result; - - /** - * @since 2.0 - * - * @param Title $title - * @param mixed &$result - */ - public function __construct( Title $title, &$result ) { - $this->title = $title; - $this->result =& $result; - } - - /** - * @since 2.0 - * - * @return boolean - */ - public function process() { - - // Two possible ways of going forward: - // - // The FIRST seen here is to use the hook to override the known status - // for predefined properties in order to avoid any edit link - // which makes no-sense for predefined properties - // - // The SECOND approach is to inject SMWWikiPageValue with a setLinkOptions setter - // that enables to set the custom options 'known' for each invoked linker during - // getShortHTMLText - // $linker->link( $this->getTitle(), $caption, $customAttributes, $customQuery, $customOptions ) - // - // @see also HooksTest::testOnTitleIsAlwaysKnown - - if ( $this->title->getNamespace() === SMW_NS_PROPERTY ) { - if ( !DIProperty::newFromUserLabel( $this->title->getText() )->isUserDefined() ) { - $this->result = true; - } - } - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/TitleMoveComplete.php b/SemanticMediaWiki/includes/src/MediaWiki/Hooks/TitleMoveComplete.php deleted file mode 100644 index a754919a..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Hooks/TitleMoveComplete.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Hooks; - -use SMW\Application; - -/** - * TitleMoveComplete occurs whenever a request to move an article - * is completed - * - * This method will be called whenever an article is moved so that - * semantic properties are moved accordingly. - * - * @see http://www.mediawiki.org/wiki/Manual:Hooks/TitleMoveComplete - * - * @ingroup FunctionHook - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class TitleMoveComplete { - - /** - * @var Title - */ - protected $oldTitle = null; - - /** - * @var Title - */ - protected $newTitle = null; - - /** - * @var User - */ - protected $user = null; - - /** - * @var integer - */ - protected $oldId; - - /** - * @var integer - */ - protected $newId; - - /** - * @since 1.9 - * - * @param Title $oldTitle old title - * @param Title $newTitle: new title - * @param Use $user user who did the move - * @param $oldId database ID of the page that's been moved - * @param $newId database ID of the created redirect - */ - public function __construct( &$oldTitle, &$newTitle, &$user, $oldId, $newId ) { - $this->oldTitle = $oldTitle; - $this->newTitle = $newTitle; - $this->user = $user; - $this->oldId = $oldId; - $this->newId = $newId; - } - - /** - * @since 1.9 - * - * @return true - */ - public function process() { - - /** - * @var Settings $settings - */ - $settings = Application::getInstance()->getSettings(); - - /** - * @var CacheHandler $cache - */ - $cache = Application::getInstance()->getCache(); - - $cache->setCacheEnabled( $this->newId > 0 ) - ->setKey( ArticlePurge::newCacheId( $this->newId ) ) - ->set( $settings->get( 'smwgAutoRefreshOnPageMove' ) ); - - $cache->setCacheEnabled( $this->oldId > 0 ) - ->setKey( ArticlePurge::newCacheId( $this->oldId ) ) - ->set( $settings->get( 'smwgAutoRefreshOnPageMove' ) ); - - Application::getInstance()->getStore()->changeTitle( - $this->oldTitle, - $this->newTitle, - $this->oldId, - $this->newId - ); - - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/DeleteSubjectJob.php b/SemanticMediaWiki/includes/src/MediaWiki/Jobs/DeleteSubjectJob.php deleted file mode 100644 index 8a926df8..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/DeleteSubjectJob.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Jobs; - -use SMW\DIWikiPage; -use SMW\SerializerFactory; -use SMW\Application; - -use Title; -use Job; - -/** - * Handle subject removal directly or as deferred job - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9.1 - * - * @author mwjames - */ -class DeleteSubjectJob extends JobBase { - - /** - * @since 1.9.1 - * - * @param Title $title - * @param array $params job parameters - */ - public function __construct( Title $title, $params = array() ) { - parent::__construct( 'SMW\DeleteSubjectJob', $title, $params ); - $this->removeDuplicates = true; - } - - /** - * deleteSubject() will eliminate any associative reference to a subject - * therefore when run as `DeferredJob` and before the actual removal SemanticData - * are serialized and attached to the dispatch job, this allows to decouple - * deletion from an update process (prioritization between subject deletion - * and data refresh process) - * - * @since 1.9.1 - * - * @return boolean - */ - public function execute() { - - if ( Application::getInstance()->getSettings()->get( 'smwgEnableUpdateJobs' ) && - $this->hasParameter( 'asDeferredJob' ) && - $this->getParameter( 'asDeferredJob' ) ) { - $this->insertAsDeferredJobWithSemanticData()->pushToJobQueue(); - return $this->deleteSubject(); - } - - return $this->run(); - } - - /** - * @see Job::run - * - * @since 1.9.1 - */ - public function run() { - - if ( $this->hasParameter( 'withAssociates' ) && $this->getParameter( 'withAssociates' ) ) { - $this->initUpdateDispatcherJob(); - } - - return $this->deleteSubject(); - } - - protected function initUpdateDispatcherJob() { - Application::getInstance() - ->newJobFactory() - ->newUpdateDispatcherJob( $this->getTitle(), $this->params ) - ->run(); - } - - protected function deleteSubject() { - Application::getInstance()->getStore()->deleteSubject( $this->getTitle() ); - return true; - } - - protected function insertAsDeferredJobWithSemanticData() { - - $this->params['semanticData'] = $this->fetchSerializedSemanticData(); - - $this->jobs[] = new self( $this->getTitle(), $this->params ); - return $this; - } - - protected function fetchSerializedSemanticData() { - return Application::getInstance()->newSerializerFactory()->serialize( - Application::getInstance()->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->getTitle() ) ) - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/JobBase.php b/SemanticMediaWiki/includes/src/MediaWiki/Jobs/JobBase.php deleted file mode 100644 index e0570513..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/JobBase.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Jobs; - -use Job; -use Title; - -/** - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -abstract class JobBase extends Job { - - /** - * @var boolean - */ - protected $enabledJobQueue = true; - - /** - * @var Job - */ - protected $jobs = array(); - - /** - * Whether to insert jobs into the JobQueue is enabled or not - * - * @since 1.9 - * - * @param boolean|true $enableJobQueue - * - * @return JobBase - */ - public function setJobQueueEnabledState( $enableJobQueue = true ) { - $this->enabledJobQueue = (bool)$enableJobQueue; - return $this; - } - - /** - * @note Job::batchInsert was deprecated in MW 1.21 - * JobQueueGroup::singleton()->push( $job ); - * - * @since 1.9 - */ - public function pushToJobQueue() { - $this->enabledJobQueue ? Job::batchInsert( $this->jobs ) : null; - } - - /** - * @note Job::getType was introduced with MW 1.21 - * - * @return string - */ - public function getType() { - return $this->command; - } - - /** - * @since 2.0 - * - * @return integer - */ - public function getJobCount() { - return count( $this->jobs ); - } - - /** - * @note Job::getTitle() in MW 1.19 does not exist - * - * @since 1.9 - * - * @return Title - */ - public function getTitle() { - return $this->title; - } - - /** - * Whether the parameters contain an element for a given key - * - * @since 1.9 - * - * @param mixed $key - * - * @return boolean - */ - public function hasParameter( $key ) { - return isset( $this->params[ $key ] ) || array_key_exists( $key, $this->params ); - } - - /** - * Returns a parameter value for a given key - * - * @since 1.9 - * - * @param mixed $key - * - * @return boolean - */ - public function getParameter( $key ) { - return $this->params[ $key ]; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/JobFactory.php b/SemanticMediaWiki/includes/src/MediaWiki/Jobs/JobFactory.php deleted file mode 100644 index 5b262288..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/JobFactory.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Jobs; - -use Title; - -/** - * Access MediaWiki Job instances - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class JobFactory { - - /** - * @since 2.0 - * - * @param Title $title - * - * @return UpdateJob - */ - public function newUpdateJob( Title $title ) { - return new UpdateJob( $title ); - } - - /** - * @since 2.0 - * - * @param Title $title - * @param array $parameters - * - * @return UpdateDispatcherJob - */ - public function newUpdateDispatcherJob( Title $title, array $parameters = array() ) { - return new UpdateDispatcherJob( $title, $parameters ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/RefreshJob.php b/SemanticMediaWiki/includes/src/MediaWiki/Jobs/RefreshJob.php deleted file mode 100644 index 5ee562a4..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/RefreshJob.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Jobs; - -use SMW\Profiler; -use SMW\Application; - -/** - * RefreshJob iterates over all page ids of the wiki, to perform an update - * action for all of them in sequence. This corresponds to the in-wiki version - * of the SMW_refreshData.php script for updating the whole wiki. - * - * @note This class ignores $smwgEnableUpdateJobs and always creates updates. - * In fact, it might be needed specifically on wikis that do not use update - * jobs in normal operation. - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Markus Krötzsch - * @author mwjames - */ -class RefreshJob extends JobBase { - - /** - * Constructor. The parameters optionally specified in the second - * argument of this constructor use the following array keys: 'spos' - * (start index, default 1), 'prog' (progress indicator, default 0), - * ('rc' (number of runs to be done, default 1). If more than one run - * is done, then the first run will restrict to properties and types. - * The progress indication refers to the current run, not to the - * overall job. - * - * @param $title Title not relevant but needed for MW jobs - * @param $params array (associative) as explained above - */ - public function __construct( $title, $params = array( 'spos' => 1, 'prog' => 0, 'rc' => 1 ) ) { - parent::__construct( 'SMW\RefreshJob', $title, $params ); - } - - /** - * @since 1.9 - * - * @return boolean success - */ - public function run() { - return $this->hasParameter( 'spos' ) ? $this->refreshData( $this->getParameter( 'spos' ) ) : true; - } - - /** - * Report the estimated progress status of this job as a number between - * 0 and 1 (0% to 100%). The progress refers to the state before - * processing this job. - * - * @return double - */ - public function getProgress() { - - $prog = $this->hasParameter( 'prog' ) ? $this->getParameter( 'prog' ) : 0; - $run = $this->hasParameter( 'run' ) ? $this->getParameter( 'run' ): 1; - $rc = $this->hasParameter( 'rc' ) ? $this->getParameter( 'rc' ) : 1; - - return ( $run - 1 + $prog ) / $rc; - } - - /** - * @see Job::insert - * @codeCoverageIgnore - */ - public function insert() { - if ( $this->enabledJobQueue ) { - parent::insert(); - } - } - - /** - * @param $spos start index - */ - protected function refreshData( $spos ) { - Profiler::In(); - - $run = $this->hasParameter( 'run' ) ? $this->getParameter( 'run' ) : 1; - $prog = Application::getInstance()->getStore()->refreshData( $spos, 20, $this->getNamespace( $run ) ); - - if ( $spos > 0 ) { - - $this->createNextJob( array( - 'spos' => $spos, - 'prog' => $prog, - 'rc' => $this->getParameter( 'rc' ), - 'run' => $run - ) ); - - } elseif ( $this->getParameter( 'rc' ) > $run ) { // do another run from the beginning - - $this->createNextJob( array( - 'spos' => 1, - 'prog' => 0, - 'rc' => $this->getParameter( 'rc' ), - 'run' => $run + 1 - ) ); - - } - - Profiler::Out(); - return true; - } - - protected function createNextJob( array $parameters ) { - $nextjob = new self( $this->getTitle(), $parameters ); - $nextjob->setJobQueueEnabledState( $this->enabledJobQueue )->insert(); - } - - protected function getNamespace( $run ) { - return ( ( $this->getParameter( 'rc' ) > 1 ) && ( $run == 1 ) ) ? array( SMW_NS_PROPERTY, SMW_NS_TYPE ) : false; - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/UpdateDispatcherJob.php b/SemanticMediaWiki/includes/src/MediaWiki/Jobs/UpdateDispatcherJob.php deleted file mode 100644 index da94065f..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/UpdateDispatcherJob.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Jobs; - -use SMW\SerializerFactory; -use SMW\Application; -use SMW\DIProperty; -use SMW\DIWikiPage; -use SMW\Profiler; - -use Title; -use Job; - -/** - * Dispatcher class to invoke UpdateJob's - * - * Can be run either in deferred or immediate mode to restore the data parity - * between a property and its attached subjects - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class UpdateDispatcherJob extends JobBase { - - /** @var Store */ - protected $store = null; - - /** - * @since 1.9 - * - * @param Title $title - * @param array $params job parameters - * @param integer $id job id - */ - public function __construct( Title $title, $params = array(), $id = 0 ) { - parent::__construct( 'SMW\UpdateDispatcherJob', $title, $params, $id ); - $this->removeDuplicates = true; - } - - /** - * @see Job::run - * - * @since 1.9 - * - * @return boolean - */ - public function run() { - Profiler::In( __METHOD__, true ); - - /** - * @var Store $store - */ - $this->store = Application::getInstance()->getStore(); - - if ( $this->getTitle()->getNamespace() === SMW_NS_PROPERTY ) { - $this->dispatchUpdateForProperty( DIProperty::newFromUserLabel( $this->getTitle()->getText() ) )->pushToJobQueue(); - } - - $this->dispatchUpdateForSubject( DIWikiPage::newFromTitle( $this->getTitle() ) )->pushToJobQueue(); - - Profiler::Out( __METHOD__, true ); - return true; - } - - /** - * @see Job::insert - * - * @since 1.9 - * @codeCoverageIgnore - */ - public function insert() { - if ( Application::getInstance()->getSettings()->get( 'smwgEnableUpdateJobs' ) ) { - parent::insert(); - } - } - - /** - * @since 1.9.0.1 - * - * @param DIWikiPage $subject - */ - protected function dispatchUpdateForSubject( DIWikiPage $subject ) { - Profiler::In( __METHOD__, true ); - - $this->addUpdateJobsForProperties( $this->store->getProperties( $subject ) ); - $this->addUpdateJobsForProperties( $this->store->getInProperties( $subject ) ); - - $this->addUpdateJobsFromSerializedData(); - - Profiler::Out( __METHOD__, true ); - return $this; - } - - /** - * Generates list of involved subjects - * - * @since 1.9 - * - * @param DIProperty $property - */ - protected function dispatchUpdateForProperty( DIProperty $property ) { - Profiler::In( __METHOD__, true ); - - $this->addUpdateJobsForProperties( array( $property ) ); - - // Hook deprecated with SMW 1.9 and will vanish with SMW 1.11 - wfRunHooks( 'smwUpdatePropertySubjects', array( &$this->jobs ) ); - - // Hook since 1.9 - wfRunHooks( 'SMW::Job::updatePropertyJobs', array( &$this->jobs, $property ) ); - - $this->addUpdateJobsForPropertyWithTypeError(); - $this->addUpdateJobsFromSerializedData(); - - Profiler::Out( __METHOD__, true ); - return $this; - } - - protected function addUpdateJobsForProperties( array $properties ) { - foreach ( $properties as $property ) { - - if ( $property->isUserDefined() ) { - $this->addUniqueUpdateJobs( $this->store->getAllPropertySubjects( $property ) ); - } - - } - } - - protected function addUpdateJobsForPropertyWithTypeError() { - $subjects = $this->store->getPropertySubjects( - new DIProperty( DIProperty::TYPE_ERROR ), - DIWikiPage::newFromTitle( $this->getTitle() ) - ); - - $this->addUniqueUpdateJobs( $subjects ); - } - - protected function addUpdateJobsFromSerializedData() { - if ( $this->hasParameter( 'semanticData' ) ) { - $this->addUpdateJobsForProperties( - Application::getInstance()->newSerializerFactory()->deserialize( $this->getParameter( 'semanticData' ) )->getProperties() - ); - } - } - - protected function addUniqueUpdateJobs( array $subjects = array() ) { - - foreach ( $subjects as $subject ) { - - $title = $subject->getTitle(); - - if ( $title instanceof Title ) { - $this->jobs[$title->getPrefixedDBkey()] = new UpdateJob( $title ); - } - } - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/UpdateJob.php b/SemanticMediaWiki/includes/src/MediaWiki/Jobs/UpdateJob.php deleted file mode 100644 index 581499c6..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/Jobs/UpdateJob.php +++ /dev/null @@ -1,123 +0,0 @@ -<?php - -namespace SMW\MediaWiki\Jobs; - -use SMW\FactboxCache; -use SMW\Profiler; -use SMW\Application; - -use ParserOutput; -use LinkCache; -use Title; - -/** - * UpdateJob is responsible for the asynchronous update of semantic data - * using MediaWiki's JobQueue infrastructure. - * - * Update jobs are created if, when saving an article, - * it is detected that the content of other pages must be re-parsed as well (e.g. - * due to some type change). - * - * @note This job does not update the page display or parser cache, so in general - * it might happen that part of the wiki page still displays based on old data (e.g. - * formatting in-page values based on a datatype thathas since been changed), whereas - * the Factbox and query/browsing interfaces might already show the updated records. - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Daniel M. Herzig - * @author Markus Krötzsch - * @author mwjames - */ -class UpdateJob extends JobBase { - - /** - * @since 1.9 - * - * @param Title $title - */ - function __construct( Title $title ) { - parent::__construct( 'SMW\UpdateJob', $title ); - $this->removeDuplicates = true; - } - - /** - * @see Job::run - * - * @return boolean - */ - public function run() { - Profiler::In( __METHOD__ . '-run' ); - - LinkCache::singleton()->clear(); - - $result = $this->doUpdate(); - - Profiler::Out( __METHOD__ . '-run' ); - return $result; - } - - /** - * @see Job::insert - * - * This actually files the job. This is prevented if the configuration of SMW - * disables jobs. - * - * @note Any method that inserts jobs with Job::batchInsert or otherwise must - * implement this check individually. The below is not called in these cases. - * - * @codeCoverageIgnore - */ - public function insert() { - if ( Application::getInstance()->getSettings()->get( 'smwgEnableUpdateJobs' ) ) { - parent::insert(); - } - } - - private function doUpdate() { - return $this->getTitle()->exists() ? $this->doParseContentForData() : $this->clearData(); - } - - private function clearData() { - Application::getInstance()->getStore()->deleteSubject( $this->getTitle() ); - return true; - } - - private function doParseContentForData() { - - $contentParser = Application::getInstance()->newContentParser( $this->getTitle() ); - $contentParser->forceToUseParser(); - $contentParser->parse(); - - if ( !( $contentParser->getOutput() instanceof ParserOutput ) ) { - $this->setLastError( $contentParser->getErrors() ); - return false; - } - - return $this->updateStore( $contentParser->getOutput() ); - } - - private function updateStore( ParserOutput $parserOutput ) { - Profiler::In( __METHOD__ . '-update' ); - - $cache = Application::getInstance()->getCache(); - $cache->setKey( FactboxCache::newCacheId( $this->getTitle()->getArticleID() ) )->delete(); - - // TODO - // Rebuild the factbox - - $parserData = Application::getInstance()->newParserData( - $this->getTitle(), - $parserOutput - ); - - $parserData->disableBackgroundUpdateJobs()->updateStore(); - - Profiler::Out( __METHOD__ . '-update' ); - return true; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/LazyDBConnectionProvider.php b/SemanticMediaWiki/includes/src/MediaWiki/LazyDBConnectionProvider.php deleted file mode 100644 index a27ad514..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/LazyDBConnectionProvider.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use SMW\DBConnectionProvider; - -use DatabaseBase; -use RuntimeException; - -/** - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class LazyDBConnectionProvider implements DBConnectionProvider { - - /** @var DatabaseBase|null */ - protected $connection = null; - - /** @var int|null */ - protected $connectionId = null; - - /** @var string|array */ - protected $groups; - - /** @var string|boolean $wiki */ - protected $wiki; - - /** - * @since 1.9 - * - * @param int $connectionId - * @param string|array $groups - * @param string|boolean $wiki - */ - public function __construct( $connectionId, $groups = array(), $wiki = false ) { - $this->connectionId = $connectionId; - $this->groups = $groups; - $this->wiki = $wiki; - } - - /** - * @see DBConnectionProvider::getConnection - * - * @since 1.9 - * - * @return DatabaseBase - * @throws RuntimeException - */ - public function getConnection() { - - if ( $this->connection === null ) { - $this->connection = wfGetLB( $this->wiki )->getConnection( $this->connectionId, $this->groups, $this->wiki ); - } - - if ( $this->isConnection( $this->connection ) ) { - return $this->connection; - } - - throw new RuntimeException( 'Expected a DatabaseBase instance' ); - } - - /** - * @see DBConnectionProvider::releaseConnection - * - * @since 1.9 - */ - public function releaseConnection() { - if ( $this->wiki !== false && $this->connection !== null ) { - wfGetLB( $this->wiki )->reuseConnection( $this->connection ); - } - } - - protected function isConnection( $connection ) { - return $connection instanceof DatabaseBase; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/MagicWordFinder.php b/SemanticMediaWiki/includes/src/MediaWiki/MagicWordFinder.php deleted file mode 100644 index 58399c73..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/MagicWordFinder.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use MagicWord; -use ParserOutput; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class MagicWordFinder { - - protected $parserOutput = null; - - /** - * @since 2.0 - * - * @param ParserOutput|null $parserOutput - */ - public function __construct( ParserOutput $parserOutput = null ) { - $this->parserOutput = $parserOutput; - } - - /** - * @since 2.0 - * - * @param ParserOutput $parserOutput - * - * @return self - */ - public function setOutput( ParserOutput $parserOutput ) { - $this->parserOutput = $parserOutput; - return $this; - } - - /** - * Remove relevant SMW magic words from the given text and return - * an array of the names of all discovered magic words. - * - * @since 2.0 - * - * @param $magicWord - * @param &$text - * - * @return array - */ - public function matchAndRemove( $magicWord, &$text ) { - - $words = array(); - - $mw = MagicWord::get( $magicWord ); - - if ( $mw->matchAndRemove( $text ) ) { - $words[] = $magicWord; - } - - return $words; - } - - /** - * @since 2.0 - * - * @param array $words - */ - public function setMagicWords( array $words ) { - - if ( $this->hasExtensionData() ) { - return $this->parserOutput->setExtensionData( 'smwmagicwords', $words ); - } - - return $this->parserOutput->mSMWMagicWords = $words; - } - - /** - * @since 2.0 - * - * @return array|null - */ - public function getMagicWords() { - - if ( $this->hasExtensionData() ) { - return $this->parserOutput->getExtensionData( 'smwmagicwords' ); - } - - if ( isset( $this->parserOutput->mSMWMagicWords ) ) { - return $this->parserOutput->mSMWMagicWords; - } - - return null; - } - - /** - * FIXME Remove when MW 1.21 becomes mandatory - */ - protected function hasExtensionData() { - return method_exists( $this->parserOutput, 'getExtensionData' ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/PageCreator.php b/SemanticMediaWiki/includes/src/MediaWiki/PageCreator.php deleted file mode 100644 index 96600dd0..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/PageCreator.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use WikiPage; -use WikiFilePage; -use Title; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class PageCreator { - - /** - * @since 2.0 - * - * @param Title $title - * - * @return WikiPage - */ - public function createPage( Title $title ) { - return WikiPage::factory( $title ); - } - - /** - * @since 2.0 - * - * @param Title $title - * - * @return WikiFilePage - */ - public function createFilePage( Title $title ) { - return new WikiFilePage( $title ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/PageInfoProvider.php b/SemanticMediaWiki/includes/src/MediaWiki/PageInfoProvider.php deleted file mode 100644 index 8a0071db..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/PageInfoProvider.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use SMW\PageInfo; - -use WikiPage; -use Revision; -use User; - -/** - * Provide access to MediaWiki objects relevant for the predefined property - * annotation process - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class PageInfoProvider implements PageInfo { - - /** - * @var WikiPage - */ - private $wikiPage = null; - - /** - * @var Revision - */ - private $revision = null; - - /** - * @var User - */ - private $user = null; - - /** - * @since 1.9 - * - * @param WikiPage $wikiPage - * @param Revision|null $revision - * @param User|null $user - */ - public function __construct( WikiPage $wikiPage, Revision $revision = null, User $user = null ) { - $this->wikiPage = $wikiPage; - $this->revision = $revision; - $this->user = $user; - } - - /** - * @since 1.9 - * - * @return integer - */ - public function getModificationDate() { - return $this->wikiPage->getTimestamp(); - } - - /** - * @note getFirstRevision() is expensive as it initiates a read on the - * revision table which is not cached - * - * @since 1.9 - * - * @return integer - */ - public function getCreationDate() { - return $this->wikiPage->getTitle()->getFirstRevision()->getTimestamp(); - } - - /** - * @note Using isNewPage() is expensive due to access to the database - * - * @since 1.9 - * - * @return boolean - */ - public function isNewPage() { - - if ( $this->isFilePage() ) { - return isset( $this->wikiPage->smwFileReUploadStatus ) ? !$this->wikiPage->smwFileReUploadStatus : false; - } - - if ( $this->revision ) { - return $this->revision->getParentId() === null; - } - - return $this->wikiPage->getRevision()->getParentId() === null; - } - - /** - * @since 1.9 - * - * @return Title - */ - public function getLastEditor() { - return $this->user ? $this->user->getUserPage() : null; - } - - /** - * @since 1.9.1 - * - * @return boolean - */ - public function isFilePage() { - return $this->wikiPage instanceof \WikiFilePage; - } - - /** - * @since 1.9.1 - * - * @return string|null - */ - public function getMediaType() { - return $this->isFilePage() ? $this->wikiPage->getFile()->getMediaType() : null; - } - - /** - * @since 1.9.1 - * - * @return string|null - */ - public function getMimeType() { - return $this->isFilePage() ? $this->wikiPage->getFile()->getMimeType() : null; - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/RedirectTargetFinder.php b/SemanticMediaWiki/includes/src/MediaWiki/RedirectTargetFinder.php deleted file mode 100644 index 337674b2..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/RedirectTargetFinder.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use ContentHandler; -use Title; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class RedirectTargetFinder { - - /** - * @var Title|null - */ - protected $target = null; - - /** - * @since 2.0 - * - * @param string $text - * - * @return Title|null - */ - public function findTarget( $text ) { - $this->target = $this->findFromText( $text ); - return $this; - } - - /** - * @since 2.0 - * - * @return Title|null - */ - public function getTarget() { - return $this->target; - } - - /** - * @since 2.0 - * - * @return boolean - */ - public function hasTarget() { - return $this->target instanceOf Title; - } - - private function findFromText( $text ) { - - if ( $this->hasContentHandler() ) { - return ContentHandler::makeContent( $text, null, CONTENT_MODEL_WIKITEXT )->getRedirectTarget(); - } - - return Title::newFromRedirect( $text ); - } - - protected function hasContentHandler() { - return defined( 'CONTENT_MODEL_WIKITEXT' ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/TitleCreator.php b/SemanticMediaWiki/includes/src/MediaWiki/TitleCreator.php deleted file mode 100644 index 6d32772b..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/TitleCreator.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use Title; -use RuntimeException; - -/** - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class TitleCreator { - - /** - * @var PageCreator - */ - private $pageCreator = null; - - /** - * @var Title - */ - private $title = null; - - /** - * @since 2.0 - * - * @param PageCreator|null $pageCreator - */ - public function __construct( PageCreator $pageCreator = null ) { - $this->pageCreator = $pageCreator; - } - - /** - * @since 2.0 - * - * @param string $text - * - * @return TitleCreator - */ - public function createFromText( $text ) { - $this->title = Title::newFromText( $text ); - return $this; - } - - /** - * @since 2.0 - * - * @return Title - */ - public function getTitle() { - return $this->title; - } - - /** - * @since 2.0 - * - * @return TitleCreator - * @throws RuntimeException - */ - public function findRedirect() { - - if ( $this->pageCreator === null ) { - throw new RuntimeException( "Expected a PageCreator instance" ); - } - - $this->title = $this->resolveRedirectTargetRecursively( $this->title ); - - return $this; - } - - protected function isValidRedirectTarget( $title ) { - return $title instanceof Title && $title->isValidRedirectTarget(); - } - - protected function isRedirect( $title ) { - return $title instanceOf Title && $title->isRedirect(); - } - - private function resolveRedirectTargetRecursively( $title ) { - - if ( $this->isRedirect( $title ) ) { - $title = $this->resolveRedirectTargetRecursively( - $this->pageCreator->createPage( $title )->getRedirectTarget() - ); - } - - if ( $this->isValidRedirectTarget( $title ) ) { - return $title; - } - - throw new RuntimeException( "Redirect target can not be resolved" ); - } - -} diff --git a/SemanticMediaWiki/includes/src/MediaWiki/TitleLookup.php b/SemanticMediaWiki/includes/src/MediaWiki/TitleLookup.php deleted file mode 100644 index 8ce479ff..00000000 --- a/SemanticMediaWiki/includes/src/MediaWiki/TitleLookup.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php - -namespace SMW\MediaWiki; - -use Title; -use UnexpectedValueException; - -/** - * A convenience class to encapsulate MW related database interaction - * - * @note This is an internal class and should not be used outside of smw-core - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9.2 - * - * @author mwjames - */ -class TitleLookup { - - /** @var Database */ - protected $database = null; - - protected $namespace = null; - - /** - * @since 1.9.2 - * - * @param Database $database - */ - public function __construct( Database $database ) { - $this->database = $database; - } - - /** - * @since 1.9.2 - * - * @param int $namespace - * - * @return TitleLookup - */ - public function byNamespace( $namespace ) { - $this->namespace = $namespace; - return $this; - } - - /** - * @since 1.9.2 - * - * @return Title[] - * @throws UnexpectedValueException - */ - public function selectAll() { - - if ( $this->namespace === null ) { - throw new UnexpectedValueException( 'Unrestricted selection without a namespace is not supported' ); - } - - if ( $this->namespace === NS_CATEGORY ) { - $tableName = 'category'; - $fields = array( 'cat_title' ); - $conditions = ''; - $options = array( 'USE INDEX' => 'cat_title' ); - } else { - $tableName = 'page'; - $fields = array( 'page_namespace', 'page_title' ); - $conditions = array( 'page_namespace' => $this->namespace ); - $options = array( 'USE INDEX' => 'PRIMARY' ); - } - - $res = $this->database->select( - $tableName, - $fields, - $conditions, - __METHOD__, - $options - ); - - return $this->makeTitlesFromSelection( $res ); - } - - /** - * @since 1.9.2 - * - * @param int $startId - * @param int $endId - * - * @return Title[] - * @throws UnexpectedValueException - */ - public function selectByIdRange( $startId = 0, $endId = 0 ) { - - if ( $this->namespace === null ) { - throw new UnexpectedValueException( 'Unrestricted selection without a namespace is not supported' ); - } - - if ( $this->namespace === NS_CATEGORY ) { - $tableName = 'category'; - $fields = array( 'cat_title', 'cat_id' ); - $conditions = array( "cat_id BETWEEN $startId AND $endId" ); - $options = array( 'ORDER BY' => 'cat_id ASC', 'USE INDEX' => 'cat_title' ); - } else { - $tableName = 'page'; - $fields = array( 'page_namespace', 'page_title', 'page_id' ); - $conditions = array( "page_id BETWEEN $startId AND $endId" ) + array( 'page_namespace' => $this->namespace ); - $options = array( 'ORDER BY' => 'page_id ASC', 'USE INDEX' => 'PRIMARY' ); - } - - $res = $this->database->select( - $tableName, - $fields, - $conditions, - __METHOD__, - $options - ); - - return $this->makeTitlesFromSelection( $res ); - } - - /** - * @since 1.9.2 - * - * @return int - */ - public function selectMaxId() { - - if ( $this->namespace === NS_CATEGORY ) { - $tableName = 'category'; - $var = 'MAX(cat_id)'; - } else { - $tableName = 'page'; - $var = 'MAX(page_id)'; - } - - return (int)$this->database->selectField( - $tableName, - $var, - false, - __METHOD__ - ); - } - - protected function makeTitlesFromSelection( $res ) { - - $pages = array(); - - if ( $res === false ) { - return $pages; - } - - foreach ( $res as $row ) { - $pages[] = $this->newTitleFromRow( $row ); - } - - return $pages; - } - - private function newTitleFromRow( $row ) { - - if ( $this->namespace === NS_CATEGORY ) { - $ns = NS_CATEGORY; - $title = $row->cat_title; - } else { - $ns = $row->page_namespace; - $title = $row->page_title; - } - - return Title::makeTitle( $ns, $title ); - } - -} diff --git a/SemanticMediaWiki/includes/src/PageInfo.php b/SemanticMediaWiki/includes/src/PageInfo.php deleted file mode 100644 index b81438e5..00000000 --- a/SemanticMediaWiki/includes/src/PageInfo.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -namespace SMW; - -/** - * Facade interface to specify access to page information - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface PageInfo { - - /** - * Returns a modification date - * - * @since 1.9 - * - * @return integer - */ - public function getModificationDate(); - - /** - * Returns a creation date - * - * @since 1.9 - * - * @return integer - */ - public function getCreationDate(); - - /** - * Whether the page object is new or not - * - * @since 1.9 - * - * @return boolean - */ - public function isNewPage(); - - /** - * Returns a user object for the last editor - * - * @since 1.9 - * - * @return Title - */ - public function getLastEditor(); - - /** - * @since 1.9.1 - * - * @return boolean - */ - public function isFilePage(); - - /** - * @see File::getMediaType - * - * @since 1.9.1 - * - * @return string|null - */ - public function getMediaType(); - - /** - * @see File::getMimeType - * - * @since 1.9.1 - * - * @return string|null - */ - public function getMimeType(); - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/src/PropertyAnnotator.php b/SemanticMediaWiki/includes/src/PropertyAnnotator.php deleted file mode 100644 index b7fe7391..00000000 --- a/SemanticMediaWiki/includes/src/PropertyAnnotator.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -namespace SMW; - -/** - * Interface specifing available methods to interact with the Decorator - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -interface PropertyAnnotator { - - /** - * Returns a SemanticData container - * - * @since 1.9 - * - * @return SemanticData - */ - public function getSemanticData(); - - /** - * Add annotations to the SemanticData container - * - * @since 1.9 - * - * @return PropertyAnnotator - */ - public function addAnnotation(); - -} diff --git a/SemanticMediaWiki/includes/src/PropertyTypeDiffFinder.php b/SemanticMediaWiki/includes/src/PropertyTypeDiffFinder.php deleted file mode 100644 index a1c062ae..00000000 --- a/SemanticMediaWiki/includes/src/PropertyTypeDiffFinder.php +++ /dev/null @@ -1,204 +0,0 @@ -<?php - -namespace SMW; - -/** - * Class that detects a change between a property and its store data - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - * @author Markus Krötzsch - */ -class PropertyTypeDiffFinder { - - /** - * @var Store - */ - protected $store; - - /** - * @var SemanticData - */ - protected $semanticData; - - /** - * @var boolean - */ - protected $hasDiff = false; - - /** - * @since 1.9 - * - * @param Store $store - * @param SemanticData $semanticData - */ - public function __construct( Store $store, SemanticData $semanticData ) { - $this->store = $store; - $this->semanticData = $semanticData; - } - - /** - * Returns a Title object - * - * @since 1.9 - * - * @return Title - */ - public function getTitle() { - return $this->semanticData->getSubject()->getTitle(); - } - - /** - * Returns if a data disparity exists - * - * @since 1.9 - * - * @return boolean - */ - public function hasDiff() { - return $this->hasDiff; - } - - /** - * Compare and compute the difference between invoked semantic data - * and the current store data - * - * @since 1.9 - * - * @return PropertyTypeComparator - */ - public function findDiff() { - Profiler::In( __METHOD__, true ); - - if ( $this->semanticData->getSubject()->getNamespace() === SMW_NS_PROPERTY ) { - $this->comparePropertyTypes(); - $this->compareConversionTypedFactors(); - } - - Profiler::Out( __METHOD__, true ); - return $this; - } - - /** - * Compare and find changes related to the property type - * - * @since 1.9 - */ - protected function comparePropertyTypes() { - Profiler::In( __METHOD__, true ); - - $update = false; - $ptype = new DIProperty( DIProperty::TYPE_HAS_TYPE ); - - // Get values from the store - $oldtype = $this->store->getPropertyValues( - $this->semanticData->getSubject(), - $ptype - ); - - // Get values currently hold by the semantic container - $newtype = $this->semanticData->getPropertyValues( $ptype ); - - // Compare old and new type - if ( !$this->isEqual( $oldtype, $newtype ) ) { - $update = true; - } else { - - // Compare values (in case of _PVAL (allowed values) for a - // property change must be processed again) - $smwgDeclarationProperties = Application::getInstance()->getSettings()->get( 'smwgDeclarationProperties' ); - - foreach ( $smwgDeclarationProperties as $prop ) { - $dataItem = new DIProperty( $prop ); - $oldValues = $this->store->getPropertyValues( - $this->semanticData->getSubject(), - $dataItem - ); - - $newValues = $this->semanticData->getPropertyValues( $dataItem ); - $update = $update || !$this->isEqual( $oldValues, $newValues ); - } - } - - $this->notifyUpdateDispatcher( $update ); - - Profiler::Out( __METHOD__, true ); - } - - /** - * Compare and find changes related to conversion factor - * - * @since 1.9 - */ - protected function compareConversionTypedFactors() { - Profiler::In( __METHOD__, true ); - - $pconversion = new DIProperty( DIProperty::TYPE_CONVERSION ); - - $newfactors = $this->semanticData->getPropertyValues( $pconversion ); - $oldfactors = $this->store->getPropertyValues( - $this->semanticData->getSubject(), - $pconversion - ); - - $this->notifyUpdateDispatcher( !$this->isEqual( $oldfactors, $newfactors ) ); - - Profiler::Out( __METHOD__, true ); - } - - /** - * @since 1.9 - * - * @param boolean $addJob - */ - protected function notifyUpdateDispatcher( $addJob = true ) { - if ( $addJob && !$this->hasDiff ) { - - Application::getInstance() - ->newJobFactory() - ->newUpdateDispatcherJob( $this->semanticData->getSubject()->getTitle() ) - ->run(); - - $this->hasDiff = true; - } - } - - /** - * Helper function that compares two arrays of data values to check whether - * they contain the same content. Returns true if the two arrays contain the - * same data values (irrespective of their order), false otherwise. - * - * @since 1.9 - * - * @param $oldDataValue - * @param $newDataValue - */ - protected function isEqual( $oldDataValue, $newDataValue ) { - - // The hashes of all values of both arrays are taken, then sorted - // and finally concatenated, thus creating one long hash out of each - // of the data value arrays. These are compared. - $values = array(); - foreach ( $oldDataValue as $v ) { - $values[] = $v->getHash(); - } - - sort( $values ); - $oldDataValueHash = implode( '___', $values ); - - $values = array(); - foreach ( $newDataValue as $v ) { - $values[] = $v->getHash(); - } - - sort( $values ); - $newDataValueHash = implode( '___', $values ); - - return ( $oldDataValueHash == $newDataValueHash ); - } - -} diff --git a/SemanticMediaWiki/includes/src/Reporter/MessageReporter.php b/SemanticMediaWiki/includes/src/Reporter/MessageReporter.php deleted file mode 100644 index 45cccb0d..00000000 --- a/SemanticMediaWiki/includes/src/Reporter/MessageReporter.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -namespace SMW\Reporter; - -/** - * Interface for objects that can report messages - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -interface MessageReporter { - - /** - * Report the provided message. - * - * @since 1.9 - * - * @param string $message - */ - public function reportMessage( $message ); - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/src/Reporter/NullMessageReporter.php b/SemanticMediaWiki/includes/src/Reporter/NullMessageReporter.php deleted file mode 100644 index 02e4bbfc..00000000 --- a/SemanticMediaWiki/includes/src/Reporter/NullMessageReporter.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -namespace SMW\Reporter; - -/** - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class NullMessageReporter implements MessageReporter { - - /** - * @param string $message - */ - public function reportMessage( $message ) {} - -} diff --git a/SemanticMediaWiki/includes/src/Reporter/ObservableMessageReporter.php b/SemanticMediaWiki/includes/src/Reporter/ObservableMessageReporter.php deleted file mode 100644 index f6c69152..00000000 --- a/SemanticMediaWiki/includes/src/Reporter/ObservableMessageReporter.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -namespace SMW\Reporter; - -/** - * Message reporter that reports messages by passing them along to all - * registered handlers. - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class ObservableMessageReporter implements MessageReporter { - - /** - * @since 1.9 - * - * @var MessageReporter[] - */ - protected $reporters = array(); - - /** - * @since 1.9 - * - * @var callable[] - */ - protected $callbacks = array(); - - /** - * @see MessageReporter::report - * - * @since 1.9 - * - * @param string $message - */ - public function reportMessage( $message ) { - foreach ( $this->reporters as $reporter ) { - $reporter->reportMessage( $message ); - } - - foreach ( $this->callbacks as $callback ) { - call_user_func( $callback, $message ); - } - } - - /** - * Register a new message reporter. - * - * @since 1.9 - * - * @param MessageReporter $reporter - */ - public function registerMessageReporter( MessageReporter $reporter ) { - $this->reporters[] = $reporter; - } - - /** - * Register a callback as message reporter. - * - * @since 1.9 - * - * @param callable $handler - */ - public function registerReporterCallback( $handler ) { - $this->callbacks[] = $handler; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/BadHttpDatabaseResponseException.php b/SemanticMediaWiki/includes/src/SPARQLStore/BadHttpDatabaseResponseException.php deleted file mode 100644 index 58c56189..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/BadHttpDatabaseResponseException.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -/** - * Class to escalate SPARQL query errors to the interface. We only do this for - * malformed queries, permission issues, etc. Connection problems are usually - * ignored so as to keep the wiki running even if the SPARQL backend is down. - * - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class BadHttpDatabaseResponseException extends \Exception { - - /// Error code: malformed query - const ERROR_MALFORMED = 1; - /// Error code: service refused to handle the request - const ERROR_REFUSED = 2; - /// Error code: the query required a graph that does not exist - const ERROR_GRAPH_NOEXISTS = 3; - /// Error code: some existing graph should not exist to run this query - const ERROR_GRAPH_EXISTS = 4; - /// Error code: unknown error - const ERROR_OTHER = 5; - /// Error code: required service not known - const ERROR_NOSERVICE = 6; - - /** - * SPARQL query that caused the problem. - * @var string - */ - public $queryText; - - /** - * Error code - * @var integer - */ - public $errorCode; - - /** - * Constructor that creates an error message based on the given data. - * - * @param $errorCode integer error code as defined in this class - * @param $queryText string with the original SPARQL query/update - * @param $endpoint string URL of the endpoint - * @param $httpCode mixed integer HTTP error code or some string to print there - */ - function __construct( $errorCode, $queryText, $endpoint, $httpCode = '<not given>' ) { - - switch ( $errorCode ) { - case self::ERROR_MALFORMED: - $errorName = 'Malformed query'; - break; - case self::ERROR_REFUSED: - $errorName = 'Query refused'; - break; - case self::ERROR_GRAPH_NOEXISTS: - $errorName = 'Graph not existing'; - break; - case self::ERROR_GRAPH_EXISTS: - $errorName = 'Graph already exists'; - break; - case self::ERROR_NOSERVICE: default: - $errorName = 'Required service has not been defined'; - break; - default: - $errorCode = self::ERROR_OTHER; - $errorName = 'Unkown error'; - } - - $message = "A SPARQL query error has occurred\n" . - "Query: $queryText\n" . - "Error: $errorName\n" . - "Endpoint: $endpoint\n" . - "HTTP response code: $httpCode\n"; - - parent::__construct( $message, $errorCode ); - $this->errorCode = $errorCode; - $this->queryText = $queryText; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/BadHttpResponseMapper.php b/SemanticMediaWiki/includes/src/SPARQLStore/BadHttpResponseMapper.php deleted file mode 100644 index 7317de47..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/BadHttpResponseMapper.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -use SMW\SPARQLStore\BadHttpDatabaseResponseException as SMWSparqlDatabaseError; -use SMW\HttpRequest; - -use Exception; - -/** - * Post-processing for a bad inbound responses - * - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author Markus Krötzsch - * @author mwjames - */ -class BadHttpResponseMapper { - - private $httpRequest = null; - - /** - * @since 2.0 - * - * @param HttpRequest $httpRequest - */ - public function __construct( HttpRequest $httpRequest ) { - $this->httpRequest = $httpRequest; - } - - /** - * Either throw a suitable exception or fall through if the error should be - * handled gracefully. It is attempted to throw exceptions for all errors that - * can generally be prevented by proper coding or configuration (e.g. query - * syntax errors), and to be silent on all errors that might be caused by - * network issues or temporary overloading of the server. In this case, calling - * methods rather return something that helps to make the best out of the situation. - * - * @since 2.0 - * - * @param HttpRequest $httpRequest - * @param $endpoint string URL of endpoint that was used - * @param $sparql string query that caused the problem - * - * @throws Exception - * @throws SparqlDatabaseException - */ - public function mapResponseToHttpRequest( $endpoint, $sparql ) { - - $error = $this->httpRequest->getLastErrorCode(); - - switch ( $error ) { - case 22: // equals CURLE_HTTP_RETURNED_ERROR but this constant is not defined in PHP - return $this->createResponseToHttpError( $this->httpRequest->getInfo( CURLINFO_HTTP_CODE ), $endpoint, $sparql ); - case 52: - case CURLE_GOT_NOTHING: - return; // happens when 4Store crashes, do not bother the wiki - case CURLE_COULDNT_CONNECT: - return; // fail gracefully if backend is down - } - - throw new Exception( "Failed to communicate with SPARQL store.\n Endpoint: " . $endpoint . "\n Curl error: '" . $this->httpRequest->getLastError() . "' ($error)" ); - } - - private function createResponseToHttpError( $httpCode, $endpoint, $sparql ) { - - /// TODO We are guessing the meaning of HTTP codes here -- the SPARQL 1.1 spec does not yet provide this information for updates (April 15 2011) - - if ( $httpCode == 400 ) { // malformed query - throw new SMWSparqlDatabaseError( SMWSparqlDatabaseError::ERROR_MALFORMED, $sparql, $endpoint, $httpCode ); - } elseif ( $httpCode == 500 ) { // query refused; maybe fail gracefully here (depending on how stores use this) - throw new SMWSparqlDatabaseError( SMWSparqlDatabaseError::ERROR_REFUSED, $sparql, $endpoint, $httpCode ); - } elseif ( $httpCode == 404 ) { - return; // endpoint not found, maybe down; fail gracefully - } - - throw new SMWSparqlDatabaseError( SMWSparqlDatabaseError::ERROR_OTHER, $sparql, $endpoint, $httpCode ); - } - -} - diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/FourstoreHttpDatabaseConnector.php b/SemanticMediaWiki/includes/src/SPARQLStore/FourstoreHttpDatabaseConnector.php deleted file mode 100644 index f0c2ec24..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/FourstoreHttpDatabaseConnector.php +++ /dev/null @@ -1,167 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -use SMW\SPARQLStore\QueryEngine\RawResultParser; -use SMW\SPARQLStore\QueryEngine\FederateResultList; - -use SMWSparqlResultParser as SparqlResultParser; -use SMWTurtleSerializer as TurtleSerializer; - -/** - * Specific modifications of the SPARQL database implementation for 4Store. - * - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class FourstoreHttpDatabaseConnector extends GenericHttpDatabaseConnector { - - /** - * Execute a SPARQL query and return an FederateResultList object - * that contains the results. Compared to GenericHttpDatabaseConnector::doQuery(), - * this also supports the parameter "restricted=1" which 4Store provides - * to enforce strict resource bounds on query answering. The method also - * checks if these bounds have been met, and records this in the query - * result. - * - * @note The restricted option in 4Store mainly enforces the given soft - * limit more strictly. To disable/configure it, simply change the soft - * limit settings of your 4Store server. - * - * @param $sparql string with the complete SPARQL query (SELECT or ASK) - * @return FederateResultList - */ - public function doQuery( $sparql ) { - - if ( $this->m_queryEndpoint === '' ) { - throw new BadHttpDatabaseResponseException( BadHttpDatabaseResponseException::ERROR_NOSERVICE, $sparql, 'not specified' ); - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_queryEndpoint ); - $this->httpRequest->setOption( CURLOPT_HTTPHEADER, array('Accept: application/sparql-results+xml,application/xml;q=0.8' )); - $this->httpRequest->setOption( CURLOPT_POST, true ); - - $parameterString = "query=" . urlencode( $sparql ) . "&restricted=1" . - ( ( $this->m_defaultGraph !== '' )? '&default-graph-uri=' . urlencode( $this->m_defaultGraph ) : '' ); - - $this->httpRequest->setOption( CURLOPT_POSTFIELDS, $parameterString ); - - $xmlResult = $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - $rawResultParser = new RawResultParser(); - $result = $rawResultParser->parse( $xmlResult ); - } else { - $this->mapHttpRequestError( $this->m_queryEndpoint, $sparql ); - $result = new FederateResultList( array(), array(), array(), FederateResultList::ERROR_UNREACHABLE ); - } - - foreach ( $result->getComments() as $comment ) { - if ( strpos( $comment, 'warning: hit complexity limit' ) === 0 || - strpos( $comment, 'some results have been dropped' ) === 0 ) { - $result->setErrorCode( FederateResultList::ERROR_INCOMPLETE ); - } //else debug_zval_dump($comment); - } - - return $result; - } - - /** - * Complex SPARQL Update delete operations are not supported in 4Store - * as of v1.1.3, hence this implementation uses a less efficient method - * for accomplishing this. - * - * @param $propertyName string Turtle name of marking property - * @param $objectName string Turtle name of marking object/value - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * @return boolean stating whether the operations succeeded - */ - public function deleteContentByValue( $propertyName, $objectName, $extraNamespaces = array() ) { - $affectedObjects = $this->select( '*', "?s $propertyName $objectName", array(), $extraNamespaces ); - $success = ( $affectedObjects->getErrorCode() == FederateResultList::ERROR_NOERROR ); - - foreach ( $affectedObjects as $expElements ) { - if ( count( $expElements ) > 0 ) { - $turtleName = TurtleSerializer::getTurtleNameForExpElement( reset( $expElements ) ); - $success = $this->delete( "$turtleName ?p ?o", "$turtleName ?p ?o", $extraNamespaces ) && $success; - } - } - - return $success; - } - - /** - * Execute a HTTP-based SPARQL POST request according to - * http://www.w3.org/2009/sparql/docs/http-rdf-update/. - * The method throws exceptions based on - * GenericHttpDatabaseConnector::mapHttpRequestError(). If errors occur and this - * method does not throw anything, then an empty result with an error - * code is returned. - * - * This method is specific to 4Store since it uses POST parameters that - * are not given in the specification. - * - * @param $payload string Turtle serialization of data to send - * - * @return boolean - */ - public function doHttpPost( $payload ) { - - if ( $this->m_dataEndpoint === '' ) { - throw new BadHttpDatabaseResponseException( BadHttpDatabaseResponseException::ERROR_NOSERVICE, "SPARQL POST with data: $payload", 'not specified' ); - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_dataEndpoint ); - $this->httpRequest->setOption( CURLOPT_POST, true ); - - $parameterString = "data=" . urlencode( $payload ) . '&graph=' . - ( ( $this->m_defaultGraph !== '' )? urlencode( $this->m_defaultGraph ) : 'default' ) . - '&mime-type=application/x-turtle'; - - $this->httpRequest->setOption( CURLOPT_POSTFIELDS, $parameterString ); - $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - return true; - } - - $this->mapHttpRequestError( $this->m_dataEndpoint, $payload ); - return false; - } - - /** - * @see GenericHttpDatabaseConnector::doUpdate - * - * @note 4store 1.1.4 breaks on update if charset is set in the Content-Type header - * - * @since 2.0 - */ - public function doUpdate( $sparql ) { - - if ( $this->m_updateEndpoint === '' ) { - throw new BadHttpDatabaseResponseException( BadHttpDatabaseResponseException::ERROR_NOSERVICE, $sparql, 'not specified' ); - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_updateEndpoint ); - $this->httpRequest->setOption( CURLOPT_POST, true ); - - $parameterString = "update=" . urlencode( $sparql ); - - $this->httpRequest->setOption( CURLOPT_POSTFIELDS, $parameterString ); - $this->httpRequest->setOption( CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded' ) ); - - $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - return true; - } - - $this->mapHttpRequestError( $this->m_updateEndpoint, $sparql ); - return false; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/FusekiHttpDatabaseConnector.php b/SemanticMediaWiki/includes/src/SPARQLStore/FusekiHttpDatabaseConnector.php deleted file mode 100644 index 91f036b9..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/FusekiHttpDatabaseConnector.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -use SMW\SPARQLStore\BadHttpDatabaseResponseException; -use SMW\SPARQLStore\QueryEngine\RawResultParser; -use SMW\SPARQLStore\QueryEngine\FederateResultList; - -/** - * @see https://jena.apache.org/documentation/serving_data/index.html - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class FusekiHttpDatabaseConnector extends GenericHttpDatabaseConnector { - - /** - * @see GenericHttpDatabaseConnector::doQuery - */ - public function doQuery( $sparql ) { - - if ( $this->m_queryEndpoint === '' ) { - throw new BadHttpDatabaseResponseException( BadHttpDatabaseResponseException::ERROR_NOSERVICE, $sparql, 'not specified' ); - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_queryEndpoint ); - $this->httpRequest->setOption( CURLOPT_HTTPHEADER, array('Accept: application/sparql-results+xml,application/xml;q=0.8' ) ); - $this->httpRequest->setOption( CURLOPT_POST, true ); - - $parameterString = "query=" . urlencode( $sparql ) . - ( ( $this->m_defaultGraph !== '' )? '&default-graph-uri=' . urlencode( $this->m_defaultGraph ) : '' ) . '&output=xml'; - - $this->httpRequest->setOption( CURLOPT_POSTFIELDS, $parameterString ); - $this->httpRequest->setOption( CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded;charset=UTF-8') ); - - $xmlResult = $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - $rawResultParser = new RawResultParser(); - return $rawResultParser->parse( $xmlResult ); - } - - $this->mapHttpRequestError( $this->m_queryEndpoint, $sparql ); - - return new FederateResultList( - array(), - array(), - array(), - FederateResultList::ERROR_UNREACHABLE - ); - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/GenericHttpDatabaseConnector.php b/SemanticMediaWiki/includes/src/SPARQLStore/GenericHttpDatabaseConnector.php deleted file mode 100644 index d2a65c36..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/GenericHttpDatabaseConnector.php +++ /dev/null @@ -1,607 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -use SMW\SPARQLStore\QueryEngine\RawResultParser; -use SMW\SPARQLStore\QueryEngine\FederateResultList; - -use SMW\CurlRequest; -use SMW\HttpRequest; - -use SMWExporter as Exporter; - -/** - * Basic database connector for exchanging data via SPARQL. - * - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class GenericHttpDatabaseConnector { - - /// Flag denoting endpoints being capable of querying - const EP_TYPE_QUERY = 1; - /// Flag denoting endpoints being capable of updating - const EP_TYPE_UPDATE = 2; - /// Flag denoting endpoints being capable of SPARQL HTTP graph management - const EP_TYPE_DATA = 4; - - /** - * The URL of the endpoint for executing read queries. - * - * @var string - */ - protected $m_queryEndpoint; - - /** - * The URL of the endpoint for executing update queries, or empty if - * update is not allowed/supported. - * - * @var string - */ - protected $m_updateEndpoint; - - /** - * The URL of the endpoint for using the SPARQL Graph Store HTTP - * Protocol with, or empty if this method is not allowed/supported. - * - * @var string - */ - protected $m_dataEndpoint; - - /** - * The URI of the default graph that is used to store data. - * Can be the empty string to omit this information in all requests - * (not supported by all stores). - * - * @var string - */ - protected $m_defaultGraph; - - /** - * @note Handles the curl handle and is reused throughout the instance to - * safe some initialization effort - * - * @var HttpRequest - */ - protected $httpRequest; - - /** - * @var BadHttpResponseMapper - */ - private $badHttpResponseMapper; - - /** - * It is suggested to use SparqlDBConnectionProvider to create an - * instance. - * - * @param $graph string of URI of the default graph to store data to; - * can be the empty string to omit this information in all requests - * (not supported by all stores) - * @param $queryEndpoint string of URL of query service (reading) - * @param $updateEndpoint string of URL of update service (writing) - * @param $dataEndpoint string of URL of POST service (writing, optional) - */ - public function __construct( $graph, $queryEndpoint, $updateEndpoint = '', $dataEndpoint = '' ) { - $this->m_defaultGraph = $graph; - $this->m_queryEndpoint = $queryEndpoint; - $this->m_updateEndpoint = $updateEndpoint; - $this->m_dataEndpoint = $dataEndpoint; - - $this->httpRequest = new CurlRequest( curl_init() ); - - $this->httpRequest->setOption( CURLOPT_FORBID_REUSE, false ); - $this->httpRequest->setOption( CURLOPT_FRESH_CONNECT, false ); - $this->httpRequest->setOption( CURLOPT_RETURNTRANSFER, true ); // put result into variable - $this->httpRequest->setOption( CURLOPT_FAILONERROR, true ); - - $this->setConnectionTimeoutInSeconds( 10 ); - } - - /** - * Get the URI of the default graph that this database connector is - * using, or the empty string if none is used (no graph related - * statements in queries/updates). - * - * @return string graph UIR or empty - */ - public function getDefaultGraph() { - return $this->m_defaultGraph; - } - - /** - * Check if the database can be contacted. - * - * @todo SPARQL endpoints sometimes return errors if no (valid) query - * is posted. The current implementation tries to catch this, but this - * might not be entirely correct. Especially, the SPARQL 1.1 HTTP error - * codes for Update are not defined yet (April 15 2011). - * - * @param $pingQueryEndpoint boolean true if the query endpoint should be - * pinged, false if the update endpoint should be pinged - * - * @return boolean to indicate success - */ - public function ping( $endpointType = self::EP_TYPE_QUERY ){ - if ( $endpointType == self::EP_TYPE_QUERY ) { - $this->httpRequest->setOption( CURLOPT_URL, $this->m_queryEndpoint ); - $this->httpRequest->setOption( CURLOPT_NOBODY, true ); - $this->httpRequest->setOption( CURLOPT_POST, true ); - } elseif ( $endpointType == self::EP_TYPE_UPDATE ) { - - if ( $this->m_updateEndpoint === '' ) { - return false; - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_updateEndpoint ); - $this->httpRequest->setOption( CURLOPT_NOBODY, false ); // 4Store gives 404 instead of 500 with CURLOPT_NOBODY - - } else { // ( $endpointType == self::EP_TYPE_DATA ) - - if ( $this->m_dataEndpoint === '' ) { - return false; - } - - // try an empty POST - return $this->doHttpPost( '' ); - } - - $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - return true; - } - - // valid HTTP responses from a complaining SPARQL endpoint that is alive and kicking - $httpCode = $this->httpRequest->getInfo( CURLINFO_HTTP_CODE ); - return ( ( $httpCode == 500 ) || ( $httpCode == 400 ) ); - } - - /** - * SELECT wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $vars mixed array or string, field name(s) to be retrieved, can be '*' - * @param $where string WHERE part of the query, without surrounding { } - * @param $options array (associative) of options, e.g. array( 'LIMIT' => '10' ) - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return SMWFederateResultList - */ - public function select( $vars, $where, $options = array(), $extraNamespaces = array() ) { - return $this->doQuery( $this->getSparqlForSelect( $vars, $where, $options, $extraNamespaces ) ); - } - - /** - * Build the SPARQL query that is used by GenericHttpDatabaseConnector::select(). - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $where string WHERE part of the query, without surrounding { } - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return string SPARQL query - */ - public function getSparqlForSelect( $vars, $where, $options = array(), $extraNamespaces = array() ) { - - $sparql = self::getPrefixString( $extraNamespaces ) . 'SELECT '; - - if ( array_key_exists( 'DISTINCT', $options ) ) { - $sparql .= 'DISTINCT '; - } - - if ( is_array( $vars ) ) { - $sparql .= implode( ',', $vars ); - } else { - $sparql .= $vars; - } - - $sparql .= " WHERE {\n" . $where . "\n}"; - - if ( array_key_exists( 'ORDER BY', $options ) ) { - $sparql .= "\nORDER BY " . $options['ORDER BY']; - } - - if ( array_key_exists( 'OFFSET', $options ) ) { - $sparql .= "\nOFFSET " . $options['OFFSET']; - } - - if ( array_key_exists( 'LIMIT', $options ) ) { - $sparql .= "\nLIMIT " . $options['LIMIT']; - } - - return $sparql; - } - - /** - * ASK wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $where string WHERE part of the query, without surrounding { } - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return SMWFederateResultList - */ - public function ask( $where, $extraNamespaces = array() ) { - return $this->doQuery( $this->getSparqlForAsk( $where, $extraNamespaces ) ); - } - - /** - * Build the SPARQL query that is used by GenericHttpDatabaseConnector::ask(). - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $where string WHERE part of the query, without surrounding { } - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return string SPARQL query - */ - public function getSparqlForAsk( $where, $extraNamespaces = array() ) { - return self::getPrefixString( $extraNamespaces ) . "ASK {\n" . $where . "\n}"; - } - - /** - * SELECT wrapper for counting results. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $variable string variable name or '*' - * @param $where string WHERE part of the query, without surrounding { } - * @param $options array (associative) of options, e.g. array('LIMIT' => '10') - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return SMWFederateResultList - */ - public function selectCount( $variable, $where, $options = array(), $extraNamespaces = array() ) { - - $sparql = self::getPrefixString( $extraNamespaces ) . 'SELECT (COUNT('; - - if ( array_key_exists( 'DISTINCT', $options ) ) { - $sparql .= 'DISTINCT '; - } - - $sparql .= $variable . ") AS ?count) WHERE {\n" . $where . "\n}"; - - if ( array_key_exists( 'OFFSET', $options ) ) { - $sparql .= "\nOFFSET " . $options['OFFSET']; - } - - if ( array_key_exists( 'LIMIT', $options ) ) { - $sparql .= "\nLIMIT " . $options['LIMIT']; - } - - return $this->doQuery( $sparql ); - } - - /** - * DELETE wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $deletePattern string CONSTRUCT pattern of tripples to delete - * @param $where string condition for data to delete - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return boolean stating whether the operations succeeded - */ - public function delete( $deletePattern, $where, $extraNamespaces = array() ) { - - $sparql = self::getPrefixString( $extraNamespaces ) . - ( ( $this->m_defaultGraph !== '' )? "WITH <{$this->m_defaultGraph}> " : '' ) . - "DELETE { $deletePattern } WHERE { $where }"; - - return $this->doUpdate( $sparql ); - } - - /** - * Convenience method for deleting all triples that have a subject that - * occurs in a triple with the given property and object. This is used - * in SMW to delete subobjects with all their data. Some RDF stores fail - * on complex delete queries, hence a wrapper function is provided to - * allow more pedestrian implementations. - * - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $propertyName string Turtle name of marking property - * @param $objectName string Turtle name of marking object/value - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return boolean stating whether the operations succeeded - */ - public function deleteContentByValue( $propertyName, $objectName, $extraNamespaces = array() ) { - return $this->delete( "?s ?p ?o", "?s $propertyName $objectName . ?s ?p ?o", $extraNamespaces ); - } - - /** - * Convenience method for deleting all triples of the entire store - * - * @return boolean - */ - public function deleteAll() { - return $this->delete( "?s ?p ?o", "?s ?p ?o" ); - } - - /** - * INSERT DELETE wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $insertPattern string CONSTRUCT pattern of tripples to insert - * @param $deletePattern string CONSTRUCT pattern of tripples to delete - * @param $where string condition for data to delete - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return boolean stating whether the operations succeeded - */ - public function insertDelete( $insertPattern, $deletePattern, $where, $extraNamespaces = array() ) { - - $sparql = self::getPrefixString( $extraNamespaces ) . - ( ( $this->m_defaultGraph !== '' )? "WITH <{$this->m_defaultGraph}> " : '' ) . - "DELETE { $deletePattern } INSERT { $insertPattern } WHERE { $where }"; - - return $this->doUpdate( $sparql ); - } - - /** - * INSERT DATA wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $triples string of triples to insert - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return boolean stating whether the operations succeeded - */ - public function insertData( $triples, $extraNamespaces = array() ) { - - if ( $this->m_dataEndpoint !== '' ) { - $turtle = self::getPrefixString( $extraNamespaces, false ) . $triples; - return $this->doHttpPost( $turtle ); - } - - $sparql = self::getPrefixString( $extraNamespaces, true ) . - "INSERT DATA " . - ( ( $this->m_defaultGraph !== '' )? " { GRAPH <{$this->m_defaultGraph}> " : '' ) . - "{ $triples } " . - ( ( $this->m_defaultGraph !== '' )? " } " : '' ) ; - - return $this->doUpdate( $sparql ); - } - - /** - * DELETE DATA wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $triples string of triples to delete - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * - * @return boolean stating whether the operations succeeded - */ - public function deleteData( $triples, $extraNamespaces = array() ) { - $sparql = self::getPrefixString( $extraNamespaces ) . - "DELETE DATA { " . - ( ( $this->m_defaultGraph !== '' )? "GRAPH <{$this->m_defaultGraph}> " : '' ) . - "{ $triples } }"; - return $this->doUpdate( $sparql ); - } - - - /** - * Execute a SPARQL query and return an SMWFederateResultList object - * that contains the results. The method throws exceptions based on - * GenericHttpDatabaseConnector::mapHttpRequestError(). If errors occur and this - * method does not throw anything, then an empty result with an error - * code is returned. - * - * @note This function sets the graph that is to be used as part of the - * request. Queries should not include additional graph information. - * - * @param $sparql string with the complete SPARQL query (SELECT or ASK) - * - * @return SMWFederateResultList - */ - public function doQuery( $sparql ) { - - if ( $this->m_queryEndpoint === '' ) { - throw new BadHttpDatabaseResponseException( BadHttpDatabaseResponseException::ERROR_NOSERVICE, $sparql, 'not specified' ); - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_queryEndpoint ); - $this->httpRequest->setOption( CURLOPT_HTTPHEADER, array('Accept: application/sparql-results+xml,application/xml;q=0.8' ) ); - $this->httpRequest->setOption( CURLOPT_POST, true ); - - $parameterString = "query=" . urlencode( $sparql ) . - ( ( $this->m_defaultGraph !== '' )? '&default-graph-uri=' . urlencode( $this->m_defaultGraph ) : '' ); - - $this->httpRequest->setOption( CURLOPT_POSTFIELDS, $parameterString ); - $this->httpRequest->setOption( CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded;charset=UTF-8') ); - - $xmlResult = $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - $rawResultParser = new RawResultParser(); - return $rawResultParser->parse( $xmlResult ); - } - - $this->mapHttpRequestError( $this->m_queryEndpoint, $sparql ); - - return new FederateResultList( - array(), - array(), - array(), - FederateResultList::ERROR_UNREACHABLE - ); - } - - /** - * Execute a SPARQL update and return a boolean to indicate if the - * operations was successful. The method throws exceptions based on - * GenericHttpDatabaseConnector::mapHttpRequestError(). If errors occur and this - * method does not throw anything, then false is returned. - * - * @note When this is written, it is not clear if the update protocol - * supports a default-graph-uri parameter. Hence the target graph for - * all updates is generally encoded in the query string and not fixed - * when sending the query. Direct callers to this function must include - * the graph information in the queries that they build. - * - * @param $sparql string with the complete SPARQL update query (INSERT or DELETE) - * - * @return boolean - */ - public function doUpdate( $sparql ) { - - if ( $this->m_updateEndpoint === '' ) { - throw new BadHttpDatabaseResponseException( BadHttpDatabaseResponseException::ERROR_NOSERVICE, $sparql, 'not specified' ); - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_updateEndpoint ); - $this->httpRequest->setOption( CURLOPT_POST, true ); - - $parameterString = "update=" . urlencode( $sparql ); - - $this->httpRequest->setOption( CURLOPT_POSTFIELDS, $parameterString ); - $this->httpRequest->setOption( CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' ) ); - - $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - return true; - } - - $this->mapHttpRequestError( $this->m_updateEndpoint, $sparql ); - return false; - } - - /** - * Execute a HTTP-based SPARQL POST request according to - * http://www.w3.org/2009/sparql/docs/http-rdf-update/. - * The method throws exceptions based on - * GenericHttpDatabaseConnector::mapHttpRequestError(). If errors occur and this - * method does not throw anything, then an empty result with an error - * code is returned. - * - * @note This protocol is not part of the SPARQL standard and may not - * be supported by all stores. To avoid using it, simply do not provide - * a data endpoint URL when configuring the SPARQL database. If used, - * the protocol might lead to a better performance since there is less - * parsing required to fetch the data from the request. - * @note Some stores (e.g. 4Store) support another mode of posting data - * that may be implemented in a special database handler. - * - * @param $payload string Turtle serialization of data to send - * - * @return boolean - */ - public function doHttpPost( $payload ) { - - if ( $this->m_dataEndpoint === '' ) { - throw new BadHttpDatabaseResponseException( BadHttpDatabaseResponseException::ERROR_NOSERVICE, "SPARQL POST with data: $payload", 'not specified' ); - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_dataEndpoint . - ( ( $this->m_defaultGraph !== '' )? '?graph=' . urlencode( $this->m_defaultGraph ) : '?default' ) ); - $this->httpRequest->setOption( CURLOPT_POST, true ); - - // POST as file (fails in 4Store) - $payloadFile = tmpfile(); - fwrite( $payloadFile, $payload ); - fseek( $payloadFile, 0 ); - - $this->httpRequest->setOption( CURLOPT_INFILE, $payloadFile ); - $this->httpRequest->setOption( CURLOPT_INFILESIZE, strlen( $payload ) ); - $this->httpRequest->setOption( CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-turtle' ) ); - - $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - return true; - } - - // TODO The error reporting based on SPARQL (Update) is not adequate for the HTTP POST protocol - $this->mapHttpRequestError( $this->m_dataEndpoint, $payload ); - return false; - } - - /** - * Create the standard PREFIX declarations for SPARQL or Turtle, - * possibly with additional namespaces involved. - * - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * @param $forSparql boolean true to use SPARQL prefix syntax, false to use Turtle prefix syntax - * - * @return string - */ - public static function getPrefixString( $extraNamespaces = array(), $forSparql = true ) { - $prefixString = ''; - $prefixIntro = $forSparql ? 'PREFIX ' : '@prefix '; - $prefixOutro = $forSparql ? "\n" : " .\n"; - - foreach ( array( 'wiki', 'rdf', 'rdfs', 'owl', 'swivt', 'property', 'xsd' ) as $shortname ) { - $prefixString .= "{$prefixIntro}{$shortname}: <" . Exporter::getNamespaceUri( $shortname ) . ">$prefixOutro"; - unset( $extraNamespaces[$shortname] ); // avoid double declaration - } - - foreach ( $extraNamespaces as $shortname => $uri ) { - $prefixString .= "{$prefixIntro}{$shortname}: <$uri>$prefixOutro"; - } - - return $prefixString; - } - - /** - * @param $endpoint string URL of endpoint that was used - * @param $sparql string query that caused the problem - */ - protected function mapHttpRequestError( $endpoint, $sparql ) { - - if ( $this->badHttpResponseMapper === null ) { - $this->badHttpResponseMapper = new BadHttpResponseMapper( $this->httpRequest ); - } - - $this->badHttpResponseMapper->mapResponseToHttpRequest( $endpoint, $sparql ); - } - - /** - * @since 2.0 - * - * @param integer $timeout - * - * @return SparqlDatabase - */ - public function setConnectionTimeoutInSeconds( $timeout = 10 ) { - $this->httpRequest->setOption( CURLOPT_CONNECTTIMEOUT, $timeout ); - return $this; - } - - /** - * @since 2.0 - * - * @param HttpRequest $httpRequest - * - * @return SparqlDatabase - */ - public function setHttpRequest( HttpRequest $httpRequest ) { - $this->httpRequest = $httpRequest; - return $this; - } - -} - diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/Condition.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/Condition.php deleted file mode 100644 index c6a4f404..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/Condition.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine\Condition; - -/** - * Abstract class that represents a SPARQL (sub-)pattern and relevant pieces - * of associated information for using it in query building. - * - * @ingroup SMWStore - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -abstract class Condition { - - /** - * If results could be ordered by the things that this condition - * matches, then this is the name of the variable to use in ORDER BY. - * Otherwise it is ''. - * @note SPARQL variable names do not include the initial "?" or "$". - * @var string - */ - public $orderByVariable = ''; - - /** - * Array that relates sortkeys (given by the users, i.e. property - * names) to variable names in the generated SPARQL query. - * Format sortkey => variable name - * @var array - */ - public $orderVariables = array(); - - /** - * Associative array of additional conditions that should not narrow - * down the set of results, but that introduce some relevant variable, - * typically for ordering. For instance, selecting the sortkey of a - * page needs only be done once per query. The array is indexed by the - * name of the (main) selected variable, e.g. "v42sortkey" to allow - * elimination of duplicate weak conditions that aim to introduce this - * variable. - * @var array of format "condition identifier" => "condition" - */ - public $weakConditions = array(); - - /** - * Associative array of additional namespaces that this condition - * requires to be declared - * @var array of format "shortName" => "namespace URI" - */ - public $namespaces = array(); - - /** - * Get the SPARQL condition string that this object represents. This - * does not inlcude the weak conditions, or additional formulations to - * match singletons (see SMWSparqlSingletonCondition). - * - * @return string - */ - abstract public function getCondition(); - - /** - * Tell whether the condition string returned by getCondition() is safe - * in the sense that it can be used alone in a SPARQL query. This - * requires that all filtered variables occur in some graph pattern, - * and that the condition is not empty. - * - * @return boolean - */ - abstract public function isSafe(); - - public function getWeakConditionString() { - return implode( '', $this->weakConditions ); - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/FalseCondition.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/FalseCondition.php deleted file mode 100644 index 505a4862..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/FalseCondition.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine\Condition; - -/** - * Represents a condition that cannot match anything. - * Ordering is not relevant, as there is nothing to order. - * - * @ingroup SMWStore - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class FalseCondition extends Condition { - - public function getCondition() { - return "<http://www.example.org> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#nothing> .\n"; - } - - public function isSafe() { - return true; - } -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/FilterCondition.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/FilterCondition.php deleted file mode 100644 index 0bf46137..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/FilterCondition.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine\Condition; - -/** - * A SPARQL condition that consists in a FILTER term only (possibly with some - * weak conditions to introduce the variables that the filter acts on). - * - * @ingroup SMWStore - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class FilterCondition extends Condition { - - /** - * Additional filter condition, i.e. a string that could be placed in - * "FILTER( ... )". - * @var string - */ - public $filter; - - public function __construct( $filter, $namespaces = array() ) { - $this->filter = $filter; - $this->namespaces = $namespaces; - } - - public function getCondition() { - return "FILTER( {$this->filter} )\n"; - } - - public function isSafe() { - return false; - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/SingletonCondition.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/SingletonCondition.php deleted file mode 100644 index 1bedad0b..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/SingletonCondition.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine\Condition; - -use SMWExpElement; - -/** - * A SPARQL condition that can match only a single element, or nothing at all. - * - * @ingroup SMWStore - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class SingletonCondition extends Condition { - - /** - * Pattern string. Anything that can be used as a WHERE condition - * when put between "{" and "}". Can be empty if the result - * unconditionally is the given element. - * @var string - */ - public $condition; - - /** - * The single element that this condition may possibly match. - * @var SMWExpElement - */ - public $matchElement; - - /** - * Whether this condition is safe. - * @see SMWSparqlCondition::isSafe(). - * @var boolean - */ - public $isSafe; - - public function __construct( SMWExpElement $matchElement, $condition = '', $isSafe = false, $namespaces = array() ) { - $this->matchElement = $matchElement; - $this->condition = $condition; - $this->isSafe = $isSafe; - $this->namespaces = $namespaces; - } - - public function getCondition() { - return $this->condition; - } - - public function isSafe() { - return $this->isSafe; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/TrueCondition.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/TrueCondition.php deleted file mode 100644 index 5ec622d5..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/TrueCondition.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine\Condition; - -/** - * Represents a condition that matches everything. Weak conditions (see - * SMWSparqlCondition::$weakConditions) might be still be included to - * enable ordering (selecting sufficient data to order by). - * - * @ingroup SMWStore - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class TrueCondition extends Condition { - - public function getCondition() { - return ''; - } - - public function isSafe() { - return false; - } -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/WhereCondition.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/WhereCondition.php deleted file mode 100644 index 1d44bb39..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/Condition/WhereCondition.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine\Condition; - -/** - * Container class that represents a SPARQL (sub-)pattern and relevant pieces - * of associated information for using it in query building. - * - * @ingroup SMWStore - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class WhereCondition extends Condition { - - /** - * The pattern string. Anything that can be used as a WHERE condition - * when put between "{" and "}". - * @var string - */ - public $condition; - - /** - * Whether this condition is safe. - * @see SMWSparqlCondition::isSafe(). - * @var boolean - */ - public $isSafe; - - public function __construct( $condition, $isSafe, $namespaces = array() ) { - $this->condition = $condition; - $this->isSafe = $isSafe; - $this->namespaces = $namespaces; - } - - public function getCondition() { - return $this->condition; - } - - public function isSafe() { - return $this->isSafe; - } -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/FederateResultList.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/FederateResultList.php deleted file mode 100644 index 2ae4c286..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/FederateResultList.php +++ /dev/null @@ -1,204 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine; - -use SMWExpLiteral as ExpLiteral; -use Iterator; - -/** - * Class for accessing SPARQL query results in a unified form. The data is - * structured in tabular form, with each cell containing some SMWExpElement. - * Rows should always have the same number of columns, but the datatype of the - * cells in each column may not be uniform throughout the result. - * - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class FederateResultList implements Iterator { - - /// Error code: no errors occurred. - const ERROR_NOERROR = 0; - /// Error code: service unreachable; result will be empty - const ERROR_UNREACHABLE = 1; - /// Error code: results might be incomplete (e.g. due to some resource limit being reached) - const ERROR_INCOMPLETE = 2; - - /** - * Associative array mapping SPARQL variable names to column indices. - * @var array of integer - */ - protected $header; - - /** - * List of result rows. Individual entries can be null if a cell in the - * SPARQL result table is empty (this is different from finding a blank - * node). - * @var array of array of (SMWExpElement or null) - */ - protected $data; - - /** - * List of comment strings found in the XML file (without surrounding - * markup, i.e. the actual string only). - * @var array of string - */ - protected $comments; - - /** - * Error code. - * @var integer - */ - protected $errorCode; - - /** - * Initialise a result set from a result string in SPARQL XML format. - * - * @param $header array mapping SPARQL variable names to column indices - * @param $data array of array of (SMWExpElement or null) - * @param $comments array of string comments if the result contained any - * @param $errorCode integer an error code - */ - public function __construct( array $header, array $data, array $comments = array(), $errorCode = self::ERROR_NOERROR ) { - $this->header = $header; - $this->data = $data; - $this->comments = $comments; - $this->errorCode = $errorCode; - reset( $this->data ); - } - - /** - * Get the number of rows in the result object. - * - * @return interger number of result rows - */ - public function numRows() { - return count( $this->data ); - } - - /** - * Return error code. SMWSparqlResultWrapper::ERROR_NOERROR (0) - * indicates that no error occurred. - * - * @return integer error code - */ - public function getErrorCode() { - return $this->errorCode; - } - - /** - * Set the error code of this result set. This is used for allowing - * callers to add additional errors discovered only later on. It does - * not allow removing existing errors, since it will not accept - * SMWSparqlResultWrapper::ERROR_NOERROR as a parameter. - * - * @param $errorCode integer error code - */ - public function setErrorCode( $errorCode ) { - if ( $errorCode != self::ERROR_NOERROR ) { - $this->errorCode = $errorCode; - } - } - - /** - * Return a list of comment strings found in the SPARQL result. Comments - * are used by some RDF stores to provide additional information or - * warnings that can thus be accessed. - * - * @return array of string - */ - public function getComments() { - return $this->comments; - } - - /** - * Check if the result is what one would get for a SPARQL ASK query - * that returned true. Returns false in all other cases (including - * the case that the results do not look at all like the result of - * an ASK query). - * - * @return boolean - */ - public function isBooleanTrue() { - if ( count( $this->data ) == 1 ) { - $row = reset( $this->data ); - $expElement = reset( $row ); - if ( ( count( $row ) == 1 ) && ( $expElement instanceof ExpLiteral ) && - ( $expElement->getLexicalForm() == 'true' ) && - ( $expElement->getDatatype() == 'http://www.w3.org/2001/XMLSchema#boolean' ) ) { - return true; - } - } - return false; - } - - /** - * Check if the result is what one would get for a SPARQL SELECT COUNT - * query, and return the corresponding integer value. Returns 0 in all - * other cases (including the case that the results do not look at all - * like the result of a SELECT COUNT query). - * - * @return integer - */ - public function getNumericValue() { - if ( count( $this->data ) == 1 ) { - $row = reset( $this->data ); - $expElement = reset( $row ); - if ( ( count( $row ) == 1 ) && ( $expElement instanceof ExpLiteral ) && - ( $expElement->getDatatype() == 'http://www.w3.org/2001/XMLSchema#integer' ) ) { - return (int)$expElement->getLexicalForm(); - } - } - return 0; - } - - /** - * Reset iterator to position 0. Standard method of Iterator. - */ - public function rewind() { - reset( $this->data ); - } - - /** - * Return the current result row. Standard method of Iterator. - * - * @return array of (SMWExpElement or null), or false at end of data - */ - public function current() { - return current( $this->data ); - } - - /** - * Return the next result row and advance the internal pointer. - * Standard method of Iterator. - * - * @return array of (SMWExpElement or null), or false at end of data - */ - public function next() { - return next( $this->data ); - } - - /** - * Return the next result row and advance the internal pointer. - * Standard method of Iterator. - * - * @return array of (SMWExpElement or null), or false at end of data - */ - public function key() { - return key( $this->data ); - } - - /** - * Return true if the internal pointer refers to a valid element. - * Standard method of Iterator. - * - * @return boolean - */ - public function valid() { - return ( current( $this->data ) !== false ); - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/QueryConditionBuilder.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/QueryConditionBuilder.php deleted file mode 100644 index 3b74b4c1..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/QueryConditionBuilder.php +++ /dev/null @@ -1,647 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine; - -use SMW\SPARQLStore\QueryEngine\Condition\Condition; -use SMW\SPARQLStore\QueryEngine\Condition\FalseCondition; -use SMW\SPARQLStore\QueryEngine\Condition\TrueCondition; -use SMW\SPARQLStore\QueryEngine\Condition\WhereCondition; -use SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition; -use SMW\SPARQLStore\QueryEngine\Condition\FilterCondition; - -use SMW\DataTypeRegistry; -use SMW\Store; -use SMW\DIProperty; -use SMW\DIWikiPage; - -use SMWDataItem as DataItem; -use SMWDIBlob as DIBlob; -use SMWDescription as Description; -use SMWExporter as Exporter; -use SMWTurtleSerializer as TurtleSerializer; -use SMWExpNsResource as ExpNsResource; -use SMWExpLiteral as ExpLiteral; -use SMWSomeProperty as SomeProperty; -use SMWNamespaceDescription as NamespaceDescription; -use SMWConjunction as Conjunction; -use SMWDisjunction as Disjunction; -use SMWClassDescription as ClassDescription; -use SMWValueDescription as ValueDescription; -use SMWConceptDescription as ConceptDescription; -use SMWThingDescription as ThingDescription; - -/** - * Condition mapping from Query objects to SPARQL - * - * @ingroup SMWStore - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author Markus Krötzsch - */ -class QueryConditionBuilder { - - /** - * Counter used to generate globally fresh variables. - * @var integer - */ - private $variableCounter = 0; - - /** - * Sortkeys that are being used while building the query conditions - * @var array - */ - private $sortkeys = array(); - - /** - * The name of the SPARQL variable that represents the query result - * @var string - */ - private $resultVariable = 'result'; - - /** - * @since 2.0 - * - * @param string $resultVariable - */ - public function setResultVariable( $resultVariable ) { - $this->resultVariable = $resultVariable; - return $this; - } - - /** - * @since 2.0 - * - * @param array $sortkeys - */ - public function setSortKeys( $sortkeys ) { - $this->sortkeys = $sortkeys; - return $this; - } - - /** - * Get a Condition object for an Description. - * - * This conversion is implemented by a number of recursive functions, - * and this is the main entry point for this recursion. In particular, - * it resets global variables that are used for the construction. - * - * If property value variables should be recorded for ordering results - * later on, the keys of the respective properties need to be given in - * sortkeys earlier. - * - * @param Description $description - * - * @return Condition - */ - public function buildCondition( Description $description ) { - $this->variableCounter = 0; - $condition = $this->mapConditionBuilderToDescription( $description, $this->resultVariable, null ); - $this->addMissingOrderByConditions( $condition ); - return $condition; - } - - /** - * Build the condition (WHERE) string for a given Condition. - * The function also expresses the single value of - * SingletonCondition objects in the condition, which may - * lead to additional namespaces for serializing its URI. - * - * @param Condition $condition - * - * @return string - */ - public function convertConditionToString( Condition &$condition ) { - - $conditionAsString = $condition->getWeakConditionString(); - - if ( ( $conditionAsString === '' ) && !$condition->isSafe() ) { - $swivtPageResource = Exporter::getSpecialNsResource( 'swivt', 'page' ); - $conditionAsString = '?' . $this->resultVariable . ' ' . $swivtPageResource->getQName() . " ?url .\n"; - } - - $conditionAsString .= $condition->getCondition(); - - if ( $condition instanceof SingletonCondition ) { // prepare for ASK, maybe rather use BIND? - - $matchElement = $condition->matchElement; - $matchElementName = TurtleSerializer::getTurtleNameForExpElement( $matchElement ); - - if ( $matchElement instanceof ExpNsResource ) { - $condition->namespaces[$matchElement->getNamespaceId()] = $matchElement->getNamespace(); - } - - $conditionAsString = str_replace( '?' . $this->resultVariable . ' ', "$matchElementName ", $conditionAsString ); - } - - return $conditionAsString; - } - - /** - * Recursively create an Condition from an Description. - * - * @param $description Description - * @param $joinVariable string name of the variable that conditions - * will refer to - * @param $orderByProperty mixed DIProperty or null, if given then - * this is the property the values of which this condition will refer - * to, and the condition should also enable ordering by this value - * @return Condition - */ - protected function mapConditionBuilderToDescription( Description $description, $joinVariable, $orderByProperty ) { - - if ( $description instanceof SomeProperty ) { - return $this->buildPropertyCondition( $description, $joinVariable, $orderByProperty ); - } elseif ( $description instanceof NamespaceDescription ) { - return $this->buildNamespaceCondition( $description, $joinVariable, $orderByProperty ); - } elseif ( $description instanceof Conjunction ) { - return $this->buildConjunctionCondition( $description, $joinVariable, $orderByProperty ); - } elseif ( $description instanceof Disjunction ) { - return $this->buildDisjunctionCondition( $description, $joinVariable, $orderByProperty ); - } elseif ( $description instanceof ClassDescription ) { - return $this->buildClassCondition( $description, $joinVariable, $orderByProperty ); - } elseif ( $description instanceof ValueDescription ) { - return $this->buildValueCondition( $description, $joinVariable, $orderByProperty ); - } elseif ( $description instanceof ConceptDescription ) { - return new TrueCondition(); ///TODO Implement concept queries - } - - // (e.g. ThingDescription) - return $this->buildTrueCondition( $joinVariable, $orderByProperty ); - } - - /** - * Recursively create an Condition from an Conjunction. - * - * @param $description Conjunction - * @param $joinVariable string name, see mapConditionBuilderToDescription() - * @param $orderByProperty mixed DIProperty or null, see mapConditionBuilderToDescription() - * - * @return Condition - */ - protected function buildConjunctionCondition( Conjunction $description, $joinVariable, $orderByProperty ) { - - $subDescriptions = $description->getDescriptions(); - - if ( count( $subDescriptions ) == 0 ) { // empty conjunction: true - return $this->buildTrueCondition( $joinVariable, $orderByProperty ); - } elseif ( count( $subDescriptions ) == 1 ) { // conjunction with one element - return $this->mapConditionBuilderToDescription( reset( $subDescriptions ), $joinVariable, $orderByProperty ); - } - - $condition = ''; - $filter = ''; - $namespaces = $weakConditions = $orderVariables = array(); - $singletonMatchElement = null; - $singletonMatchElementName = ''; - $hasSafeSubconditions = false; - - foreach ( $subDescriptions as $subDescription ) { - - $subCondition = $this->mapConditionBuilderToDescription( $subDescription, $joinVariable, null ); - - if ( $subCondition instanceof FalseCondition ) { - return new FalseCondition(); - } elseif ( $subCondition instanceof TrueCondition ) { - // ignore true conditions in a conjunction - } elseif ( $subCondition instanceof WhereCondition ) { - $condition .= $subCondition->condition; - } elseif ( $subCondition instanceof FilterCondition ) { - $filter .= ( $filter ? ' && ' : '' ) . $subCondition->filter; - } elseif ( $subCondition instanceof SingletonCondition ) { - $matchElement = $subCondition->matchElement; - $matchElementName = TurtleSerializer::getTurtleNameForExpElement( $matchElement ); - - if ( $matchElement instanceof ExpNsResource ) { - $namespaces[$matchElement->getNamespaceId()] = $matchElement->getNamespace(); - } - - if ( ( !is_null( $singletonMatchElement ) ) && - ( $singletonMatchElementName !== $matchElementName ) ) { - return new FalseCondition(); - } - - $condition .= $subCondition->condition; - $singletonMatchElement = $subCondition->matchElement; - $singletonMatchElementName = $matchElementName; - } - - $hasSafeSubconditions = $hasSafeSubconditions || $subCondition->isSafe(); - $namespaces = array_merge( $namespaces, $subCondition->namespaces ); - $weakConditions = array_merge( $weakConditions, $subCondition->weakConditions ); - $orderVariables = array_merge( $orderVariables, $subCondition->orderVariables ); - } - - if ( !is_null( $singletonMatchElement ) ) { - if ( $filter !== '' ) { - $condition .= "FILTER( $filter )"; - } - - $result = new SingletonCondition( - $singletonMatchElement, - $condition, - $hasSafeSubconditions, - $namespaces - ); - - } elseif ( $condition === '' ) { - $result = new FilterCondition( $filter, $namespaces ); - } else { - if ( $filter !== '' ) { - $condition .= "FILTER( $filter )"; - } - - $result = new WhereCondition( $condition, $hasSafeSubconditions, $namespaces ); - } - - $result->weakConditions = $weakConditions; - $result->orderVariables = $orderVariables; - - $this->addOrderByDataForProperty( $result, $joinVariable, $orderByProperty ); - - return $result; - } - - /** - * Recursively create an Condition from an Disjunction. - * - * @param $description Disjunction - * @param $joinVariable string name, see mapConditionBuilderToDescription() - * @param $orderByProperty mixed DIProperty or null, see mapConditionBuilderToDescription() - * - * @return Condition - */ - protected function buildDisjunctionCondition( Disjunction $description, $joinVariable, $orderByProperty ) { - $subDescriptions = $description->getDescriptions(); - if ( count( $subDescriptions ) == 0 ) { // empty disjunction: false - return new FalseCondition(); - } elseif ( count( $subDescriptions ) == 1 ) { // disjunction with one element - return $this->mapConditionBuilderToDescription( reset( $subDescriptions ), $joinVariable, $orderByProperty ); - } // else: proper disjunction; note that orderVariables found in subconditions cannot be used for the whole disjunction - - $unionCondition = ''; - $filter = ''; - $namespaces = $weakConditions = array(); - $hasSafeSubconditions = false; - foreach ( $subDescriptions as $subDescription ) { - $subCondition = $this->mapConditionBuilderToDescription( $subDescription, $joinVariable, null ); - if ( $subCondition instanceof FalseCondition ) { - // empty parts in a disjunction can be ignored - } elseif ( $subCondition instanceof TrueCondition ) { - return $this->buildTrueCondition( $joinVariable, $orderByProperty ); - } elseif ( $subCondition instanceof WhereCondition ) { - $hasSafeSubconditions = $hasSafeSubconditions || $subCondition->isSafe(); - $unionCondition .= ( $unionCondition ? ' UNION ' : '' ) . - "{\n" . $subCondition->condition . "}"; - } elseif ( $subCondition instanceof FilterCondition ) { - $filter .= ( $filter ? ' || ' : '' ) . $subCondition->filter; - } elseif ( $subCondition instanceof SingletonCondition ) { - $hasSafeSubconditions = $hasSafeSubconditions || $subCondition->isSafe(); - $matchElement = $subCondition->matchElement; - $matchElementName = TurtleSerializer::getTurtleNameForExpElement( $matchElement ); - if ( $matchElement instanceof ExpNsResource ) { - $namespaces[$matchElement->getNamespaceId()] = $matchElement->getNamespace(); - } - if ( $subCondition->condition === '' ) { - $filter .= ( $filter ? ' || ' : '' ) . "?$joinVariable = $matchElementName"; - } else { - $unionCondition .= ( $unionCondition ? ' UNION ' : '' ) . - "{\n" . $subCondition->condition . " FILTER( ?$joinVariable = $matchElementName ) }"; - } - } - $namespaces = array_merge( $namespaces, $subCondition->namespaces ); - $weakConditions = array_merge( $weakConditions, $subCondition->weakConditions ); - } - - if ( ( $unionCondition === '' ) && ( $filter === '' ) ) { - return new FalseCondition(); - } elseif ( $unionCondition === '' ) { - $result = new FilterCondition( $filter, $namespaces ); - } elseif ( $filter === '' ) { - $result = new WhereCondition( $unionCondition, $hasSafeSubconditions, $namespaces ); - } else { - $subJoinVariable = $this->getNextVariable(); - $unionCondition = str_replace( "?$joinVariable ", "?$subJoinVariable ", $unionCondition ); - $filter .= " || ?$joinVariable = ?$subJoinVariable"; - $result = new WhereCondition( "OPTIONAL { $unionCondition }\n FILTER( $filter )\n", false, $namespaces ); - } - - $result->weakConditions = $weakConditions; - - $this->addOrderByDataForProperty( $result, $joinVariable, $orderByProperty ); - - return $result; - } - - /** - * Recursively create an Condition from an SomeProperty. - * - * @param $description SomeProperty - * @param $joinVariable string name, see mapConditionBuilderToDescription() - * @param $orderByProperty mixed DIProperty or null, see mapConditionBuilderToDescription() - * - * @return Condition - */ - protected function buildPropertyCondition( SomeProperty $description, $joinVariable, $orderByProperty ) { - $diProperty = $description->getProperty(); - - //*** Find out if we should order by the values of this property ***// - if ( array_key_exists( $diProperty->getKey(), $this->sortkeys ) ) { - $innerOrderByProperty = $diProperty; - } else { - $innerOrderByProperty = null; - } - - //*** Prepare inner condition ***// - $innerJoinVariable = $this->getNextVariable(); - $innerCondition = $this->mapConditionBuilderToDescription( $description->getDescription(), $innerJoinVariable, $innerOrderByProperty ); - $namespaces = $innerCondition->namespaces; - - if ( $innerCondition instanceof FalseCondition ) { - return new FalseCondition(); - } elseif ( $innerCondition instanceof SingletonCondition ) { - $matchElement = $innerCondition->matchElement; - $objectName = TurtleSerializer::getTurtleNameForExpElement( $matchElement ); - if ( $matchElement instanceof ExpNsResource ) { - $namespaces[$matchElement->getNamespaceId()] = $matchElement->getNamespace(); - } - } else { - $objectName = '?' . $innerJoinVariable; - } - - //*** Exchange arguments when property is inverse ***// - if ( $diProperty->isInverse() ) { // don't check if this really makes sense - $subjectName = $objectName; - $objectName = '?' . $joinVariable; - $diNonInverseProperty = new DIProperty( $diProperty->getKey(), false ); - } else { - $subjectName = '?' . $joinVariable; - $diNonInverseProperty = $diProperty; - } - - //*** Build the condition ***// - // Use helper properties in encoding values, refer to this helper property: - if ( Exporter::hasHelperExpElement( $diProperty ) ) { - $propertyExpElement = Exporter::getResourceElementForProperty( $diNonInverseProperty, true ); - } else { - $propertyExpElement = Exporter::getResourceElementForProperty( $diNonInverseProperty ); - } - - $propertyName = TurtleSerializer::getTurtleNameForExpElement( $propertyExpElement ); - - if ( $propertyExpElement instanceof ExpNsResource ) { - $namespaces[$propertyExpElement->getNamespaceId()] = $propertyExpElement->getNamespace(); - } - - $condition = "$subjectName $propertyName $objectName .\n"; - $innerConditionString = $innerCondition->getCondition() . $innerCondition->getWeakConditionString(); - - if ( $innerConditionString !== '' ) { - if ( $innerCondition instanceof FilterCondition ) { - $condition .= $innerConditionString; - } else { - $condition .= "{ $innerConditionString}\n"; - } - } - - $result = new WhereCondition( $condition, true, $namespaces ); - - //*** Record inner ordering variable if found ***// - $result->orderVariables = $innerCondition->orderVariables; - if ( !is_null( $innerOrderByProperty ) && ( $innerCondition->orderByVariable !== '' ) ) { - $result->orderVariables[$diProperty->getKey()] = $innerCondition->orderByVariable; - } - - $this->addOrderByDataForProperty( $result, $joinVariable, $orderByProperty, DataItem::TYPE_WIKIPAGE ); - - return $result; - } - - /** - * Create an Condition from an ClassDescription. - * - * @param $description ClassDescription - * @param $joinVariable string name, see mapConditionBuilderToDescription() - * @param $orderByProperty mixed DIProperty or null, see mapConditionBuilderToDescription() - * - * @return Condition - */ - protected function buildClassCondition( ClassDescription $description, $joinVariable, $orderByProperty ) { - - $condition = ''; - $namespaces = array(); - $instExpElement = Exporter::getSpecialPropertyResource( '_INST' ); - - foreach( $description->getCategories() as $diWikiPage ) { - $categoryExpElement = Exporter::getResourceElementForWikiPage( $diWikiPage ); - $categoryName = TurtleSerializer::getTurtleNameForExpElement( $categoryExpElement ); - $namespaces[$categoryExpElement->getNamespaceId()] = $categoryExpElement->getNamespace(); - $newcondition = "{ ?$joinVariable " . $instExpElement->getQName() . " $categoryName . }\n"; - if ( $condition === '' ) { - $condition = $newcondition; - } else { - $condition .= "UNION\n$newcondition"; - } - } - - if ( $condition === '' ) { // empty disjunction: always false, no results to order - return new FalseCondition(); - } - - $result = new WhereCondition( $condition, true, $namespaces ); - - $this->addOrderByDataForProperty( $result, $joinVariable, $orderByProperty, DataItem::TYPE_WIKIPAGE ); - - return $result; - } - - /** - * Create an Condition from an NamespaceDescription. - * - * @param $description NamespaceDescription - * @param $joinVariable string name, see mapConditionBuilderToDescription() - * @param $orderByProperty mixed DIProperty or null, see mapConditionBuilderToDescription() - * - * @return Condition - */ - protected function buildNamespaceCondition( NamespaceDescription $description, $joinVariable, $orderByProperty ) { - $nspropExpElement = Exporter::getSpecialNsResource( 'swivt', 'wikiNamespace' ); - $nsExpElement = new ExpLiteral( strval( $description->getNamespace() ), 'http://www.w3.org/2001/XMLSchema#integer' ); - $nsName = TurtleSerializer::getTurtleNameForExpElement( $nsExpElement ); - $condition = "{ ?$joinVariable " . $nspropExpElement->getQName() . " $nsName . }\n"; - - $result = new WhereCondition( $condition, true, array() ); - - $this->addOrderByDataForProperty( - $result, - $joinVariable, - $orderByProperty, - DataItem::TYPE_WIKIPAGE - ); - - return $result; - } - - /** - * Create an Condition from an ValueDescription. - * - * @param $description ValueDescription - * @param $joinVariable string name, see mapConditionBuilderToDescription() - * @param $orderByProperty mixed DIProperty or null, see mapConditionBuilderToDescription() - * - * @return Condition - */ - protected function buildValueCondition( ValueDescription $description, $joinVariable, $orderByProperty ) { - $dataItem = $description->getDataItem(); - - switch ( $description->getComparator() ) { - case SMW_CMP_EQ: $comparator = '='; break; - case SMW_CMP_LESS: $comparator = '<'; break; - case SMW_CMP_GRTR: $comparator = '>'; break; - case SMW_CMP_LEQ: $comparator = '<='; break; - case SMW_CMP_GEQ: $comparator = '>='; break; - case SMW_CMP_NEQ: $comparator = '!='; break; - case SMW_CMP_LIKE: $comparator = 'regex'; break; - case SMW_CMP_NLKE: $comparator = '!regex'; break; - default: $comparator = ''; // unkown, unsupported - } - - if ( $comparator === '' ) { - $result = $this->buildTrueCondition( $joinVariable, $orderByProperty ); - } elseif ( $comparator == '=' ) { - $expElement = Exporter::getDataItemHelperExpElement( $dataItem ); - if ( is_null( $expElement ) ) { - $expElement = Exporter::getDataItemExpElement( $dataItem ); - } - $result = new SingletonCondition( $expElement ); - $this->addOrderByDataForProperty( $result, $joinVariable, $orderByProperty, $dataItem->getDIType() ); - } elseif ( $comparator == 'regex' || $comparator == '!regex' ) { - if ( $dataItem instanceof DIBlob ) { - $pattern = '^' . str_replace( array( '^', '.', '\\', '+', '{', '}', '(', ')', '|', '^', '$', '[', ']', '*', '?' ), - array( '\^', '\.', '\\\\', '\+', '\{', '\}', '\(', '\)', '\|', '\^', '\$', '\[', '\]', '.*', '.' ), - $dataItem->getString() ) . '$'; - $result = new FilterCondition( "$comparator( ?$joinVariable, \"$pattern\", \"s\")", array() ); - $this->addOrderByDataForProperty( $result, $joinVariable, $orderByProperty, $dataItem->getDIType() ); - } else { - $result = $this->buildTrueCondition( $joinVariable, $orderByProperty ); - } - } else { - $result = new FilterCondition( '', array() ); - $this->addOrderByData( $result, $joinVariable, $dataItem->getDIType() ); - $orderByVariable = $result->orderByVariable; - - if ( $dataItem instanceof DIWikiPage ) { - $expElement = Exporter::getDataItemExpElement( $dataItem->getSortKeyDataItem() ); - } else { - $expElement = Exporter::getDataItemHelperExpElement( $dataItem ); - if ( is_null( $expElement ) ) { - $expElement = Exporter::getDataItemExpElement( $dataItem ); - } - } - - $valueName = TurtleSerializer::getTurtleNameForExpElement( $expElement ); - - if ( $expElement instanceof ExpNsResource ) { - $result->namespaces[$expElement->getNamespaceId()] = $expElement->getNamespace(); - } - - $result->filter = "?$orderByVariable $comparator $valueName"; - } - - return $result; - } - - /** - * Create an Condition from an empty (true) description. - * May still require helper conditions for ordering. - * - * @param $joinVariable string name, see mapConditionBuilderToDescription() - * @param $orderByProperty mixed DIProperty or null, see mapConditionBuilderToDescription() - * - * @return Condition - */ - protected function buildTrueCondition( $joinVariable, $orderByProperty ) { - $result = new TrueCondition(); - $this->addOrderByDataForProperty( $result, $joinVariable, $orderByProperty ); - return $result; - } - - /** - * Get a fresh unused variable name for building SPARQL conditions. - * - * @return string - */ - protected function getNextVariable() { - return 'v' . ( ++$this->variableCounter ); - } - - /** - * Extend the given SPARQL condition by a suitable order by variable, - * if an order by property is set. - * - * @param Condition $sparqlCondition condition to modify - * @param string $mainVariable the variable that represents the value to be ordered - * @param mixed $orderByProperty DIProperty or null - * @param integer $diType DataItem type id if known, or DataItem::TYPE_NOTYPE to determine it from the property - */ - protected function addOrderByDataForProperty( Condition &$sparqlCondition, $mainVariable, $orderByProperty, $diType = DataItem::TYPE_NOTYPE ) { - if ( is_null( $orderByProperty ) ) { - return; - } - - if ( $diType == DataItem::TYPE_NOTYPE ) { - $diType = DataTypeRegistry::getInstance()->getDataItemId( $orderByProperty->findPropertyTypeID() ); - } - - $this->addOrderByData( $sparqlCondition, $mainVariable, $diType ); - } - - /** - * Extend the given SPARQL condition by a suitable order by variable, - * possibly adding conditions if required for the type of data. - * - * @param Condition $sparqlCondition condition to modify - * @param string $mainVariable the variable that represents the value to be ordered - * @param integer $diType DataItem type id - */ - protected function addOrderByData( Condition &$sparqlCondition, $mainVariable, $diType ) { - if ( $diType == DataItem::TYPE_WIKIPAGE ) { - $sparqlCondition->orderByVariable = $mainVariable . 'sk'; - $skeyExpElement = Exporter::getSpecialPropertyResource( '_SKEY' ); - $sparqlCondition->weakConditions = array( $sparqlCondition->orderByVariable => - "?$mainVariable " . $skeyExpElement->getQName() . " ?{$sparqlCondition->orderByVariable} .\n" ); - } else { - $sparqlCondition->orderByVariable = $mainVariable; - } - } - - /** - * Extend the given Condition with additional conditions to - * ensure that it can be ordered by all requested properties. After - * this operation, every key in sortkeys is assigned to a query - * variable by $sparqlCondition->orderVariables. - * - * @param Condition $sparqlCondition condition to modify - */ - protected function addMissingOrderByConditions( Condition &$sparqlCondition ) { - foreach ( $this->sortkeys as $propkey => $order ) { - if ( !array_key_exists( $propkey, $sparqlCondition->orderVariables ) ) { // Find missing property to sort by. - - if ( $propkey === '' ) { // order by result page sortkey - $this->addOrderByData( $sparqlCondition, $this->resultVariable, DataItem::TYPE_WIKIPAGE ); - $sparqlCondition->orderVariables[$propkey] = $sparqlCondition->orderByVariable; - } else { // extend query to order by other property values - $diProperty = new DIProperty( $propkey ); - $auxDescription = new SomeProperty( $diProperty, new ThingDescription() ); - $auxSparqlCondition = $this->mapConditionBuilderToDescription( $auxDescription, $this->resultVariable, null ); - // orderVariables MUST be set for $propkey -- or there is a bug; let it show! - $sparqlCondition->orderVariables[$propkey] = $auxSparqlCondition->orderVariables[$propkey]; - $sparqlCondition->weakConditions[$sparqlCondition->orderVariables[$propkey]] = $auxSparqlCondition->getWeakConditionString() . $auxSparqlCondition->getCondition(); - $sparqlCondition->namespaces = array_merge( $sparqlCondition->namespaces, $auxSparqlCondition->namespaces ); - } - } - } - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/QueryEngine.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/QueryEngine.php deleted file mode 100644 index 350c6696..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/QueryEngine.php +++ /dev/null @@ -1,324 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine; - -use SMW\SPARQLStore\QueryEngine\Condition\Condition; -use SMW\SPARQLStore\QueryEngine\Condition\FalseCondition; -use SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition; -use SMW\SPARQLStore\QueryEngine\FederateResultList; - -use SMW\QueryOutputFormatter; - -use SMWSparqlDatabase as SparqlDatabase; -use SMWQueryResult as QueryResult; -use SMWQuery as Query; -use SMWThingDescription as ThingDescription; - -/** - * Class mapping SMWQuery objects to SPARQL, and for controlling the execution - * of these queries to obtain suitable QueryResult objects. - * - * @ingroup Store - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author Markus Krötzsch - * @author mwjames - */ -class QueryEngine { - - /// The name of the SPARQL variable that represents the query result. - const RESULT_VARIABLE = 'result'; - - /** - * @var SparqlDatabase - */ - private $connection; - - /** - * @var QueryConditionBuilder - */ - private $queryConditionBuilder; - - /** - * @var ResultListConverter - */ - private $resultListConverter; - - /** - * Copy of the SMWQuery sortkeys array to be used while building the - * SPARQL query conditions. - * @var array - */ - private $sortkeys; - - /** - * @var boolean - */ - private $ignoreQueryErrors = false; - - /** - * @var boolean - */ - private $sortingSupport = true; - - /** - * @var boolean - */ - private $randomSortingSupport = true; - - /** - * @since 2.0 - * - * @param SparqlDatabase $connection - * @param QueryConditionBuilder $queryConditionBuilder - * @param ResultListConverter $resultListConverter - */ - public function __construct( SparqlDatabase $connection, QueryConditionBuilder $queryConditionBuilder, ResultListConverter $resultListConverter ) { - $this->connection = $connection; - $this->queryConditionBuilder = $queryConditionBuilder; - $this->resultListConverter = $resultListConverter; - - $this->queryConditionBuilder->setResultVariable( self::RESULT_VARIABLE ); - } - - /** - * @since 2.0 - * - * @param boolean $ignoreQueryErrors - */ - public function setIgnoreQueryErrors( $ignoreQueryErrors ) { - $this->ignoreQueryErrors = $ignoreQueryErrors; - return $this; - } - - /** - * @since 2.0 - * - * @param boolean $sortingSupport - */ - public function setSortingSupport( $sortingSupport ) { - $this->sortingSupport = $sortingSupport; - return $this; - } - - /** - * @since 2.0 - * - * @param boolean $randomSortingSupport - */ - public function setRandomSortingSupport( $randomSortingSupport ) { - $this->randomSortingSupport = $randomSortingSupport; - return $this; - } - - /** - * @since 2.0 - * @param Query $query - * - * @return QueryResult|string - */ - public function getQueryResult( Query $query ) { - - if ( ( !$this->ignoreQueryErrors || $query->getDescription() instanceof ThingDescription ) && - $query->querymode != Query::MODE_DEBUG && - count( $query->getErrors() ) > 0 ) { - return $this->resultListConverter->newEmptyQueryResult( $query, false ); - } - - // don't query, but return something to the printer - if ( $query->querymode == Query::MODE_NONE ) { - return $this->resultListConverter->newEmptyQueryResult( $query, true ); - } - - if ( $query->querymode == Query::MODE_DEBUG ) { - return $this->getDebugQueryResult( $query ); - } elseif ( $query->querymode == Query::MODE_COUNT ) { - return $this->getCountQueryResult( $query ); - } - - return $this->getInstanceQueryResult( $query ); - } - - /** - * Get the output number for a query in counting mode. - * - * @note ignore sorting, just count - * - * @param Query $query - * - * @return integer - */ - public function getCountQueryResult( Query $query ) { - - // $countResultLookup = new CountResultLookup( $this->connection, $this->queryConditionBuilder ); - // $countResultLookup->getQueryResult( $query ); - - $this->sortkeys = array(); - - $sparqlCondition = $this->queryConditionBuilder - ->setSortKeys( $this->sortkeys ) - ->buildCondition( $query->getDescription() ); - - if ( $sparqlCondition instanceof SingletonCondition ) { - if ( $sparqlCondition->condition === '' ) { // all URIs exist, no querying - return 1; - } else { - $condition = $this->queryConditionBuilder->convertConditionToString( $sparqlCondition ); - $namespaces = $sparqlCondition->namespaces; - $askQueryResult = $this->connection->ask( $condition, $namespaces ); - - return $askQueryResult->isBooleanTrue() ? 1 : 0; - } - } elseif ( $sparqlCondition instanceof FalseCondition ) { - return 0; - } - - $condition = $this->queryConditionBuilder->convertConditionToString( $sparqlCondition ); - $namespaces = $sparqlCondition->namespaces; - - $options = $this->getOptions( $query, $sparqlCondition ); - $options['DISTINCT'] = true; - - $federateResultList = $this->connection->selectCount( - '?' . self::RESULT_VARIABLE, - $condition, - $options, - $namespaces - ); - - return $this->resultListConverter->convertToQueryResult( $federateResultList, $query ); - } - - /** - * Get the results for a query in instance retrieval mode. - * - * @param Query $query - * - * @return QueryResult - */ - public function getInstanceQueryResult( Query $query ) { - - $this->sortkeys = $query->sortkeys; - - $sparqlCondition = $this->queryConditionBuilder - ->setSortKeys( $this->sortkeys ) - ->buildCondition( $query->getDescription() ); - - if ( $sparqlCondition instanceof SingletonCondition ) { - $matchElement = $sparqlCondition->matchElement; - - if ( $sparqlCondition->condition === '' ) { // all URIs exist, no querying - $results = array( array ( $matchElement ) ); - } else { - $condition = $this->queryConditionBuilder->convertConditionToString( $sparqlCondition ); - $namespaces = $sparqlCondition->namespaces; - $askQueryResult = $this->connection->ask( $condition, $namespaces ); - $results = $askQueryResult->isBooleanTrue() ? array( array ( $matchElement ) ) : array(); - } - - $federateResultList = new FederateResultList( array( self::RESULT_VARIABLE => 0 ), $results ); - - } elseif ( $sparqlCondition instanceof FalseCondition ) { - $federateResultList = new FederateResultList( array( self::RESULT_VARIABLE => 0 ), array() ); - } else { - $condition = $this->queryConditionBuilder->convertConditionToString( $sparqlCondition ); - $namespaces = $sparqlCondition->namespaces; - - $options = $this->getOptions( $query, $sparqlCondition ); - $options['DISTINCT'] = true; - - $federateResultList = $this->connection->select( - '?' . self::RESULT_VARIABLE, - $condition, - $options, - $namespaces - ); - } - - return $this->resultListConverter->convertToQueryResult( $federateResultList, $query ); - } - - /** - * Get the output string for a query in debugging mode. - * - * @param Query $query - * - * @return string - */ - public function getDebugQueryResult( Query $query ) { - - $this->sortkeys = $query->sortkeys; - - $sparqlCondition = $this->queryConditionBuilder - ->setSortKeys( $this->sortkeys ) - ->buildCondition( $query->getDescription() ); - - $entries = array(); - - if ( $sparqlCondition instanceof SingletonCondition ) { - if ( $sparqlCondition->condition === '' ) { // all URIs exist, no querying - $sparql = 'None (no conditions).'; - } else { - $condition = $this->queryConditionBuilder->convertConditionToString( $sparqlCondition ); - $namespaces = $sparqlCondition->namespaces; - $sparql = $this->connection->getSparqlForAsk( $condition, $namespaces ); - } - } elseif ( $sparqlCondition instanceof FalseCondition ) { - $sparql = 'None (conditions can not be satisfied by anything).'; - } else { - $condition = $this->queryConditionBuilder->convertConditionToString( $sparqlCondition ); - $namespaces = $sparqlCondition->namespaces; - - $options = $this->getOptions( $query, $sparqlCondition ); - $options['DISTINCT'] = true; - - $sparql = $this->connection->getSparqlForSelect( - '?' . self::RESULT_VARIABLE, - $condition, - $options, - $namespaces - ); - } - - $sparql = str_replace( array( '[',':',' ' ), array( '[', ':', ' ' ), $sparql ); - $entries['SPARQL Query'] = "<pre>$sparql</pre>"; - - return QueryOutputFormatter::formatDebugOutput( 'SPARQLStore', $entries, $query ); - } - - /** - * Get a SPARQL option array for the given query. - * - * @param Query $query - * @param Condition $sparqlCondition (storing order by variable names) - * - * @return array - */ - protected function getOptions( Query $query, Condition $sparqlCondition ) { - - $result = array( 'LIMIT' => $query->getLimit() + 1, 'OFFSET' => $query->getOffset() ); - - // Build ORDER BY options using discovered sorting fields. - if ( $this->sortingSupport ) { - - $orderByString = ''; - - foreach ( $this->sortkeys as $propkey => $order ) { - if ( ( $order != 'RANDOM' ) && array_key_exists( $propkey, $sparqlCondition->orderVariables ) ) { - $orderByString .= "$order(?" . $sparqlCondition->orderVariables[$propkey] . ") "; - } elseif ( ( $order == 'RANDOM' ) && $this->randomSortingSupport ) { - // not supported in SPARQL; might be possible via function calls in some stores - } - } - - if ( $orderByString !== '' ) { - $result['ORDER BY'] = $orderByString; - } - } - - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/RawResultParser.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/RawResultParser.php deleted file mode 100644 index ec2215e6..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/RawResultParser.php +++ /dev/null @@ -1,202 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine; - -use SMWExpResource as ExpResource; -use SMWExpLiteral as ExpLiteral; - -use RuntimeException; - -/** - * Class for parsing SPARQL results in XML format - * - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class RawResultParser { - - /** - * @var resource - */ - private $parser; - - /** - * Associative array mapping SPARQL variable names to column indices. - * @var array of integer - */ - private $header; - - /** - * List of result rows. Individual entries can be null if a cell in the - * SPARQL result table is empty (this is different from finding a blank - * node). - * @var array of array of (SMWExpElement or null) - */ - private $data; - - /** - * List of comment strings found in the XML file (without surrounding - * markup, i.e. the actual string only). - * @var array of string - */ - private $comments; - - /** - * Stack of open XML tags during parsing. - * @var array of string - */ - private $xmlOpenTags; - - /** - * Integer index of the column that the current result binding fills. - * @var integer - */ - private $xmlBindIndex; - - /** - * Datatype URI for the current literal, or empty if none. - * @var string - */ - private $currentDataType; - - /** - * @since 2.0 - */ - public function __construct() { - $this->parser = xml_parser_create(); - - xml_parser_set_option( $this->parser, XML_OPTION_SKIP_WHITE, 0 ); - xml_parser_set_option( $this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8' ); - xml_parser_set_option( $this->parser, XML_OPTION_CASE_FOLDING, 0 ); - xml_set_object( $this->parser, $this ); - xml_set_element_handler( $this->parser, 'handleOpenElement', 'handleCloseElement' ); - xml_set_character_data_handler( $this->parser, 'handleCharacterData' ); - xml_set_default_handler( $this->parser, 'handleDefault' ); - //xml_set_start_namespace_decl_handler($parser, 'handleNsDeclaration' ); - } - - /** - * @since 2.0 - */ - public function __destruct() { - xml_parser_free( $this->parser ); - } - - /** - * Parse the given XML result and return an FederateResultList for - * the contained data. - * - * @param string $rawData - * - * @return FederateResultList - */ - public function parse( $rawResult ) { - - $this->xmlOpenTags = array(); - $this->header = array(); - $this->data = array(); - $this->comments = array(); - - if ( $rawResult == 'false' || is_bool( $rawResult ) || $this->parseXml( $rawResult ) ) { - return new FederateResultList( $this->header, $this->data, $this->comments ); - } - - throw new RuntimeException( "Parser error: " . $this->getLastError() ); - } - - private function parseXml( $xmlResultData ) { - return xml_parse( $this->parser, $xmlResultData , true ); - } - - private function getLastError() { - return xml_error_string( xml_get_error_code( $this->parser ) ); - } - - private function handleDefault( $parser, $data ) { - if ( substr( $data, 0, 4 ) == '<!--' ) { - $comment = substr( $data, 4, strlen( $data ) - 7 ); - $this->comments[] = trim( $comment ); - } - } - - /** - * @see xml_set_element_handler - */ - private function handleOpenElement( $parser, $elementTag, $attributes ) { - - $this->currentDataType = ''; - - $prevTag = end( $this->xmlOpenTags ); - $this->xmlOpenTags[] = $elementTag; - - switch ( $elementTag ) { - case 'binding' && ( $prevTag == 'result' ): - if ( ( array_key_exists( 'name', $attributes ) ) && - ( array_key_exists( $attributes['name'], $this->header ) ) ) { - $this->xmlBindIndex = $this->header[$attributes['name']]; - } - break; - case 'result' && ( $prevTag == 'results' ): - $row = array(); - - for ( $i = 0; $i < count( $this->header ); ++$i ) { - $row[$i] = null; - } - - $this->data[] = $row; - break; - case 'literal' && ( $prevTag == 'binding' ): - if ( array_key_exists( 'datatype', $attributes ) ) { - $this->currentDataType = $attributes['datatype']; - } - /// TODO handle xml:lang attributes here as well? - break; - case 'variable' && ( $prevTag == 'head' ): - if ( array_key_exists( 'name', $attributes ) ) { - $this->header[$attributes['name']] = count( $this->header ); - } - break; - } - } - - /** - * @see xml_set_element_handler - */ - private function handleCloseElement( $parser, $elementTag ) { - array_pop( $this->xmlOpenTags ); - } - - /** - * @see xml_set_character_data_handler - */ - private function handleCharacterData( $parser, $characterData ) { - - $prevTag = end( $this->xmlOpenTags ); - $rowcount = count( $this->data ); - - switch ( $prevTag ) { - case 'uri': - $this->data[$rowcount-1][$this->xmlBindIndex] = new ExpResource( $characterData ); - break; - case 'literal': - $this->data[$rowcount-1][$this->xmlBindIndex] = new ExpLiteral( $characterData, $this->currentDataType ); - break; - case 'bnode': - $this->data[$rowcount-1][$this->xmlBindIndex] = new ExpResource( '_' . $characterData ); - break; - case 'boolean': - // no "results" in this case - $literal = new ExpLiteral( $characterData, 'http://www.w3.org/2001/XMLSchema#boolean' ); - - // ?? Really !! - $this->data = array( array( $literal ) ); - $this->header = array( '' => 0 ); - break; - } - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/ResultListConverter.php b/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/ResultListConverter.php deleted file mode 100644 index 84fad554..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/QueryEngine/ResultListConverter.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php - -namespace SMW\SPARQLStore\QueryEngine; - -use SMW\Store; - -use SMWExporter as Exporter; -use SMWQueryResult as QueryResult; -use SMWQuery as Query; - -/** - * Convert SPARQL FederateResultList object to an QueryResult object - * - * @ingroup Store - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author Markus Krötzsch - * @author mwjames - */ -class ResultListConverter { - - /** - * @var Store - */ - private $store; - - /** - * @since 2.0 - * - * @param Store $store - */ - public function __construct( Store $store ) { - $this->store = $store; - } - - /** - * @since 2.0 - * - * @param Query $query QueryResults hold a reference to original query - * @param boolean $hasFurtherResults - * - * @return QueryResult - */ - public function newEmptyQueryResult( Query $query , $hasFurtherResults = false ) { - return new QueryResult( - $query->getDescription()->getPrintrequests(), - $query, - array(), - $this->store, - $hasFurtherResults - ); - } - - /** - * This function is used to generate instance query results, and the given - * result wrapper must have an according format (one result column that - * contains URIs of wiki pages). - * - * @param FederateResultList $federateResultList - * @param Query $query QueryResults hold a reference to original query - * - * @return QueryResult - */ - public function convertToQueryResult( FederateResultList $federateResultList, Query $query ) { - - if ( $query->querymode === Query::MODE_COUNT ) { - return $this->makeQueryResultForCount( $federateResultList, $query ); - } - - return $this->makeQueryResultForInstance( $federateResultList,$query ); - } - - private function makeQueryResultForCount( FederateResultList $federateResultList, Query $query ) { - - $queryResult = new QueryResult( - $query->getDescription()->getPrintrequests(), - $query, - array(), - $this->store, - false - ); - - if ( $federateResultList->getErrorCode() === FederateResultList::ERROR_NOERROR ) { - $queryResult->setCountValue( $federateResultList->getNumericValue() ); - } else { - $queryResult->addErrors( array( wfMessage( 'smw_db_sparqlqueryproblem' )->inContentLanguage()->text() ) ); - } - - return $queryResult; - } - - private function makeQueryResultForInstance( FederateResultList $federateResultList, Query $query ) { - - $resultDataItems = array(); - - foreach ( $federateResultList as $resultRow ) { - if ( count( $resultRow ) > 0 ) { - $dataItem = Exporter::findDataItemForExpElement( $resultRow[0] ); - - if ( !is_null( $dataItem ) ) { - $resultDataItems[] = $dataItem; - } - } - } - - if ( $federateResultList->numRows() > $query->getLimit() ) { - array_pop( $resultDataItems ); - $hasFurtherResults = true; - } else { - $hasFurtherResults = false; - } - - $result = new QueryResult( - $query->getDescription()->getPrintrequests(), - $query, - $resultDataItems, - $this->store, - $hasFurtherResults - ); - - switch ( $federateResultList->getErrorCode() ) { - case FederateResultList::ERROR_NOERROR: break; - case FederateResultList::ERROR_INCOMPLETE: - $result->addErrors( array( wfMessage( 'smw_db_sparqlqueryincomplete' )->inContentLanguage()->text() ) ); - break; - default: - $result->addErrors( array( wfMessage( 'smw_db_sparqlqueryproblem' )->inContentLanguage()->text() ) ); - break; - } - - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/README.md b/SemanticMediaWiki/includes/src/SPARQLStore/README.md deleted file mode 100644 index fa45dff8..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# SPARQLStore - -The following client database connectors are currently available: - -- Default using `GenericHttpDatabaseConnector` -- [Jena Fuseki][fuseki] using `FusekiHttpDatabaseConnector` -- [Virtuoso][virtuoso] using `VirtuosoHttpDatabaseConnector` -- [4Store][4store] using `FourstoreHttpDatabaseConnector` - -## SPARQLStore integration - -The `SPARQLStore` uses two components a base store (by default using the existing `SQLStore`) and a client database connector. The base store accumulates information about properties and value annotations as well as statistics while the database connector is responsible for transforming a `#ask` query into a `SPARQL` query and requesting data from the [TDB][tdb]. - -- `#ask` query is transformed into an equivalent SPARQL condition using the `QueryConditionBuilder` -- The client database connector resolves the condition into a `SPARQL` statement and makes a query request to the database -- The client database (Fuseki etc. ) is expected to execute the query and return a list of results which are parsed using the `RawResultParser` and made available as `FederateResultList` -- The `ResultListConverter` is to convert a `FederateResultList` into a `QueryResult` object -- The `QueryResult` object will fetch all remaining data (for each printrequest ) from the base store which are to be used by a `ResultPrinter` - -## Integration testing - -Information about the testing environment and installation details can be found in the `build/travis/install-services.sh`. - -### Jena Fuseki integration - -When running integration tests with [Jena Fuseki][fuseki] it is suggested that the `in-memory` option is used to avoid potential loss of production data during test execution. - -```sh -fuseki-server --update --port=3030 --mem /db -``` - -```php -$smwgSparqlDatabaseConnector = 'Fuseki'; -$smwgSparqlQueryEndpoint = 'http://localhost:3030/db/query'; -$smwgSparqlUpdateEndpoint = 'http://localhost:3030/db/update'; -$smwgSparqlDataEndpoint = ''; -``` - -Fuseki supports [TDB Dynamic Datasets][fuseki-dataset] (in SPARQL known as [RDF dataset][sparql-dataset]) which can enbled using the following settings for testing. - -```sh -fuseki-server --update --port=3030 --memTDB --set tdb:unionDefaultGraph=true /db -``` -```php -$smwgSparqlDatabaseConnector = 'Fuseki'; -$smwgSparqlQueryEndpoint = 'http://localhost:3030/db/query'; -$smwgSparqlUpdateEndpoint = 'http://localhost:3030/db/update'; -$smwgSparqlDataEndpoint = ''; -$smwgSparqlDefaultGraph = 'http://example.org/myFusekiGraph'; -``` -### Virtuoso integration - -Virtuoso-opensource 6.1 - -```sh -sudo apt-get install virtuoso-opensource -``` - -```php -$smwgSparqlDatabaseConnector = 'Virtuoso'; -$smwgSparqlQueryEndpoint = 'http://localhost:8890/sparql'; -$smwgSparqlUpdateEndpoint = 'http://localhost:8890/sparql'; -$smwgSparqlDataEndpoint = ''; -$smwgSparqlDefaultGraph = 'http://example.org/myVirtuosoGraph'; -``` - -### 4Store integration - -Currently, Travis-CI doesn't support `4Store` (1.1.4-2) as service but the following configuration has been sucessfully tested with the available test suite. - -```sh -apt-get install 4store -``` - -```php -$smwgSparqlDatabaseConnector = '4store'; -$smwgSparqlQueryEndpoint = 'http://localhost:8088/sparql/'; -$smwgSparqlUpdateEndpoint = 'http://localhost:8088/update/'; -$smwgSparqlDataEndpoint = 'http://localhost:8088/data/'; -$smwgSparqlDefaultGraph = 'http://example.org/myFourstoreGraph'; -``` - -## Miscellaneous - -- [Large Triple Stores](http://www.w3.org/wiki/LargeTripleStores) - -[fuseki]: https://jena.apache.org/ -[fuseki-dataset]: https://jena.apache.org/documentation/tdb/dynamic_datasets.html -[sparql-dataset]: https://www.w3.org/TR/sparql11-query/#specifyingDataset -[virtuoso]: https://github.com/openlink/virtuoso-opensource -[4store]: https://github.com/garlik/4store -[tdb]: http://en.wikipedia.org/wiki/Triplestore
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/RedirectLookup.php b/SemanticMediaWiki/includes/src/SPARQLStore/RedirectLookup.php deleted file mode 100644 index a910a8ee..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/RedirectLookup.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -use SMW\DIWikiPage; - -use SMWSparqlDatabase as SparqlDatabase; -use SMWExpNsResource as ExpNsResource; -use SMWExpResource as ExpResource; -use SMWExporter as Exporter; -use SMWTurtleSerializer as TurtleSerializer; - -use RuntimeException; - -/** - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author Markus Krötzsch - * @author mwjames - */ -class RedirectLookup { - - /** - * @var SMWSparqlDatabase - */ - private $sparqlDatabase = null; - - /** - * @since 2.0 - * - * @param SparqlDatabase $sparqlDatabase - */ - public function __construct( SparqlDatabase $sparqlDatabase ) { - $this->sparqlDatabase = $sparqlDatabase; - } - - /** - * Find the redirect target of an ExpNsResource - * - * Returns an SMWExpNsResource object the input redirects to, the input - * itself if there is no redirect (or it cannot be used for making a resource - * with a prefix). - * - * @since 1.6 - * - * @param ExpNsResource $expNsResource string URI to check - * @param boolean $existsthat is set to true if $expNsResource is in the - * store; always false for blank nodes; always true for subobjects - * - * @return ExpNsResource - * @throws RuntimeException - */ - public function findRedirectTargetResource( ExpNsResource $expNsResource, &$exists ) { - - $exists = true; - - if ( $expNsResource->isBlankNode() ) { - $exists = false; - return $expNsResource; - } - - if ( ( $expNsResource->getDataItem() instanceof DIWikiPage ) && - $expNsResource->getDataItem()->getSubobjectName() !== '' ) { - return $expNsResource; - } - - $firstRow = $this->lookupResourceUriTargetFromDatabase( $expNsResource ); - - if ( $firstRow === false ) { - $exists = false; - return $expNsResource; - } - - if ( count( $firstRow ) > 1 && !is_null( $firstRow[1] ) ) { - return $this->getResourceForTargetElement( $expNsResource, $firstRow[1] ); - } - - return $expNsResource; - } - - private function lookupResourceUriTargetFromDatabase( ExpNsResource $expNsResource ) { - - $resourceUri = TurtleSerializer::getTurtleNameForExpElement( $expNsResource ); - $rediUri = TurtleSerializer::getTurtleNameForExpElement( Exporter::getSpecialPropertyResource( '_REDI' ) ); - $skeyUri = TurtleSerializer::getTurtleNameForExpElement( Exporter::getSpecialPropertyResource( '_SKEY' ) ); - - $federateResultList = $this->sparqlDatabase->select( - '*', - "$resourceUri $skeyUri ?s OPTIONAL { $resourceUri $rediUri ?r }", - array( 'LIMIT' => 1 ), - array( $expNsResource->getNamespaceId() => $expNsResource->getNamespace() ) - ); - - return $federateResultList->current(); - } - - private function getResourceForTargetElement( ExpNsResource $expNsResource, $rediTargetElement ) { - - if ( !$rediTargetElement instanceof ExpResource ) { - throw new RuntimeException( 'Expected a ExpResource instance' ); - } - - $rediTargetUri = $rediTargetElement->getUri(); - $wikiNamespace = Exporter::getNamespaceUri( 'wiki' ); - - if ( strpos( $rediTargetUri, $wikiNamespace ) === 0 ) { - return new ExpNsResource( substr( $rediTargetUri, strlen( $wikiNamespace ) ), $wikiNamespace, 'wiki' ); - } - - return $expNsResource; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/SPARQLStore.php b/SemanticMediaWiki/includes/src/SPARQLStore/SPARQLStore.php deleted file mode 100644 index 0af6de73..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/SPARQLStore.php +++ /dev/null @@ -1,395 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -use SMW\SPARQLStore\QueryEngine\QueryEngine; -use SMW\SPARQLStore\QueryEngine\QueryConditionBuilder; -use SMW\SPARQLStore\QueryEngine\ResultListConverter; - -use SMW\SemanticData; -use SMW\DIWikiPage; -use SMW\Store; -use SMW\DIProperty; - -use SMWDataItem as DataItem; -use SMWQuery as Query; -use SMWExporter as Exporter; -use SMWTurtleSerializer as TurtleSerializer; -use SMWUpdateJob; -use SMWExpNsResource as ExpNsResource; - -use Title; - -/** - * Storage access class for using SMW's SPARQL database for keeping semantic - * data. The store keeps an underlying base store running for completeness. - * This might become optional in the future. - * - * @ingroup Store - * - * @license GNU GPL v2+ - * @since 1.6 - * - * @author Markus Krötzsch - */ -class SPARQLStore extends Store { - - /** - * Class to be used as an underlying base store. This can be changed in - * LocalSettings.php (after enableSemantics()) to use another base - * store. - * - * @since 1.8 - * @var string - */ - static public $baseStoreClass = 'SMWSQLStore3'; - - /** - * Underlying store to use for basic read operations. - * - * @since 1.8 - * @var Store - */ - protected $baseStore; - - /** - * @since 1.9.2 - * @var GenericHttpDatabaseConnector - */ - protected $sparqlDatabase = null; - - /** - * @since 1.8 - * - * @param Store $baseStore - */ - public function __construct( Store $baseStore = null ) { - $this->baseStore = $baseStore; - - if ( $this->baseStore === null ) { - $this->baseStore = new self::$baseStoreClass(); - } - } - - /** - * @see Store::getSemanticData() - * @since 1.8 - */ - public function getSemanticData( DIWikiPage $subject, $filter = false ) { - return $this->baseStore->getSemanticData( $subject, $filter ); - } - - /** - * @see Store::getPropertyValues() - * @since 1.8 - */ - public function getPropertyValues( $subject, DIProperty $property, $requestoptions = null ) { - return $this->baseStore->getPropertyValues( $subject, $property, $requestoptions); - } - - /** - * @see Store::getPropertySubjects() - * @since 1.8 - */ - public function getPropertySubjects( DIProperty $property, $value, $requestoptions = null ) { - return $this->baseStore->getPropertySubjects( $property, $value, $requestoptions ); - } - - /** - * @see Store::getAllPropertySubjects() - * @since 1.8 - */ - public function getAllPropertySubjects( DIProperty $property, $requestoptions = null ) { - return $this->baseStore->getAllPropertySubjects( $property, $requestoptions ); - } - - /** - * @see Store::getProperties() - * @since 1.8 - */ - public function getProperties( DIWikiPage $subject, $requestoptions = null ) { - return $this->baseStore->getProperties( $subject, $requestoptions ); - } - - /** - * @see Store::getInProperties() - * @since 1.8 - */ - public function getInProperties( DataItem $object, $requestoptions = null ) { - return $this->baseStore->getInProperties( $object, $requestoptions ); - } - - /** - * @see Store::deleteSubject() - * @since 1.6 - */ - public function deleteSubject( Title $subject ) { - $this->doSparqlDataDelete( DIWikiPage::newFromTitle( $subject ) ); - $this->baseStore->deleteSubject( $subject ); - } - - /** - * @see Store::changeTitle() - * @since 1.6 - */ - public function changeTitle( Title $oldtitle, Title $newtitle, $pageid, $redirid = 0 ) { - $oldWikiPage = DIWikiPage::newFromTitle( $oldtitle ); - $newWikiPage = DIWikiPage::newFromTitle( $newtitle ); - $oldExpResource = Exporter::getDataItemExpElement( $oldWikiPage ); - $newExpResource = Exporter::getDataItemExpElement( $newWikiPage ); - $namespaces = array( $oldExpResource->getNamespaceId() => $oldExpResource->getNamespace() ); - $namespaces[$newExpResource->getNamespaceId()] = $newExpResource->getNamespace(); - $oldUri = TurtleSerializer::getTurtleNameForExpElement( $oldExpResource ); - $newUri = TurtleSerializer::getTurtleNameForExpElement( $newExpResource ); - - $this->baseStore->changeTitle( $oldtitle, $newtitle, $pageid, $redirid ); // do this only here, so Imported from is not moved too early - - $sparqlDatabase = $this->getSparqlDatabase(); - $sparqlDatabase->insertDelete( "?s ?p $newUri", "?s ?p $oldUri", "?s ?p $oldUri", $namespaces ); - if ( $oldtitle->getNamespace() == SMW_NS_PROPERTY ) { - $sparqlDatabase->insertDelete( "?s $newUri ?o", "?s $oldUri ?o", "?s $oldUri ?o", $namespaces ); - } - // Note that we cannot change oldUri to newUri in triple subjects, - // since some triples change due to the move. Use SMWUpdateJob. - $newUpdate = new SMWUpdateJob( $newtitle ); - $newUpdate->run(); - if ( $redirid != 0 ) { // update/create redirect page data - $oldUpdate = new SMWUpdateJob( $oldtitle ); - $oldUpdate->run(); - } - } - - /** - * Update the Sparql back-end. - * - * This method can be called independently to force an update of the Sparql - * database. In general it is suggested to use updateData to carry out a - * synchronized update of the base and Sparql store. - * - * @since 2.0 - * - * @param SemanticData $semanticData - */ - public function doSparqlDataUpdate( SemanticData $semanticData ) { - - $this->doSparqlFlatDataUpdate( $semanticData ); - - foreach( $semanticData->getSubSemanticData() as $subSemanticData ) { - $this->doSparqlFlatDataUpdate( $subSemanticData ); - } - } - - /** - * Update the Sparql back-end, without taking any subobject data into account. - * - * @param SemanticData $semanticData - */ - private function doSparqlFlatDataUpdate( SemanticData $semanticData ) { - - $turtleTriplesBuilder = new TurtleTriplesBuilder( - $semanticData, - new RedirectLookup( $this->getSparqlDatabase() ) - ); - - if ( !$turtleTriplesBuilder->hasTriplesForUpdate() ) { - return; - } - - $this->doSparqlDataDelete( $semanticData->getSubject() ); - - $this->getSparqlDatabase()->insertData( - $turtleTriplesBuilder->getTriples(), - $turtleTriplesBuilder->getPrefixes() - ); - } - - /** - * @see Store::doDataUpdate() - * @since 1.6 - */ - protected function doDataUpdate( SemanticData $semanticData ) { - $this->baseStore->doDataUpdate( $semanticData ); - $this->doSparqlDataUpdate( $semanticData ); - } - - /** - * Delete a dataitem from the Sparql back-end together with all data that is - * associated resources - * - * @since 2.0 - * - * @param DataItem $dataItem - * - * @return boolean - */ - public function doSparqlDataDelete( DataItem $dataItem ) { - - $extraNamespaces = array(); - - $expResource = Exporter::getDataItemExpElement( $dataItem ); - $resourceUri = TurtleSerializer::getTurtleNameForExpElement( $expResource ); - - if ( $expResource instanceof ExpNsResource ) { - $extraNamespaces = array( $expResource->getNamespaceId() => $expResource->getNamespace() ); - } - - $masterPageProperty = Exporter::getSpecialNsResource( 'swivt', 'masterPage' ); - $masterPagePropertyUri = TurtleSerializer::getTurtleNameForExpElement( $masterPageProperty ); - - $success = $this->getSparqlDatabase()->deleteContentByValue( $masterPagePropertyUri, $resourceUri, $extraNamespaces ); - - if ( $success ) { - return $this->getSparqlDatabase()->delete( "$resourceUri ?p ?o", "$resourceUri ?p ?o", $extraNamespaces ); - } - - return false; - } - - /** - * @see Store::getQueryResult() - * @since 1.6 - */ - public function getQueryResult( Query $query ) { - - $queryEngine = new QueryEngine( - $this->getSparqlDatabase(), - new QueryConditionBuilder(), - new ResultListConverter( $this ) - ); - - return $queryEngine - ->setIgnoreQueryErrors( $GLOBALS['smwgIgnoreQueryErrors'] ) - ->setSortingSupport( $GLOBALS['smwgQSortingSupport'] ) - ->setRandomSortingSupport( $GLOBALS['smwgQRandSortingSupport'] ) - ->getQueryResult( $query ); - } - - /** - * @see Store::getPropertiesSpecial() - * @since 1.8 - */ - public function getPropertiesSpecial( $requestoptions = null ) { - return $this->baseStore->getPropertiesSpecial( $requestoptions ); - } - - /** - * @see Store::getUnusedPropertiesSpecial() - * @since 1.8 - */ - public function getUnusedPropertiesSpecial( $requestoptions = null ) { - return $this->baseStore->getUnusedPropertiesSpecial( $requestoptions ); - } - - /** - * @see Store::getWantedPropertiesSpecial() - * @since 1.8 - */ - public function getWantedPropertiesSpecial( $requestoptions = null ) { - return $this->baseStore->getWantedPropertiesSpecial( $requestoptions ); - } - - /** - * @see Store::getStatistics() - * @since 1.8 - */ - public function getStatistics() { - return $this->baseStore->getStatistics(); - } - - /** - * @see Store::refreshConceptCache() - * @since 1.8 - */ - public function refreshConceptCache( Title $concept ) { - return $this->baseStore->refreshConceptCache( $concept ); - } - - /** - * @see Store::deleteConceptCache() - * @since 1.8 - */ - public function deleteConceptCache( $concept ) { - return $this->baseStore->deleteConceptCache( $concept ); - } - - /** - * @see Store::getConceptCacheStatus() - * @since 1.8 - */ - public function getConceptCacheStatus( $concept ) { - return $this->baseStore->getConceptCacheStatus( $concept ); - } - - /** - * @see Store::setup() - * @since 1.8 - */ - public function setup( $verbose = true ) { - $this->baseStore->setup( $verbose ); - } - - /** - * @see Store::drop() - * @since 1.6 - */ - public function drop( $verbose = true ) { - $this->baseStore->drop( $verbose ); - $this->getSparqlDatabase()->deleteAll(); - } - - /** - * @see Store::refreshData() - * @since 1.8 - */ - public function refreshData( &$index, $count, $namespaces = false, $usejobs = true ) { - return $this->baseStore->refreshData( $index, $count, $namespaces, $usejobs ); - } - - /** - * @since 1.9.2 - * - * @param GenericHttpDatabaseConnector $sparqlDatabase - */ - public function setSparqlDatabase( GenericHttpDatabaseConnector $sparqlDatabase ) { - $this->sparqlDatabase = $sparqlDatabase; - return $this; - } - - /** - * @since 2.0 - */ - public function getPropertyTables() { - return $this->baseStore->getPropertyTables(); - } - - /** - * @since 1.9.2 - * - * @return GenericHttpDatabaseConnector - */ - public function getSparqlDatabase() { - - if ( $this->sparqlDatabase === null ) { - $this->sparqlDatabase = smwfGetSparqlDatabase(); - } - - return $this->sparqlDatabase; - } - - /** - * @since 2.0 - * - * @return Database - */ - public function getDatabase() { - return $this->baseStore->getDatabase(); - } - - /** - * @since 2.0 - */ - public function clear() { - $this->baseStore->clear(); - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/SparqlDBConnectionProvider.php b/SemanticMediaWiki/includes/src/SPARQLStore/SparqlDBConnectionProvider.php deleted file mode 100644 index f1a0eb77..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/SparqlDBConnectionProvider.php +++ /dev/null @@ -1,167 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -use SMW\DBConnectionProvider; -use SMW\SPARQLStore\GenericHttpDatabaseConnector; - -use RuntimeException; - -/** - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author mwjames - */ -class SparqlDBConnectionProvider implements DBConnectionProvider { - - /** - * List of supported standard connectors - * - * @var array - */ - private $connectorIdToClass = array( - 'default' => 'SMW\SPARQLStore\GenericHttpDatabaseConnector', - 'fuseki' => 'SMW\SPARQLStore\FusekiHttpDatabaseConnector', - 'virtuoso' => 'SMW\SPARQLStore\VirtuosoHttpDatabaseConnector', - '4store' => 'SMW\SPARQLStore\FourstoreHttpDatabaseConnector', - ); - - /** - * @var SparqlDatabase - */ - private $connection = null; - - /** - * @var string|null - */ - private $connectorId = null; - - /** - * @var string|null - */ - private $defaultGraph = null; - - /** - * @var string|null - */ - private $queryEndpoint = null; - - /** - * @var string|null - */ - private $updateEndpoint = null; - - /** - * @var string|null - */ - private $dataEndpoint = null; - - /** - * @since 2.0 - * - * @param string|null $connectorId - * @param string|null $defaultGraph - * @param string|null $queryEndpoint - * @param string|null $updateEndpoint - * @param string|null $dataEndpoint - */ - public function __construct( $connectorId = null, $defaultGraph = null, $queryEndpoint = null, $updateEndpoint = null, $dataEndpoint = null ) { - $this->connectorId = $connectorId; - - if ( $this->connectorId === null ) { - $this->connectorId = $GLOBALS['smwgSparqlDatabaseConnector']; - } - - $this->defaultGraph = $defaultGraph; - $this->queryEndpoint = $queryEndpoint; - $this->updateEndpoint = $updateEndpoint; - $this->dataEndpoint = $dataEndpoint; - } - - /** - * @see DBConnectionProvider::getConnection - * - * @since 2.0 - * - * @return SparqlDatabase - * @throws RuntimeException - */ - public function getConnection() { - - if ( $this->connection === null ) { - $this->connection = $this->connectTo( strtolower( $this->connectorId ) ); - } - - return $this->connection; - } - - /** - * @see DBConnectionProvider::releaseConnection - * - * @since 2.0 - */ - public function releaseConnection() { - $this->connection = null; - } - - private function connectTo( $connectorId ) { - - $databaseConnector = $this->mapConnectorIdToClass( $connectorId ); - - if ( $this->defaultGraph === null ) { - $this->defaultGraph = $GLOBALS['smwgSparqlDefaultGraph']; - } - - if ( $this->queryEndpoint === null ) { - $this->queryEndpoint = $GLOBALS['smwgSparqlQueryEndpoint']; - } - - if ( $this->updateEndpoint === null ) { - $this->updateEndpoint = $GLOBALS['smwgSparqlUpdateEndpoint']; - } - - if ( $this->dataEndpoint === null ) { - $this->dataEndpoint = $GLOBALS['smwgSparqlDataEndpoint']; - } - - $connection = new $databaseConnector( - $this->defaultGraph, - $this->queryEndpoint, - $this->updateEndpoint, - $this->dataEndpoint - ); - - if ( $this->isSparqlDatabase( $connection ) ) { - return $connection; - } - - throw new RuntimeException( 'Expected a SparqlDatabase instance' ); - } - - private function mapConnectorIdToClass( $connectorId ) { - - $databaseConnector = $this->connectorIdToClass[ 'default' ]; - - if ( isset( $this->connectorIdToClass[ $connectorId ] ) ) { - $databaseConnector = $this->connectorIdToClass[ $connectorId ]; - } - - if ( $connectorId === 'custom' ) { - $databaseConnector = $GLOBALS['smwgSparqlDatabase']; - } - - if ( !class_exists( $databaseConnector ) ) { - throw new RuntimeException( "{$databaseConnector} is not available" ); - } - - return $databaseConnector; - } - - private function isSparqlDatabase( $connection ) { - return $connection instanceof GenericHttpDatabaseConnector; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/TurtleTriplesBuilder.php b/SemanticMediaWiki/includes/src/SPARQLStore/TurtleTriplesBuilder.php deleted file mode 100644 index c58cf26d..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/TurtleTriplesBuilder.php +++ /dev/null @@ -1,281 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -use SMW\SemanticData; -use SMW\DIWikiPage; - -use SMWTurtleSerializer as TurtleSerializer; -use SMWExporter; -use SMWExpElement; -use SMWExpData; -use SMWExpResource; -use SMWExpNsResource; - -/** - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author Markus Krötzsch - * @author mwjames - */ -class TurtleTriplesBuilder { - - /** - * @var SemanticData - */ - private $semanticData = null; - - /** - * @var RedirectLookup - */ - private $redirectLookup = null; - - /** - * @var null|string - */ - private $triples = null; - - /** - * @var null|array - */ - private $prefixes = null; - - /** - * @var null|boolean - */ - private $hasTriplesForUpdate = null; - - /** - * @since 2.0 - * - * @param SemanticData $semanticData - * @param RedirectLookup $redirectLookup - */ - public function __construct( SemanticData $semanticData, RedirectLookup $redirectLookup ) { - $this->semanticData = $semanticData; - $this->redirectLookup = $redirectLookup; - } - - /** - * @since 2.0 - * - * @return TurtleTriplesBuilder - */ - public function doBuild() { - return $this->serializeToTurtleRepresentation(); - } - - /** - * @since 2.0 - * - * @return string - */ - public function getTriples() { - - if ( $this->triples === null ) { - $this->doBuild(); - } - - return $this->triples; - } - - /** - * @since 2.0 - * - * @return array - */ - public function getPrefixes() { - - if ( $this->prefixes === null ) { - $this->doBuild(); - } - - return $this->prefixes; - } - - /** - * @since 2.0 - * - * @return boolean - */ - public function hasTriplesForUpdate() { - - if ( $this->hasTriplesForUpdate === null ) { - $this->doBuild(); - } - - return $this->hasTriplesForUpdate; - } - - private function serializeToTurtleRepresentation() { - - $this->hasTriplesForUpdate = false; - $this->triples = ''; - $this->prefixes = array(); - - $expDataArray = $this->prepareUpdateExpData( $this->semanticData ); - - if ( count( $expDataArray ) > 0 ) { - - $this->hasTriplesForUpdate = true; - - $turtleSerializer = new TurtleSerializer( true ); - $turtleSerializer->startSerialization(); - - foreach ( $expDataArray as $expData ) { - $turtleSerializer->serializeExpData( $expData ); - } - - $turtleSerializer->finishSerialization(); - - $this->triples = $turtleSerializer->flushContent(); - $this->prefixes = $turtleSerializer->flushSparqlPrefixes(); - } - - return $this; - } - - /** - * Prepare an array of SMWExpData elements that should be written to - * the SPARQL store. The result is empty if no updates should be done. - * Note that this is different from writing an SMWExpData element that - * has no content. - * Otherwise, the first SMWExpData object in the array is a translation - * of the given input data, but with redirects resolved. Further - * SMWExpData objects might be included in the resulting list to - * capture necessary stub declarations for objects that do not have - * any data in the RDF store yet. - * - * @since 1.6 - * - * @param SemanticData $semanticData - * - * @return array of SMWExpData - */ - private function prepareUpdateExpData( SemanticData $semanticData ) { - - $result = array(); - - $expData = SMWExporter::makeExportData( $semanticData ); - $newExpData = $this->expandUpdateExpData( $expData, $result, false ); - array_unshift( $result, $newExpData ); - - return $result; - } - - /** - * Find a normalized representation of the given SMWExpElement that can - * be used in an update of the stored data. Normalization uses - * redirects. The type of the ExpElement might change, especially into - * SMWExpData in order to store auxiliary properties. - * Moreover, the method records any auxiliary data that should be - * written to the store when including this SMWExpElement into updates. - * This auxiliary data is collected in a call-by-ref array. - * - * @since 1.6 - * - * @param $expElement SMWExpElement object containing the update data - * @param $auxiliaryExpData array of SMWExpData - * - * @return SMWExpElement - */ - private function expandUpdateExpElement( SMWExpElement $expElement, array &$auxiliaryExpData ) { - - if ( $expElement instanceof SMWExpResource ) { - return $this->expandUpdateExpResource( $expElement, $auxiliaryExpData ); - } - - if ( $expElement instanceof SMWExpData ) { - return $this->expandUpdateExpData( $expElement, $auxiliaryExpData, true ); - } - - return $expElement; - } - - /** - * Find a normalized representation of the given SMWExpResource that can - * be used in an update of the stored data. Normalization uses - * redirects. The type of the ExpElement might change, especially into - * SMWExpData in order to store auxiliary properties. - * Moreover, the method records any auxiliary data that should be - * written to the store when including this SMWExpElement into updates. - * This auxiliary data is collected in a call-by-ref array. - * - * @since 1.6 - * - * @param $expResource SMWExpResource object containing the update data - * @param $auxiliaryExpData array of SMWExpData - * - * @return SMWExpElement - */ - private function expandUpdateExpResource( SMWExpResource $expResource, array &$auxiliaryExpData ) { - - $exists = true; - - if ( $expResource instanceof SMWExpNsResource ) { - $elementTarget = $this->redirectLookup->findRedirectTargetResource( $expResource, $exists ); - } else { - $elementTarget = $expResource; - } - - if ( !$exists && ( $elementTarget->getDataItem() instanceof DIWikiPage ) ) { - - $diWikiPage = $elementTarget->getDataItem(); - $hash = $diWikiPage->getHash(); - - if ( !array_key_exists( $hash, $auxiliaryExpData ) ) { - $auxiliaryExpData[$hash] = SMWExporter::makeExportDataForSubject( $diWikiPage, null, true ); - } - } - - return $elementTarget; - } - - /** - * Find a normalized representation of the given SMWExpData that can - * be used in an update of the stored data. Normalization uses - * redirects. - * Moreover, the method records any auxiliary data that should be - * written to the store when including this SMWExpElement into updates. - * This auxiliary data is collected in a call-by-ref array. - * - * @since 1.6 - * @param $expData SMWExpData object containing the update data - * @param $auxiliaryExpData array of SMWExpData - * @param $expandSubject boolean controls if redirects/auxiliary data should also be sought for subject - * @return SMWExpData - */ - private function expandUpdateExpData( SMWExpData $expData, array &$auxiliaryExpData, $expandSubject ) { - - $subjectExpResource = $expData->getSubject(); - - if ( $expandSubject ) { - - $expandedExpElement = $this->expandUpdateExpElement( $subjectExpResource, $auxiliaryExpData ); - - if ( $expandedExpElement instanceof SMWExpData ) { - $newExpData = $expandedExpElement; - } else { // instanceof SMWExpResource - $newExpData = new SMWExpData( $subjectExpResource ); - } - } else { - $newExpData = new SMWExpData( $subjectExpResource ); - } - - foreach ( $expData->getProperties() as $propertyResource ) { - - $propertyTarget = $this->expandUpdateExpElement( $propertyResource, $auxiliaryExpData ); - - foreach ( $expData->getValues( $propertyResource ) as $expElement ) { - $elementTarget = $this->expandUpdateExpElement( $expElement, $auxiliaryExpData ); - $newExpData->addPropertyObjectValue( $propertyTarget, $elementTarget ); - } - } - - return $newExpData; - } - -} diff --git a/SemanticMediaWiki/includes/src/SPARQLStore/VirtuosoHttpDatabaseConnector.php b/SemanticMediaWiki/includes/src/SPARQLStore/VirtuosoHttpDatabaseConnector.php deleted file mode 100644 index ba5d7f52..00000000 --- a/SemanticMediaWiki/includes/src/SPARQLStore/VirtuosoHttpDatabaseConnector.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php - -namespace SMW\SPARQLStore; - -/** - * Virtuoso specific adjustments for GenericHttpDatabaseConnector - * - * Specific modifications of the SPARQL database implementation for Virtuoso. - * In particular, Virtuoso does not support SPARQL Update but only the non-standard - * SPARUL protocol that requires different syntax for update queries. - * If future versions of Virtuoso support SPARQL Update, the standard SPARQL - * database connector should work properly. - * - * Virtuoso uses the SPARQL query endpoint for updates as well. So both - * $smwgSparqlUpdateEndpoint and $smwgSparqlQueryEndpoint should be something - * like 'http://localhost:8890/sparql/'. $smwgSparqlDataEndpoint should be - * left empty. - * - * A graph is always needed, i.e., $smwgSparqlDefaultGraph must be set to some - * graph name (URI). - * - * Known limitations: - * (might be fixed in recent Virtuoso versions, please let us know) - * - * - Data endpoint not tested: $smwgSparqlDataEndpoint should be left empty - * - Numerical datatypes are not supported properly, and Virtuoso - * will miss query results when query conditions require number values. - * This also affects Type:Date properties since the use numerical values for - * querying. - * - Some edit (insert) queries fail for unknown reasons, probably related to - * unusual/complex input data (e.g., using special characters in strings); - * errors will occur when trying to store such values on a page. - * - Virtuoso stumbles over XSD dates with negative years, even if they have - * only four digits as per ISO. Trying to store such data will cause errors. - * - * @ingroup Sparql - * - * @license GNU GPL v2+ - * @since 1.7.1 - * - * @author Markus Krötzsch - */ -class VirtuosoHttpDatabaseConnector extends GenericHttpDatabaseConnector { - - /** - * DELETE wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $deletePattern string CONSTRUCT pattern of tripples to delete - * @param $where string condition for data to delete - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * @return boolean stating whether the operations succeeded - */ - public function delete( $deletePattern, $where, $extraNamespaces = array() ) { - - $sparql = self::getPrefixString( $extraNamespaces ) . "DELETE" . - ( ( $this->m_defaultGraph !== '' )? " FROM <{$this->m_defaultGraph}> " : '' ) . - "{ $deletePattern } WHERE { $where }"; - - return $this->doUpdate( $sparql ); - } - - /** - * INSERT DELETE wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $insertPattern string CONSTRUCT pattern of tripples to insert - * @param $deletePattern string CONSTRUCT pattern of tripples to delete - * @param $where string condition for data to delete - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * @return boolean stating whether the operations succeeded - */ - public function insertDelete( $insertPattern, $deletePattern, $where, $extraNamespaces = array() ) { - - $sparql = self::getPrefixString( $extraNamespaces ) . "MODIFY" . - ( ( $this->m_defaultGraph !== '' )? " GRAPH <{$this->m_defaultGraph}> " : '' ) . - "DELETE { $deletePattern } INSERT { $insertPattern } WHERE { $where }"; - - return $this->doUpdate( $sparql ); - } - - /** - * INSERT DATA wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $triples string of triples to insert - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * @return boolean stating whether the operations succeeded - */ - public function insertData( $triples, $extraNamespaces = array() ) { - - if ( $this->m_dataEndpoint !== '' ) { - $turtle = self::getPrefixString( $extraNamespaces, false ) . $triples; - return $this->doHttpPost( $turtle ); - } - - $sparql = self::getPrefixString( $extraNamespaces, true ) . - "INSERT DATA " . - ( ( $this->m_defaultGraph !== '' )? "INTO GRAPH <{$this->m_defaultGraph}> " : '' ) . - "{ $triples }"; - - return $this->doUpdate( $sparql ); - } - - /** - * DELETE DATA wrapper. - * The function declares the standard namespaces wiki, swivt, rdf, owl, - * rdfs, property, xsd, so these do not have to be included in - * $extraNamespaces. - * - * @param $triples string of triples to delete - * @param $extraNamespaces array (associative) of namespaceId => namespaceUri - * @return boolean stating whether the operations succeeded - */ - public function deleteData( $triples, $extraNamespaces = array() ) { - - $sparql = self::getPrefixString( $extraNamespaces ) . - "DELETE DATA " . - ( ( $this->m_defaultGraph !== '' )? "FROM GRAPH <{$this->m_defaultGraph}> " : '' ) . - "{ $triples }"; - - return $this->doUpdate( $sparql ); - } - - /** - * Execute a SPARQL update and return a boolean to indicate if the - * operations was successful. - * - * Virtuoso expects SPARQL updates to be posted using the "query" - * parameter (rather than "update"). - * - * @param $sparql string with the complete SPARQL update query (INSERT or DELETE) - * @return boolean - */ - public function doUpdate( $sparql ) { - - if ( $this->m_updateEndpoint === '' ) { - throw new BadHttpDatabaseResponseException( BadHttpDatabaseResponseException::ERROR_NOSERVICE, $sparql, 'not specified' ); - } - - $this->httpRequest->setOption( CURLOPT_URL, $this->m_updateEndpoint ); - $this->httpRequest->setOption( CURLOPT_POST, true ); - - $parameterString = "query=" . urlencode( $sparql ); - - $this->httpRequest->setOption( CURLOPT_POSTFIELDS, $parameterString ); - $this->httpRequest->execute(); - - if ( $this->httpRequest->getLastErrorCode() == 0 ) { - return true; - } - - $this->mapHttpRequestError( $this->m_updateEndpoint, $sparql ); - return false; - } - -} - diff --git a/SemanticMediaWiki/includes/src/Store/Maintenance/ConceptCacheRebuilder.php b/SemanticMediaWiki/includes/src/Store/Maintenance/ConceptCacheRebuilder.php deleted file mode 100644 index 5f5ce172..00000000 --- a/SemanticMediaWiki/includes/src/Store/Maintenance/ConceptCacheRebuilder.php +++ /dev/null @@ -1,263 +0,0 @@ -<?php - -namespace SMW\Store\Maintenance; - -use SMW\MediaWiki\TitleLookup; -use SMW\Reporter\MessageReporter; -use SMW\Reporter\NullMessageReporter; - -use SMW\Settings; -use SMW\Store; -use SMW\DIConcept; - -use Title; - -/** - * Is part of the `rebuildConceptCache.php` maintenance script to rebuild - * cache entries for selected concepts - * - * @note This is an internal class and should not be used outside of smw-core - * - * @ingroup SMW - * - * @license GNU GPL v2+ - * @since 1.9.2 - * - * @author mwjames - */ -class ConceptCacheRebuilder { - - /** @var MessageReporter */ - protected $reporter; - - /** @var Store */ - protected $store; - - /** @var Settings */ - protected $settings; - - protected $concept = null; - protected $action = null; - protected $options = array(); - protected $startId = 0; - protected $endId = 0; - protected $lines = 0; - protected $verbose = false; - - /** - * @since 1.9.2 - * - * @param Store $store - * @param Settings $settings - * @param MessageReporter|null $reporter - */ - public function __construct( Store $store, Settings $settings, MessageReporter $reporter = null ) { - $this->store = $store; - $this->settings = $settings; - $this->reporter = $reporter; - - if ( $this->reporter === null ) { - $this->reporter = new NullMessageReporter(); - } - } - - /** - * @since 1.9.2 - * - * @param array $parameters - */ - public function setParameters( array $parameters ) { - - $options = array( 'hard', 'update', 'old', 'quiet', 'status', 'verbose' ); - - foreach ( $options as $option ) { - if ( isset( $parameters[$option] ) ) { - $this->options[$option] = $parameters[$option]; - } - } - - if ( isset( $parameters['concept'] ) ) { - $this->concept = $parameters['concept']; - } - - if ( isset( $parameters['s'] ) ) { - $this->startId = intval( $parameters['s'] ); - } - - if ( isset( $parameters['e'] ) ) { - $this->endId = intval( $parameters['e'] ); - } - - $actions = array( 'status', 'create', 'delete' ); - - foreach ( $actions as $action ) { - if ( isset( $parameters[$action] ) && $this->action === null ) { - $this->action = $action; - } - } - - $this->verbose = array_key_exists( 'verbose', $parameters ); - } - - /** - * @since 1.9.2 - * - * @return boolean - */ - public function rebuild() { - - switch ( $this->action ) { - case 'status': - $this->reportMessage( "\nDisplaying concept cache status information. Use CTRL-C to abort.\n\n" ); - break; - case 'create': - $this->reportMessage( "\nCreating/updating concept caches. Use CTRL-C to abort.\n\n" ); - break; - case 'delete': - $delay = 5; - $this->reportMessage( "\nAbort with CTRL-C in the next $delay seconds ... " ); - $this->hasOption( 'quiet' ) ? '' : wfCountDown( $delay ); - $this->reportMessage( "\nDeleting concept caches.\n\n" ); - break; - default: - return false; - } - - if ( $this->hasOption( 'hard' ) ) { - - $settings = ' smwgQMaxDepth: ' . $this->settings->get( 'smwgQMaxDepth' ); - $settings .= ' smwgQMaxSize: ' . $this->settings->get( 'smwgQMaxSize' ); - $settings .= ' smwgQFeatures: ' . $this->settings->get( 'smwgQFeatures' ); - - $this->reportMessage( "Option 'hard' is parameterized by{$settings}\n\n" ); - } - - $concepts = $this->getConcepts(); - - foreach ( $concepts as $concept ) { - $this->workOnConcept( $concept ); - } - - if ( $concepts === array() ) { - $this->reportMessage( "No concept available.\n" ); - } else { - $this->reportMessage( "\nDone.\n" ); - } - - return true; - } - - protected function workOnConcept( Title $title ) { - - $concept = $this->store->getConceptCacheStatus( $title ); - - if ( $this->skipConcept( $title, $concept ) ) { - return $this->lines += $this->verbose ? 1 : 0; - } - - $result = $this->performAction( $title, $concept ); - - if ( $result ) { - $this->reportMessage( ' ' . implode( $result, "\n " ) . "\n" ); - } - - return $this->lines += 1; - } - - protected function skipConcept( $title, $concept = null ) { - - $skip = false; - - if ( $concept === null ) { - $skip = 'page not cachable (no concept description, maybe a redirect)'; - } elseif ( ( $this->hasOption( 'update' ) ) && ( $concept->getCacheStatus() !== 'full' ) ) { - $skip = 'page not cached yet'; - } elseif ( ( $this->hasOption( 'old' ) ) && ( $concept->getCacheStatus() === 'full' ) && - ( $concept->getCacheDate() > ( strtotime( 'now' ) - intval( $this->options['old'] ) * 60 ) ) ) { - $skip = 'cache is not old yet'; - } elseif ( ( $this->hasOption( 'hard' ) ) && ( $this->settings->get( 'smwgQMaxSize' ) >= $concept->getSize() ) && - ( $this->settings->get( 'smwgQMaxDepth' ) >= $concept->getDepth() && - ( ( ~( ~( $concept->getQueryFeatures() + 0 ) | $this->settings->get( 'smwgQFeatures' ) ) ) == 0 ) ) ) { - $skip = 'concept is not "hard" according to wiki settings'; - } - - if ( $skip ) { - $line = $this->lines !== false ? "($this->lines) " : ''; - $this->reportMessage( $line . 'Skipping concept "' . $title->getPrefixedText() . "\": $skip\n", $this->verbose ); - } - - return $skip; - } - - protected function performAction( Title $title, DIConcept $concept ) { - - $this->reportMessage( "($this->lines) " ); - - if ( $this->action === 'create' ) { - $this->reportMessage( 'Creating cache for "' . $title->getPrefixedText() . "\" ...\n" ); - return $this->store->refreshConceptCache( $title ); - } - - if ( $this->action === 'delete' ) { - $this->reportMessage( 'Deleting cache for "' . $title->getPrefixedText() . "\" ...\n" ); - return $this->store->deleteConceptCache( $title ); - } - - $this->reportMessage( 'Status for "' . $title->getPrefixedText() . '": ' ); - - if ( $concept->getCacheStatus() === 'full' ) { - return $this->reportMessage( 'Cache created at ' . - $this->getCacheDateInfo( $concept->getCacheDate() ) . - "{$concept->getCacheCount()} elements in cache\n" - ); - } - - $this->reportMessage( "Not cached.\n" ); - } - - protected function getConcepts() { - - if ( $this->concept !== null ) { - return array( $this->acquireSingleConcept() ); - } - - return $this->acquireMultipleConcepts(); - } - - protected function acquireSingleConcept() { - return Title::newFromText( $this->concept, SMW_NS_CONCEPT ); - } - - protected function acquireMultipleConcepts() { - - $titleLookup = new TitleLookup( $this->store->getDatabase() ); - $titleLookup->byNamespace( SMW_NS_CONCEPT ); - - if ( $this->endId == 0 && $this->startId == 0 ) { - return $titleLookup->selectAll(); - } - - $endId = $titleLookup->selectMaxId(); - - if ( $this->endId > 0 ) { - $endId = min( $this->endId, $endId ); - } - - return $titleLookup->selectByIdRange( $this->startId, $endId ); - } - - protected function hasOption( $key ) { - return isset( $this->options[$key] ); - } - - protected function reportMessage( $message, $output = true ) { - if ( $output ) { - $this->reporter->reportMessage( $message ); - } - } - - private function getCacheDateInfo( $date ) { - return date( 'Y-m-d H:i:s', $date ) . ' (' . floor( ( strtotime( 'now' ) - $date ) / 60 ) . ' minutes old), '; - } - -} diff --git a/SemanticMediaWiki/includes/src/Store/Maintenance/DataRebuilder.php b/SemanticMediaWiki/includes/src/Store/Maintenance/DataRebuilder.php deleted file mode 100644 index 00240373..00000000 --- a/SemanticMediaWiki/includes/src/Store/Maintenance/DataRebuilder.php +++ /dev/null @@ -1,353 +0,0 @@ -<?php - -namespace SMW\Store\Maintenance; - -use SMW\MediaWiki\Jobs\UpdateJob; -use SMW\MediaWiki\TitleLookup; - -use SMW\Reporter\MessageReporter; -use SMW\Reporter\NullMessageReporter; - -use SMW\Settings; -use SMW\Store; -use SMW\DIWikiPage; - -use SMWQueryProcessor; -use Title; -use LinkCache; - -/** - * Is part of the `rebuildData.php` maintenance script to rebuild existing data - * for the store - * - * @note This is an internal class and should not be used outside of smw-core - * - * @ingroup SMW - * - * @licence GNU GPL v2+ - * @since 1.9.2 - * - * @author mwjames - */ -class DataRebuilder { - - /** - * @var Store - */ - private $store; - - /** - * @var MessageReporter - */ - private $reporter; - - private $rebuildCount = 0; - - private $delay = false; - private $pages = false; - private $canWriteToIdFile = false; - private $start = 1; - private $end = false; - private $filters = false; - private $fullDelete = false; - private $verbose = false; - private $useIds = false; - private $startIdFile = false; - private $query = false; - - /** - * @since 1.9.2 - * - * @param Store $store - * @param MessageReporter|null $reporter - */ - public function __construct( Store $store, MessageReporter $reporter = null ) { - $this->store = $store; - $this->reporter = $reporter; - - if ( $this->reporter === null ) { - $this->reporter = new NullMessageReporter(); - } - } - - /** - * @since 1.9.2 - * - * @param array $parameters - */ - public function setParameters( array $options ) { - - if ( isset( $options['server'] ) ) { - $GLOBALS['wgServer'] = $options['server']; - } - - if ( array_key_exists( 'd', $options ) ) { - $this->delay = intval( $options['d'] ) * 1000; // convert milliseconds to microseconds - } - - if ( isset( $options['page'] ) ) { - $this->pages = explode( '|', $options['page'] ); - } - - if ( array_key_exists( 's', $options ) ) { - $this->start = max( 1, intval( $options['s'] ) ); - } elseif ( array_key_exists( 'startidfile', $options ) ) { - - $this->canWriteToIdFile = $this->idFileIsWritable( $options['startidfile'] ); - $this->startIdFile = $options['startidfile']; - - if ( is_readable( $options['startidfile'] ) ) { - $this->start = max( 1, intval( file_get_contents( $options['startidfile'] ) ) ); - } - } - - // Note: this might reasonably be larger than the page count - if ( array_key_exists( 'e', $options ) ) { - $this->end = intval( $options['e'] ); - } elseif ( array_key_exists( 'n', $options ) ) { - $this->end = $this->start + intval( $options['n'] ); - } - - $this->useIds = array_key_exists( 's', $options ) || array_key_exists( 'e', $options ); - - $this->verbose = array_key_exists( 'v', $options ); - - $this->filters = $this->describeFiltersFromOptions( $options ); - - if ( array_key_exists( 'f', $options ) ) { - $this->fullDelete = true; - } - - if ( array_key_exists( 'query', $options ) ) { - $this->query = $options['query']; - } - - } - - /** - * @since 1.9.2 - * - * @return boolean - */ - public function rebuild() { - - $this->reportMessage( "\nSelected storage " . get_class( $this->store ) . " for update!\n\n" ); - - if ( $this->fullDelete ) { - $this->performFullDelete(); - } - - if ( $this->pages || $this->query || $this->filters ) { - return $this->rebuildSelectedPages(); - } - - return $this->rebuildAll(); - } - - /** - * @since 1.9.2 - * - * @return int - */ - public function getRebuildCount() { - return $this->rebuildCount; - } - - protected function rebuildSelectedPages() { - - $this->reportMessage( "Refreshing specified pages!\n\n" ); - - $pages = $this->query ? $this->getPagesFromQuery() : array(); - $pages = $this->pages ? array_merge( (array)$this->pages, $pages ) : $pages; - $pages = $this->filters ? array_merge( $pages, $this->getPagesFromFilters() ) : $pages; - $numPages = count( $pages ); - - $titleCache = array(); - - foreach ( $pages as $page ) { - - $title = $this->makeTitleOf( $page ); - - if ( $title !== null && !isset( $titleCache[ $title->getPrefixedDBkey() ] ) ) { - - $this->rebuildCount++; - $percentage = round( $this->rebuildCount / $numPages * 100 ); - - $this->reportMessage( "($this->rebuildCount/$numPages $percentage%) Processing page " . $title->getPrefixedDBkey() . " ...\n", $this->verbose ); - - $updatejob = new UpdateJob( $title ); - $updatejob->run(); - - $titleCache[ $title->getPrefixedDBkey() ] = true; - } - } - - $this->reportMessage( "$this->rebuildCount pages refreshed.\n" ); - - return true; - } - - protected function rebuildAll() { - - $linkCache = LinkCache::singleton(); - - $this->reportMessage( "Refreshing all semantic data in the database!\n---\n" . - " Some versions of PHP suffer from memory leaks in long-running scripts.\n" . - " If your machine gets very slow after many pages (typically more than\n" . - " 1000) were refreshed, please abort with CTRL-C and resume this script\n" . - " at the last processed page id using the parameter -s (use -v to display\n" . - " page ids during refresh). Continue this until all pages were refreshed.\n---\n" - ); - - $this->reportMessage( "Processing all IDs from $this->start to " . ( $this->end ? "$this->end" : 'last ID' ) . " ...\n" ); - - $id = $this->start; - - while ( ( ( !$this->end ) || ( $id <= $this->end ) ) && ( $id > 0 ) ) { - - $this->rebuildCount++; - - $this->reportMessage( "($this->rebuildCount) Processing ID " . $id . " ...\n", $this->verbose ); - - $this->store->refreshData( $id, 1, false, false ); - - if ( $this->delay !== false ) { - usleep( $this->delay ); - } - - if ( $this->rebuildCount % 100 === 0 ) { // every 100 pages only - $linkCache->clear(); // avoid memory leaks - } - } - - $this->writeIdToFile( $id ); - $this->reportMessage( "$this->rebuildCount IDs refreshed.\n" ); - - return true; - } - - protected function performFullDelete() { - - $this->reportMessage( "\n Deleting all stored data completely and rebuilding it again later!\n" . - " Semantic data in the wiki might be incomplete for some time while this operation runs.\n\n" . - " NOTE: It is usually necessary to run this script ONE MORE TIME after this operation,\n" . - " since some properties' types are not stored yet in the first run.\n" . - " The first run can normally use the parameter -p to refresh only properties.\n\n" - ); - - if ( $this->useIds ) { - $this->reportMessage( " WARNING: -s or -e are used, so some pages will not be refreshed at all!\n" . - " Data for those pages will only be available again when they have been\n" . - " refreshed as well!\n\n" - ); - } - - $obLevel = ob_get_level(); - - $this->reportMessage( ' Abort with control-c in the next five seconds ... ' ); - wfCountDown( 6 ); - - $this->store->drop( $this->verbose ); - wfRunHooks( 'smwDropTables' ); - wfRunHooks( 'SMW::Store::dropTables', array( $this->verbose ) ); - - $this->store->setupStore( $this->verbose ); - - // Be sure to have some buffer, otherwise some PHPs complain - while ( ob_get_level() > $obLevel ) { - ob_end_flush(); - } - - $this->reportMessage( "\nAll storage structures have been deleted and recreated.\n\n" ); - - return true; - } - - protected function idFileIsWritable( $startIdFile ) { - - if ( !is_writable( file_exists( $startIdFile ) ? $startIdFile : dirname( $startIdFile ) ) ) { - die( "Cannot use a startidfile that we can't write to.\n" ); - } - - return true; - } - - protected function writeIdToFile( $id ) { - if ( $this->canWriteToIdFile ) { - file_put_contents( $this->startIdFile, "$id" ); - } - } - - protected function describeFiltersFromOptions( $options ) { - - $filtersarray = array(); - - if ( array_key_exists( 'c', $options ) ) { - $filtersarray[] = NS_CATEGORY; - } - - if ( array_key_exists( 'p', $options ) ) { - $filtersarray[] = SMW_NS_PROPERTY; - } - - if ( array_key_exists( 't', $options ) ) { - $filtersarray[] = SMW_NS_TYPE; - } - - return $filtersarray !== array() ? $filtersarray : false; - } - - protected function getPagesFromQuery() { - - // get number of pages and fix query limit - $query = SMWQueryProcessor::createQuery( - $this->query, - SMWQueryProcessor::getProcessedParams( array( 'format' => 'count' ) ) - ); - - $result = $this->store->getQueryResult( $query ); - - // get pages and add them to the pages explicitly listed in the 'page' parameter - $query = SMWQueryProcessor::createQuery( - $this->query, - SMWQueryProcessor::getProcessedParams( array() ) - ); - - $query->setUnboundLimit( $result instanceof \SMWQueryResult ? $result->getCountValue() : $result ); - - return $this->store->getQueryResult( $query )->getResults(); - } - - protected function getPagesFromFilters() { - - $pages = array(); - - $titleLookup = new TitleLookup( $this->store->getDatabase() ); - - foreach ( $this->filters as $namespace ) { - $pages = array_merge( $pages, $titleLookup->byNamespace( $namespace )->selectAll() ); - } - - return $pages; - } - - protected function makeTitleOf( $page ) { - - if ( $page instanceof DIWikiPage ) { - return $page->getTitle(); - } - - if ( $page instanceof Title ) { - return $page; - } - - return Title::newFromText( $page ); - } - - protected function reportMessage( $message, $output = true ) { - if ( $output ) { - $this->reporter->reportMessage( $message ); - } - } - -} diff --git a/SemanticMediaWiki/includes/storage/CacheableResultCollector.php b/SemanticMediaWiki/includes/storage/CacheableResultCollector.php deleted file mode 100644 index 33c38843..00000000 --- a/SemanticMediaWiki/includes/storage/CacheableResultCollector.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - -namespace SMW\Store; - -use SMW\CacheableResultMapper; -use SMW\ResultCollector; -use SMW\DIProperty; -use SMW\Settings; - -use SMWRequestOptions; -use InvalidArgumentException; -use MWTimestamp; - -/** - * Base class thats represents a cacheable ResultCollector - * - * @ingroup Store - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -abstract class CacheableResultCollector implements ResultCollector { - - /** @var array */ - protected $results = array(); - - /** @var SMWRequestOptions */ - protected $requestOptions = null; - - /** @var boolean */ - protected $isCached = false; - - /** @var string */ - protected $cacheDate = null; - - /** - * @see ResultCollector::getResults - * - * @since 1.9 - * - * @return array - */ - public function getResults() { - - $cacheableResult = new CacheableResultMapper( $this->cacheSetup()->set( 'prefix', 'collector' ) ); - - $results = $cacheableResult->fetchFromCache(); - - if ( $results ) { - - $this->isCached = true; - $this->results = $results; - $this->cacheDate = $cacheableResult->getCacheDate(); - wfDebug( get_called_class() . ' served from cache' . "\n" ); - - } else { - - $this->results = $this->runCollector(); - $this->isCached = false; - $cacheableResult->recache( $this->results ); - } - - return $this->results; - } - - /** - * Set request options - * - * @since 1.9 - * - * @param SMWRequestOptions $requestOptions - * - * @return CacheableResultCollector - */ - public function setRequestOptions( SMWRequestOptions $requestOptions ) { - $this->requestOptions = $requestOptions; - return $this; - } - - /** - * Returns whether or not results have been cached - * - * @since 1.9 - * - * @return boolean - */ - public function isCached() { - return $this->isCached; - } - - /** - * In case results were cached, it returns the timestamp of the cached - * results - * - * @since 1.9 - * - * @return string|null - */ - public function getCacheDate() { - return $this->cacheDate; - } - - /** - * Returns number of available results - * - * @since 1.9 - * - * @return integer - */ - public function getCount() { - return count( $this->results ); - } - - /** - * Sub-class is returning an ObjectDictionary that specifies details needed - * for the CacheableResultMapper instantiation - * - * @par Example: - * @code - * return new SimpleDictionary( array( - * 'id' => 'Foo', - * 'type' => 'FooType', - * 'enabled' => true or false, - * 'expiry' => 3600 - * ) ); - * @endcode - * - * @since 1.9 - * - * @return ObjectDictionary - */ - protected abstract function cacheSetup(); - - /** - * @codeCoverageIgnore - * @since 1.9 - * - * @param string $type - * - * @return TableDefinition - */ - protected function findPropertyTableByType( $type, $dataItemId = false ) { - - $propertyTables = $this->store->getPropertyTables(); - - if ( $dataItemId ) { - $id = $this->store->findTypeTableId( $type ); - } else { - $id = $this->store->findPropertyTableID( new DIProperty( $type ) ); - } - - return $propertyTables[$id]; - } - -} diff --git a/SemanticMediaWiki/includes/storage/PropertyStatisticsRebuilder.php b/SemanticMediaWiki/includes/storage/PropertyStatisticsRebuilder.php deleted file mode 100644 index a0844d0e..00000000 --- a/SemanticMediaWiki/includes/storage/PropertyStatisticsRebuilder.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace SMW\Store; - -/** - * Interface for PropertyStatisticsStore rebuilders. - * - * @since 1.9 - * - * @ingroup SMWStore - * - * @license GNU GPL v2 or later - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -interface PropertyStatisticsRebuilder { - - /** - * @since 1.9 - * - * @param PropertyStatisticsStore $propStatsStore - */ - public function rebuild( PropertyStatisticsStore $propStatsStore ); - -} diff --git a/SemanticMediaWiki/includes/storage/PropertyStatisticsStore.php b/SemanticMediaWiki/includes/storage/PropertyStatisticsStore.php deleted file mode 100644 index a37e33c2..00000000 --- a/SemanticMediaWiki/includes/storage/PropertyStatisticsStore.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -namespace SMW\Store; - -/** - * Interface for stores of property statistics. - * - * @since 1.9 - * - * @ingroup SMWStore - * - * @license GNU GPL v2 or later - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -interface PropertyStatisticsStore { - - /** - * Change the usage count for the property of the given ID by the given - * value. The method does nothing if the count is 0. - * - * @since 1.9 - * - * @param integer $propertyId - * @param integer $value - * - * @return boolean Success indicator - */ - public function addToUsageCount( $propertyId, $value ); - - /** - * Increase the usage counts of multiple properties. - * - * The $additions parameter should be an array with integer - * keys that are property ids, and associated integer values - * that are the amount the usage count should be increased. - * - * @since 1.9 - * - * @param array $additions - * - * @return boolean Success indicator - */ - public function addToUsageCounts( array $additions ); - - /** - * Updates an existing usage count. - * - * @since 1.9 - * - * @param integer $propertyId - * @param integer $value - * - * @return boolean Success indicator - */ - public function setUsageCount( $propertyId, $value ); - - /** - * Adds a new usage count. - * - * @since 1.9 - * - * @param integer $propertyId - * @param integer $value - * - * @return boolean Success indicator - */ - public function insertUsageCount( $propertyId, $value ); - - /** - * Returns the usage counts of the provided properties. - * - * The returned array contains integer keys which are property ids, - * with the associated values being their usage count (also integers). - * - * Properties for which no usage count is found will not have - * an entry in the result array. - * - * @since 1.9 - * - * @param array $propertyIds - * - * @return array - */ - public function getUsageCounts( array $propertyIds ); - - /** - * Deletes all rows in the table. - * - * @since 1.9 - * - * @return boolean Success indicator - */ - public function deleteAll(); - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/storage/QueryOutputFormatter.php b/SemanticMediaWiki/includes/storage/QueryOutputFormatter.php deleted file mode 100644 index b8f08e24..00000000 --- a/SemanticMediaWiki/includes/storage/QueryOutputFormatter.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -namespace SMW; - -use SMWQuery as Query; - -/** - * @ingroup Store - * - * @license GNU GPL v2+ - * @since 2.0 - * - * @author Markus Krötzsch - */ -class QueryOutputFormatter { - - /** - * Generate textual debug output that shows an arbitrary list of informative - * fields. Used for formatting query debug output. - * - * @note All strings given must be usable and safe in wiki and HTML - * contexts. - * - * @param $storeName string name of the storage backend for which this is generated - * @param $entries array of name => value of informative entries to display - * @param $query SMWQuery or null, if given add basic data about this query as well - * - * @return string - */ - public static function formatDebugOutput( $storeName, array $entries, Query $query = null ) { - - if ( $query instanceOf Query ) { - $preEntries = array(); - $preEntries['Generated Wiki-Query'] = '<pre>' . str_replace( '[', '[', $query->getDescription()->getQueryString() ) . '</pre>'; - $preEntries['Query Metrics'] = 'Query-Size:' . $query->getDescription()->getSize() . '<br />' . - 'Query-Depth:' . $query->getDescription()->getDepth(); - $entries = array_merge( $preEntries, $entries ); - - $errors = ''; - foreach ( $query->getErrors() as $error ) { - $errors .= $error . '<br />'; - } - if ( $errors === '' ) { - $errors = 'None'; - } - $entries['Errors and Warnings'] = $errors; - } - - $result = '<div style="border: 5px dotted #A1FB00; background: #FFF0BD; padding: 20px; ">' . - "<h3>Debug Output by $storeName</h3>"; - foreach ( $entries as $header => $information ) { - $result .= "<h4>$header</h4>"; - if ( $information !== '' ) { - $result .= "$information"; - } - } - - $result .= '</div>'; - - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SMW_QueryResult.php b/SemanticMediaWiki/includes/storage/SMW_QueryResult.php deleted file mode 100644 index 7d4e83de..00000000 --- a/SemanticMediaWiki/includes/storage/SMW_QueryResult.php +++ /dev/null @@ -1,359 +0,0 @@ -<?php - -use SMW\SerializerFactory; - -/** - * Objects of this class encapsulate the result of a query in SMW. They - * provide access to the query result and printed data, and to some - * relevant query parameters that were used. - * - * Standard access is provided through the iterator function getNext(), - * which returns an array ("table row") of SMWResultArray objects ("table cells"). - * It is also possible to access the set of result pages directly using - * getResults(). This is useful for printers that disregard printouts and - * only are interested in the actual list of pages. - * - * - * @file SMW_QueryResult.php - * @ingroup SMWQuery - * - * @licence GNU GPL v2 or later - * @author Markus Krötzsch - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class SMWQueryResult { - /** - * Array of SMWDIWikiPage objects that are the basis for this result - * @var SMWDIWikiPage[] - */ - protected $mResults; - - /** - * Array of SMWPrintRequest objects, indexed by their natural hash keys - * @var SMWPrintRequest[] - */ - protected $mPrintRequests; - - /** - * Are there more results than the ones given? - * @var boolean - */ - protected $mFurtherResults; - - /** - * The query object for which this is a result, must be set on create and is the source of - * data needed to create further result links. - * @var SMWQuery - */ - protected $mQuery; - - /** - * The SMWStore object used to retrieve further data on demand. - * @var SMWStore - */ - protected $mStore; - - /** - * Holds a value that belongs to a count query result - * @var integer|null - */ - private $countValue; - - /** - * Initialise the object with an array of SMWPrintRequest objects, which - * define the structure of the result "table" (one for each column). - * - * TODO: Update documentation - * - * @param SMWPrintRequest[] $printRequests - * @param SMWQuery $query - * @param SMWDIWikiPage[] $results - * @param SMWStore $store - * @param boolean $furtherRes - */ - public function __construct( array $printRequests, SMWQuery $query, array $results, SMWStore $store, $furtherRes = false ) { - $this->mResults = $results; - reset( $this->mResults ); - $this->mPrintRequests = $printRequests; - $this->mFurtherResults = $furtherRes; - $this->mQuery = $query; - $this->mStore = $store; - } - - /** - * Get the SMWStore object that this result is based on. - * - * @return SMWStore - */ - public function getStore() { - return $this->mStore; - } - - /** - * Return the next result row as an array of SMWResultArray objects, and - * advance the internal pointer. - * - * @return SMWResultArray[]|false - */ - public function getNext() { - $page = current( $this->mResults ); - next( $this->mResults ); - - if ( $page === false ) return false; - - $row = array(); - - foreach ( $this->mPrintRequests as $p ) { - $row[] = new SMWResultArray( $page, $p, $this->mStore ); - } - - return $row; - } - - /** - * Return number of available results. - * - * @return integer - */ - public function getCount() { - return count( $this->mResults ); - } - - /** - * Return an array of SMWDIWikiPage objects that make up the - * results stored in this object. - * - * @return SMWDIWikiPage[] - */ - public function getResults() { - return $this->mResults; - } - - /** - * Returns the query object of the current result set - * - * @since 1.8 - * - * @return SMWQuery - */ - public function getQuery() { - return $this->mQuery; - } - - /** - * Return the number of columns of result values that each row - * in this result set contains. - * - * @return integer - */ - public function getColumnCount() { - return count( $this->mPrintRequests ); - } - - /** - * Return array of print requests (needed for printout since they contain - * property labels). - * - * @return SMWPrintRequest[] - */ - public function getPrintRequests() { - return $this->mPrintRequests; - } - - /** - * Returns the query string defining the conditions for the entities to be - * returned. - * - * @return string - */ - public function getQueryString() { - return $this->mQuery->getQueryString(); - } - - /** - * Would there be more query results that were not shown due to a limit? - * - * @return boolean - */ - public function hasFurtherResults() { - return $this->mFurtherResults; - } - - /** - * @since 2.0 - * - * @param integer $countValue - */ - public function setCountValue( $countValue ) { - $this->countValue = (int)$countValue; - } - - /** - * @since 2.0 - * - * @return integer|null - */ - public function getCountValue() { - return $this->countValue; - } - - /** - * Return error array, possibly empty. - * - * @return array - */ - public function getErrors() { - // Just use query errors, as no errors generated in this class at the moment. - return $this->mQuery->getErrors(); - } - - /** - * Adds an array of erros. - * - * @param array $errors - */ - public function addErrors( array $errors ) { - $this->mQuery->addErrors( $errors ); - } - - /** - * Create an SMWInfolink object representing a link to further query results. - * This link can then be serialised or extended by further params first. - * The optional $caption can be used to set the caption of the link (though this - * can also be changed afterwards with SMWInfolink::setCaption()). If empty, the - * message 'smw_iq_moreresults' is used as a caption. - * - * @deprecated since SMW 1.8 - * - * @param string|false $caption - * - * @return SMWInfolink - */ - public function getQueryLink( $caption = false ) { - $link = $this->getLink(); - - if ( $caption == false ) { - // The space is right here, not in the QPs! - $caption = ' ' . wfMessage( 'smw_iq_moreresults' )->inContentLanguage()->text(); - } - - $link->setCaption( $caption ); - - $params = array( trim( $this->mQuery->getQueryString() ) ); - - foreach ( $this->mQuery->getExtraPrintouts() as /* SMWPrintRequest */ $printout ) { - $serialization = $printout->getSerialisation(); - - // TODO: this is a hack to get rid of the mainlabel param in case it was automatically added - // by SMWQueryProcessor::addThisPrintout. Should be done nicer when this link creation gets redone. - if ( $serialization !== '?#' ) { - $params[] = $serialization; - } - } - - if ( $this->mQuery->getMainLabel() !== false ) { - $params['mainlabel'] = $this->mQuery->getMainLabel(); - } - - $params['offset'] = $this->mQuery->getOffset() + count( $this->mResults ); - - if ( $params['offset'] === 0 ) { - unset( $params['offset'] ); - } - - if ( $this->mQuery->getLimit() > 0 ) { - $params['limit'] = $this->mQuery->getLimit(); - } - - if ( count( $this->mQuery->sortkeys ) > 0 ) { - $order = implode( ',', $this->mQuery->sortkeys ); - $sort = implode( ',', array_keys( $this->mQuery->sortkeys ) ); - - if ( $sort !== '' || $order != 'ASC' ) { - $params['order'] = $order; - $params['sort'] = $sort; - } - } - - foreach ( $params as $key => $param ) { - $link->setParameter( $param, is_string( $key ) ? $key : false ); - } - - return $link; - } - - /** - * Returns an SMWInfolink object with the QueryResults print requests as parameters. - * - * @since 1.8 - * - * @return SMWInfolink - */ - public function getLink() { - $params = array( trim( $this->mQuery->getQueryString() ) ); - - foreach ( $this->mQuery->getExtraPrintouts() as $printout ) { - $serialization = $printout->getSerialisation(); - - // TODO: this is a hack to get rid of the mainlabel param in case it was automatically added - // by SMWQueryProcessor::addThisPrintout. Should be done nicer when this link creation gets redone. - if ( $serialization !== '?#' ) { - $params[] = $serialization; - } - } - - // Note: the initial : prevents SMW from reparsing :: in the query string. - return SMWInfolink::newInternalLink( '', ':Special:Ask', false, $params ); - } - - /** - * @see DISerializer::getSerializedQueryResult - * @since 1.7 - * @return array - */ - public function serializeToArray() { - return SerializerFactory::serialize( $this ); - } - - /** - * Returns a serialized SMWQueryResult object with additional meta data - * - * This methods extends the serializeToArray() for additional meta - * that are useful when handling data via the api - * - * @note should be used instead of SMWQueryResult::serializeToArray() - * as this method contains additional informaion - * - * @since 1.9 - * - * @return array - */ - public function toArray() { - - // @note micro optimization: We call getSerializedQueryResult() - // only once and create the hash here instead of calling getHash() - // to avoid getSerializedQueryResult() being called again - // @note count + offset equals total therefore we deploy both values - $serializeArray = $this->serializeToArray(); - - return array_merge( $serializeArray, array( - 'meta'=> array( - 'hash' => md5( FormatJson::encode( $serializeArray ) ), - 'count' => $this->getCount(), - 'offset' => $this->mQuery->getOffset() - ) - ) - ); - } - - /** - * Returns result hash value - * - * @since 1.9 - * - * @return string - */ - public function getHash() { - return md5( FormatJson::encode( $this->serializeToArray() ) ); - } -} diff --git a/SemanticMediaWiki/includes/storage/SMW_RequestOptions.php b/SemanticMediaWiki/includes/storage/SMW_RequestOptions.php deleted file mode 100644 index 616000ab..00000000 --- a/SemanticMediaWiki/includes/storage/SMW_RequestOptions.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -/** - * Container object for various options that can be used when retrieving - * data from the store. These options are mostly relevant for simple, - * direct requests -- inline queries may require more complex options due - * to their more complex structure. - * Options that should not be used or where default values should be used - * can be left as initialised. - * - * @ingroup SMWStore - * - * @author Markus Krötzsch - */ -class SMWRequestOptions { - - /** - * The maximum number of results that should be returned. - */ - public $limit = -1; - - /** - * A numerical offset. The first $offset results are skipped. - * Note that this does not imply a defined order of results - * (see SMWRequestOptions->$sort below). - */ - public $offset = 0; - - /** - * Should the result be ordered? The employed order is defined - * by the type of result that are requested: wiki pages and strings - * are ordered alphabetically, whereas other data is ordered - * numerically. Usually, the order should be fairly "natural". - */ - public $sort = false; - - /** - * If SMWRequestOptions->$sort is true, this parameter defines whether - * the results are ordered in ascending or descending order. - */ - public $ascending = true; - - /** - * Specifies a lower or upper bound for the values returned by the query. - * Whether it is lower or upper is specified by the parameter "ascending" - * (true->lower, false->upper). - */ - public $boundary = null; - - /** - * Specifies whether or not the requested boundary should be returned - * as a result. - */ - public $include_boundary = true; - - /** - * An array of string conditions that are applied if the result has a - * string label that can be subject to those patterns. - */ - private $stringcond = array(); - - /** - * Set a new string condition applied to labels of results (if available). - * - * @param $string string to match - * @param $condition integer type of condition, one of STRCOND_PRE, STRCOND_POST, STRCOND_MID - */ - public function addStringCondition( $string, $condition ) { - $this->stringcond[] = new SMWStringCondition( $string, $condition ); - } - - /** - * Return the specified array of SMWStringCondition objects. - */ - public function getStringConditions() { - return $this->stringcond; - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/storage/SMW_ResultArray.php b/SemanticMediaWiki/includes/storage/SMW_ResultArray.php deleted file mode 100644 index 42ed4e2e..00000000 --- a/SemanticMediaWiki/includes/storage/SMW_ResultArray.php +++ /dev/null @@ -1,304 +0,0 @@ -<?php - -/** - * Container for the contents of a single result field of a query result, - * i.e. basically an array of SMWDataItems with some additional parameters. - * The content of the array is fetched on demand only. - * - * @file SMW_ResultArray.php - * @ingroup SMWQuery - * - * @author Markus Krötzsch - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class SMWResultArray { - - /** - * @var SMWPrintRequest - */ - protected $mPrintRequest; - - /** - * @var SMWDIWikiPage - */ - protected $mResult; - - /** - * @var SMWStore - */ - protected $mStore; - - /** - * @var array of SMWDataItem or false - */ - protected $mContent; - - static protected $catCacheObj = false; - static protected $catCache = false; - - /** - * Constructor. - * - * @param SMWDIWikiPage $resultPage - * @param SMWPrintRequest $printRequest - * @param SMWStore $store - */ - public function __construct( SMWDIWikiPage $resultPage, SMWPrintRequest $printRequest, SMWStore $store ) { - $this->mResult = $resultPage; - $this->mPrintRequest = $printRequest; - $this->mStore = $store; - $this->mContent = false; - } - - /** - * Get the SMWStore object that this result is based on. - * - * @return SMWStore - */ - public function getStore() { - return $this->mStore; - } - - /** - * Returns the SMWDIWikiPage object to which this SMWResultArray refers. - * If you only care for those objects, consider using SMWQueryResult::getResults() - * directly. - * - * @return SMWDIWikiPage - */ - public function getResultSubject() { - return $this->mResult; - } - - /** - * Returns an array of SMWDataItem objects that contain the results of - * the given print request for the given result object. - * - * @return array of SMWDataItem or false - */ - public function getContent() { - $this->loadContent(); - return $this->mContent; - } - - /** - * Return an SMWPrintRequest object describing what is contained in this - * result set. - * - * @return SMWPrintRequest - */ - public function getPrintRequest() { - return $this->mPrintRequest; - } - - /** - * Compatibility alias for getNextDatItem(). - * @deprecated since 1.6. Call getNextDataValue() or getNextDataItem() directly as needed. Method will vanish before SMW 1.7. - */ - public function getNextObject() { - return $this->getNextDataValue(); - } - - /** - * Return the next SMWDataItem object or false if no further object exists. - * - * @since 1.6 - * - * @return SMWDataItem or false - */ - public function getNextDataItem() { - $this->loadContent(); - $result = current( $this->mContent ); - next( $this->mContent ); - return $result; - } - - /** - * Set the internal pointer of the array of SMWDataItem objects to its first - * element. Return the first SMWDataItem object or false if the array is - * empty. - * - * @since 1.7.1 - * - * @return SMWDataItem or false - */ - public function reset() { - $this->loadContent(); - return reset( $this->mContent ); - } - - /** - * Return an SMWDataValue object for the next SMWDataItem object or - * false if no further object exists. - * - * @since 1.6 - * - * @return SMWDataValue or false - */ - public function getNextDataValue() { - $di = $this->getNextDataItem(); - if ( $di === false ) { - return false; - } - if ( $this->mPrintRequest->getMode() == SMWPrintRequest::PRINT_PROP && - $this->mPrintRequest->getTypeID() == '_rec' && - $this->mPrintRequest->getParameter( 'index' ) !== false ) { - // Not efficient, but correct: we need to find the right property for - // the selected index of the record here. - $pos = $this->mPrintRequest->getParameter( 'index' ) - 1; - $recordValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $di, - $this->mPrintRequest->getData()->getDataItem() ); - $diProperties = $recordValue->getPropertyDataItems(); - - if ( array_key_exists( $pos, $diProperties ) && - !is_null( $diProperties[$pos] ) ) { - $diProperty = $diProperties[$pos]; - } else { - $diProperty = null; - } - } elseif ( $this->mPrintRequest->getMode() == SMWPrintRequest::PRINT_PROP ) { - $diProperty = $this->mPrintRequest->getData()->getDataItem(); - } else { - $diProperty = null; - } - $dv = \SMW\DataValueFactory::getInstance()->newDataItemValue( $di, $diProperty ); - if ( $this->mPrintRequest->getOutputFormat() ) { - $dv->setOutputFormat( $this->mPrintRequest->getOutputFormat() ); - } - return $dv; - } - - /** - * Return the main text representation of the next SMWDataItem object - * in the specified format, or false if no further object exists. - * - * The parameter $linker controls linking of title values and should - * be some Linker object (or NULL for no linking). - * - * @param integer $outputMode - * @param mixed $linker - * - * @return string or false - */ - public function getNextText( $outputMode, $linker = null ) { - $dataValue = $this->getNextDataValue(); - if ( $dataValue !== false ) { // Print data values. - return $dataValue->getShortText( $outputMode, $linker ); - } else { - return false; - } - } - - /** - * Load results of the given print request and result subject. This is only - * done when needed. - */ - protected function loadContent() { - if ( $this->mContent !== false ) return; - - wfProfileIn( 'SMWQueryResult::loadContent (SMW)' ); - - switch ( $this->mPrintRequest->getMode() ) { - case SMWPrintRequest::PRINT_THIS: // NOTE: The limit is ignored here. - $this->mContent = array( $this->mResult ); - break; - case SMWPrintRequest::PRINT_CATS: - // Always recompute cache here to ensure output format is respected. - self::$catCache = $this->mStore->getPropertyValues( $this->mResult, - new SMWDIProperty( '_INST' ), $this->getRequestOptions( false ) ); - self::$catCacheObj = $this->mResult->getHash(); - - $limit = $this->mPrintRequest->getParameter( 'limit' ); - $this->mContent = ( $limit === false ) ? ( self::$catCache ) : - array_slice( self::$catCache, 0, $limit ); - break; - case SMWPrintRequest::PRINT_PROP: - $propertyValue = $this->mPrintRequest->getData(); - if ( $propertyValue->isValid() ) { - $this->mContent = $this->mStore->getPropertyValues( $this->mResult, - $propertyValue->getDataItem(), $this->getRequestOptions() ); - } else { - $this->mContent = array(); - } - - // Print one component of a multi-valued string. - // Known limitation: the printrequest still is of type _rec, so if printers check - // for this then they will not recognize that it returns some more concrete type. - if ( ( $this->mPrintRequest->getTypeID() == '_rec' ) && - ( $this->mPrintRequest->getParameter( 'index' ) !== false ) ) { - $pos = $this->mPrintRequest->getParameter( 'index' ) - 1; - $newcontent = array(); - - foreach ( $this->mContent as $diContainer ) { - /* SMWRecordValue */ $recordValue = \SMW\DataValueFactory::getInstance()->newDataItemValue( $diContainer, $propertyValue->getDataItem() ); - $dataItems = $recordValue->getDataItems(); - - if ( array_key_exists( $pos, $dataItems ) && - ( !is_null( $dataItems[$pos] ) ) ) { - $newcontent[] = $dataItems[$pos]; - } - } - - $this->mContent = $newcontent; - } - break; - case SMWPrintRequest::PRINT_CCAT: ///NOTE: The limit is ignored here. - if ( self::$catCacheObj != $this->mResult->getHash() ) { - self::$catCache = $this->mStore->getPropertyValues( $this->mResult, new SMWDIProperty( '_INST' ) ); - self::$catCacheObj = $this->mResult->getHash(); - } - - $found = false; - $prkey = $this->mPrintRequest->getData()->getDBkey(); - - foreach ( self::$catCache as $cat ) { - if ( $cat->getDBkey() == $prkey ) { - $found = true; - break; - } - } - $this->mContent = array( new SMWDIBoolean( $found ) ); - break; - default: $this->mContent = array(); // Unknown print request. - } - - reset( $this->mContent ); - - wfProfileOut( 'SMWQueryResult::loadContent (SMW)' ); - } - - /** - * Make a request option object based on the given parameters, and - * return NULL if no such object is required. The parameter defines - * if the limit should be taken into account, which is not always desired - * (especially if results are to be cached for future use). - * - * @param boolean $useLimit - * - * @return SMWRequestOptions or null - */ - protected function getRequestOptions( $useLimit = true ) { - $limit = $useLimit ? $this->mPrintRequest->getParameter( 'limit' ) : false; - $order = trim( $this->mPrintRequest->getParameter( 'order' ) ); - - // Important: use "!=" for order, since trim() above does never return "false", use "!==" for limit since "0" is meaningful here. - if ( ( $limit !== false ) || ( $order != false ) ) { - $options = new SMWRequestOptions(); - - if ( $limit !== false ) $options->limit = trim( $limit ); - - if ( ( $order == 'descending' ) || ( $order == 'reverse' ) || ( $order == 'desc' ) ) { - $options->sort = true; - $options->ascending = false; - } elseif ( ( $order == 'ascending' ) || ( $order == 'asc' ) ) { - $options->sort = true; - $options->ascending = true; - } - } else { - $options = null; - } - - return $options; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SMW_SQLHelpers.php b/SemanticMediaWiki/includes/storage/SMW_SQLHelpers.php deleted file mode 100644 index dfe6a34c..00000000 --- a/SemanticMediaWiki/includes/storage/SMW_SQLHelpers.php +++ /dev/null @@ -1,521 +0,0 @@ -<?php - -/** - * Some static helper functions that SMW uses for setting up - * SQL databases. - * - * @author Markus Krötzsch - * @author Marcel Gsteiger - * @author Jeroen De Dauw - * - * @file SMW_SQLHelpers.php - * @ingroup SMWStore - */ -class SMWSQLHelpers { - - /** - * Database backends often have different types that need to be used - * repeatedly in (Semantic) MediaWiki. This function provides the - * preferred type (as a string) for various common kinds of columns. - * The input is one of the following strings: 'id' (page id numbers or - * similar), 'title' (title strings or similar), 'namespace' (namespace - * numbers), 'blob' (longer text blobs), 'iw' (interwiki prefixes). - * - * @param string $input - * @return string|false SQL type declaration - */ - static public function getStandardDBType( $input ) { - global $wgDBtype; - - switch ( $input ) { - case 'id': return $wgDBtype == 'postgres' ? 'SERIAL' : ($wgDBtype == 'sqlite' ? 'INTEGER' :'INT(8) UNSIGNED'); // like page_id in MW page table - case 'namespace': return $wgDBtype == 'postgres' ? 'BIGINT' : 'INT(11)'; // like page_namespace in MW page table - case 'title': return $wgDBtype == 'postgres' ? 'TEXT' : 'VARBINARY(255)'; // like page_title in MW page table - case 'iw': return ($wgDBtype == 'postgres' || $wgDBtype == 'sqlite') ? 'TEXT' : 'VARCHAR(32) binary'; // like iw_prefix in MW interwiki table - case 'blob': return $wgDBtype == 'postgres' ? 'BYTEA' : 'MEDIUMBLOB'; // larger blobs of character data, usually not subject to SELECT conditions - } - - return false; - } - - /** - * Generic creation and updating function for database tables. Ideally, it - * would be able to modify a table's signature in arbitrary ways, but it will - * fail for some changes. Its string-based interface is somewhat too - * impoverished for a permanent solution. It would be possible to go for update - * scripts (specific to each change) in the style of MediaWiki instead. - * - * Make sure the table of the given name has the given fields, provided - * as an array with entries fieldname => typeparams. typeparams should be - * in a normalised form and order to match to existing values. - * - * The function returns an array that includes all columns that have been - * changed. For each such column, the array contains an entry - * columnname => action, where action is one of 'up', 'new', or 'del' - * - * If progress reports during this operation are desired, then the parameter $reportTo should - * be given an object that has a method reportProgress(string) for doing so. - * - * @note The function partly ignores the order in which fields are set up. - * Only if the type of some field changes will its order be adjusted explicitly. - * - * @param string $tableName The table name. Does not need to have been passed to DatabaseBase->tableName yet. - * @param array $columns The fields and their types the table should have. - * @param DatabaseBase or Database $db - * @param object $reportTo Object to report back to. - */ - public static function setupTable( $rawTableName, array $fields, $db, $reportTo = null ) { - $tableName = $db->tableName( $rawTableName ); - - self::reportProgress( "Checking table $tableName ...\n", $reportTo ); - - if ( $db->tableExists( $rawTableName ) === false ) { // create new table - self::reportProgress( " Table not found, now creating...\n", $reportTo ); - self::createTable( $tableName, $fields, $db, $reportTo ); - self::reportProgress( " ... done.\n", $reportTo ); - } else { - self::reportProgress( " Table already exists, checking structure ...\n", $reportTo ); - self::updateTable( $tableName, $fields, $db, $reportTo ); - self::reportProgress( " ... done.\n", $reportTo ); - } - } - - /** - * Creates a new database table with the specified fields. - * - * @param string $tableName The table name. - * @param array $columns The fields and their types the table should have. - * @param DatabaseBase|Database $db - * @param object $reportTo object to report back to. - */ - protected static function createTable( $tableName, array $fields, $db, $reportTo ) { - global $wgDBtype, $wgDBname; - - $sql = 'CREATE TABLE ' . ( ( $wgDBtype == 'postgres' || $wgDBtype == 'sqlite' ) ? '' : "`$wgDBname`." ) . $tableName . ' ('; - - $fieldSql = array(); - - foreach ( $fields as $fieldName => $fieldType ) { - $fieldSql[] = "$fieldName $fieldType"; - } - - $sql .= implode( ',', $fieldSql ) . ') '; - - if ( $wgDBtype != 'postgres' && $wgDBtype != 'sqlite' ) { - // This replacement is needed for compatibility, see http://bugs.mysql.com/bug.php?id=17501 - $sql .= str_replace( 'TYPE', 'ENGINE', $GLOBALS['wgDBTableOptions'] ); - } - - $db->query( $sql, __METHOD__ ); - } - - /** - * Update a table given an array of field names and field types. - * - * @param string $tableName The table name. - * @param array $columns The fields and their types the table should have. - * @param DatabaseBase|Database $db - * @param object $reportTo Object to report back to. - */ - protected static function updateTable( $tableName, array $fields, $db, $reportTo ) { - global $wgDBtype; - - $currentFields = self::getFields( $tableName, $db, $reportTo ); - - $isPostgres = $wgDBtype == 'postgres'; - - if ( !$isPostgres ) $position = 'FIRST'; - - // Loop through all the field definitions, and handle each definition for either postgres or MySQL. - foreach ( $fields as $fieldName => $fieldType ) { - if ( $isPostgres ) { - self::updatePostgresField( $tableName, $fieldName, $fieldType, $currentFields, $db, $reportTo ); - } else { - self::updateMySqlField( $tableName, $fieldName, $fieldType, $currentFields, $db, $reportTo, $position ); - $position = "AFTER $fieldName"; - } - - $currentFields[$fieldName] = false; - } - - // The updated fields have their value set to false, so if a field has a value - // that differs from false, it's an obsolete one that should be removed. - foreach ( $currentFields as $fieldName => $value ) { - if ( $value !== false ) { - SMWSQLHelpers::reportProgress( " ... deleting obsolete field $fieldName ... ", $reportTo ); - - if ( $isPostgres ) { - $db->query( 'ALTER TABLE "' . $tableName . '" DROP COLUMN "' . $fieldName . '"', __METHOD__ ); - } elseif ( $wgDBtype == 'sqlite' ) { - // DROP COLUMN not supported in Sqlite3 - SMWSQLHelpers::reportProgress( " ... deleting obsolete field $fieldName not possible in SQLLite ... you could delete and reinitialize the tables to remove obsolete data, or just keep it ... ", $reportTo ); - } else { - $db->query( "ALTER TABLE $tableName DROP COLUMN `$fieldName`", __METHOD__ ); - } - - SMWSQLHelpers::reportProgress( "done.\n", $reportTo ); - } - } - } - - /** - * Returns an array of fields (as keys) and their types (as values). - * - * @param string $tableName The table name. - * @param DatabaseBase|Database $db - * @param object $reportTo to report back to. - * - * @return array - */ - protected static function getFields( $tableName, $db, $reportTo ) { - global $wgDBtype; - - if ( $wgDBtype == 'postgres' ) { - $tableName = str_replace( '"', '', $tableName ); - // Use the data dictionary in postgresql to get an output comparable to DESCRIBE. - $sql = <<<EOT -SELECT - a.attname as "Field", - upper(pg_catalog.format_type(a.atttypid, a.atttypmod)) as "Type", - (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) - FROM pg_catalog.pg_attrdef d - WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) as "Extra", - case when a.attnotnull THEN 'NO'::text else 'YES'::text END as "Null", a.attnum - FROM pg_catalog.pg_attribute a - WHERE a.attrelid = ( - SELECT c.oid - FROM pg_catalog.pg_class c - LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname ~ '^($tableName)$' - AND pg_catalog.pg_table_is_visible(c.oid) - LIMIT 1 - ) AND a.attnum > 0 AND NOT a.attisdropped - ORDER BY a.attnum -EOT; - } elseif ( $wgDBtype == 'sqlite' ) { // SQLite - $sql = 'PRAGMA table_info(' . $tableName . ')'; - } else { // MySQL - $sql = 'DESCRIBE ' . $tableName; - } - - $res = $db->query( $sql, __METHOD__ ); - $curfields = array(); - - foreach ( $res as $row ) { - if ( $wgDBtype == 'postgres' ) { // postgresql - $type = strtoupper( $row->Type ); - - if ( preg_match( '/^nextval\\(.+\\)/i', $row->Extra ) ) { - $type = 'SERIAL NOT NULL'; - } elseif ( $row->Null != 'YES' ) { - $type .= ' NOT NULL'; - } - } elseif ( $wgDBtype == 'sqlite' ) { // SQLite - $row->Field = $row->name; - $row->Type = $row->type; - $type = $row->type; - if ( $row->notnull == '1' ) { - $type .= ' NOT NULL'; - } - if ( $row->pk == '1' ) { - $type .= ' PRIMARY KEY AUTOINCREMENT'; - } - } else { // mysql - $type = strtoupper( $row->Type ); - - if ( substr( $type, 0, 8 ) == 'VARCHAR(' ) { - $type .= ' binary'; // just assume this to be the case for VARCHAR, though DESCRIBE will not tell us - } - - if ( $row->Null != 'YES' ) { - $type .= ' NOT NULL'; - } - - if ( $row->Key == 'PRI' ) { /// FIXME: updating "KEY" is not possible, the below query will fail in this case. - $type .= ' KEY'; - } - - if ( $row->Extra == 'auto_increment' ) { - $type .= ' AUTO_INCREMENT'; - } - } - - $curfields[$row->Field] = $type; - } - - return $curfields; - } - - /** - * Update a single field given it's name and type and an array of - * current fields. Postgres version. - * - * @param string $tableName The table name. - * @param string $name The field name. - * @param string $type The field type and attributes. - * @param array $currentFields List of fields as they have been found in the database. - * @param DatabaseBase|Database $db - * @param object $reportTo Object to report back to. - */ - protected static function updatePostgresField( $tableName, $name, $type, array $currentFields, $db, $reportTo ) { - $keypos = strpos( $type, ' PRIMARY KEY' ); - - if ( $keypos > 0 ) { - $type = substr( $type, 0, $keypos ); - } - - $type = strtoupper( $type ); - - if ( !array_key_exists( $name, $currentFields ) ) { - self::reportProgress( " ... creating field $name ... ", $reportTo ); - - $db->query( "ALTER TABLE $tableName ADD \"" . $name . "\" $type", __METHOD__ ); - - self::reportProgress( "done.\n", $reportTo ); - } elseif ( $currentFields[$name] != $type ) { - self::reportProgress( " ... changing type of field $name from '$currentFields[$name]' to '$type' ... ", $reportTo ); - - $notnullposnew = strpos( $type, ' NOT NULL' ); - if ( $notnullposnew > 0 ) { - $type = substr( $type, 0, $notnullposnew ); - } - - $notnullposold = strpos( $currentFields[$name], ' NOT NULL' ); - $typeold = strtoupper( ( $notnullposold > 0 ) ? substr( $currentFields[$name], 0, $notnullposold ) : $currentFields[$name] ); - - if ( $typeold != $type ) { - $sql = "ALTER TABLE " . $tableName . " ALTER COLUMN \"" . $name . "\" TYPE " . $type; - $db->query( $sql, __METHOD__ ); - } - - if ( $notnullposold != $notnullposnew ) { - $sql = "ALTER TABLE " . $tableName . " ALTER COLUMN \"" . $name . "\" " . ( $notnullposnew > 0 ? 'SET' : 'DROP' ) . " NOT NULL"; - $db->query( $sql, __METHOD__ ); - } - - self::reportProgress( "done.\n", $reportTo ); - } else { - self::reportProgress( " ... field $name is fine.\n", $reportTo ); - } - } - - /** - * Update a single field given it's name and type and an array of - * current fields. MySQL version. - * - * @param string $tableName The table name. - * @param string $name The field name. - * @param string $type The field type and attributes. - * @param array $currentFields List of fields as they have been found in the database. - * @param DatabaseBase|Database $db - * @param object $reportTo Object to report back to. - * @param string $position - */ - protected static function updateMySqlField( $tableName, $name, $type, array $currentFields, $db, $reportTo, $position ) { - if ( !array_key_exists( $name, $currentFields ) ) { - self::reportProgress( " ... creating field $name ... ", $reportTo ); - - $db->query( "ALTER TABLE $tableName ADD `$name` $type $position", __METHOD__ ); - $result[$name] = 'new'; - - self::reportProgress( "done.\n", $reportTo ); - } elseif ( $currentFields[$name] != $type ) { - self::reportProgress( " ... changing type of field $name from '$currentFields[$name]' to '$type' ... ", $reportTo ); - - $db->query( "ALTER TABLE $tableName CHANGE `$name` `$name` $type $position", __METHOD__ ); - $result[$name] = 'up'; - self::reportProgress( "done.\n", $reportTo ); - } else { - self::reportProgress( " ... field $name is fine.\n", $reportTo ); - } - } - - /** - * Make sure that each of the column descriptions in the given array is - * indexed by *one* index in the given DB table. - * - * @param string $tableName table name. Does not need to have been passed to DatabaseBase->tableName yet. - * @param array $indexes array of strings, each a comma separated list with column names to index - * @param DatabaseBase|Database $db DatabaseBase or Database - * @param object $reportTo object to report messages to; since 1.8 - */ - public static function setupIndex( $rawTableName, array $indexes, $db, $reportTo = null ) { - global $wgDBtype; - - $tableName = $wgDBtype == 'postgres' ? $db->tableName( $rawTableName, 'raw' ) : $db->tableName( $rawTableName ); - - self::reportProgress( "Checking index structures for table $tableName ...\n", $reportTo ); - - // First remove obsolete indexes. - $oldIndexes = self::getIndexInfo( $db, $tableName ); - if ( $wgDBtype == 'sqlite' ) { // SQLite - /// TODO We do not currently get the right column definitions in - /// SQLLite; hence we can only drop all indexes. Wasteful. - foreach ( $oldIndexes as $key => $index ) { - self::dropIndex( $db, $key, $tableName, $key, $reportTo ); - } - } else { - foreach ( $oldIndexes as $key => $indexColumn ) { - $id = array_search( $indexColumn, $indexes ); - if ( $id !== false || $key == 'PRIMARY' ) { - self::reportProgress( " ... index $indexColumn is fine.\n", $reportTo ); - unset( $indexes[$id] ); - } else { // Duplicate or unrequired index. - self::dropIndex( $db, $key, $tableName, $indexColumn, $reportTo ); - } - } - } - - // Add new indexes. - foreach ( $indexes as $key => $index ) { - // If the index is an array, it contains the column - // name as first element, and index type as second one. - if ( is_array( $index ) ) { - $columns = $index[0]; - $type = count( $index ) > 1 ? $index[1] : 'INDEX'; - } else { - $columns = $index; - $type = 'INDEX'; - } - - self::createIndex( $db, $type, "{$tableName}_index{$key}", $tableName, $columns, $reportTo ); - } - - self::reportProgress( " ... done.\n", $reportTo ); - - return true; - } - - /** - * Get the information about all indexes of a table. The result is an - * array of format indexname => indexcolumns. The latter is a comma - * separated list. - * - * @since 1.8 - * @param DatabaseBase|Database $db database handler - * @param string $tableName name of table - * @return array indexname => columns - */ - protected static function getIndexInfo( $db, $tableName ) { - global $wgDBtype; - - $indexes = array(); - if ( $wgDBtype == 'postgres' ) { // postgresql - $sql = "SELECT i.relname AS indexname," - . " pg_get_indexdef(i.oid) AS indexdef, " - . " replace(substring(pg_get_indexdef(i.oid) from E'\\\\((.*)\\\\)'), ' ' , '') AS indexcolumns" - . " FROM pg_index x" - . " JOIN pg_class c ON c.oid = x.indrelid" - . " JOIN pg_class i ON i.oid = x.indexrelid" - . " LEFT JOIN pg_namespace n ON n.oid = c.relnamespace" - . " LEFT JOIN pg_tablespace t ON t.oid = i.reltablespace" - . " WHERE c.relkind = 'r'::\"char\" AND i.relkind = 'i'::\"char\"" - . " AND c.relname = '" . $tableName . "'" - . " AND NOT pg_get_indexdef(i.oid) ~ '^CREATE UNIQUE INDEX'"; - $res = $db->query( $sql, __METHOD__ ); - - if ( !$res ) { - return false; - } - - foreach ( $res as $row ) { - $indexes[$row->indexname] = $row->indexcolumns; - } - } elseif ( $wgDBtype == 'sqlite' ) { // SQLite - $res = $db->query( 'PRAGMA index_list(' . $tableName . ')' , __METHOD__ ); - - if ( !$res ) { - return false; - } - - foreach ( $res as $row ) { - /// FIXME The value should not be $row->name below?! - if ( !array_key_exists( $row->name, $indexes ) ) { - $indexes[$row->name] = $row->name; - } else { - $indexes[$row->name] .= ',' . $row->name; - } - } - } else { // MySQL and default - $res = $db->query( 'SHOW INDEX FROM ' . $tableName , __METHOD__ ); - - if ( !$res ) { - return false; - } - - foreach ( $res as $row ) { - if ( !array_key_exists( $row->Key_name, $indexes ) ) { - $indexes[$row->Key_name] = $row->Column_name; - } else { - $indexes[$row->Key_name] .= ',' . $row->Column_name; - } - } - } - - return $indexes; - } - - /** - * Drop an index using the suitable SQL for various RDBMS. - * - * @since 1.8 - * @param DatabaseBase|Database $db database handler - * @param string $indexName name fo the index as in DB - * @param string $tableName name of the table (not relevant in all DBMSs) - * @param string $columns list of column names to index, comma - * separated; only for reporting - * @param object $reportTo to report messages to - */ - protected static function dropIndex( $db, $indexName, $tableName, $columns, $reportTo = null ) { - global $wgDBtype; - - self::reportProgress( " ... removing index $columns ...", $reportTo ); - if ( $wgDBtype == 'postgres' ) { // postgresql - $db->query( 'DROP INDEX IF EXISTS ' . $indexName, __METHOD__ ); - } elseif ( $wgDBtype == 'sqlite' ) { // SQLite - $db->query( 'DROP INDEX ' . $indexName, __METHOD__ ); - } else { // MySQL and default - $db->query( 'DROP INDEX ' . $indexName . ' ON ' . $tableName, __METHOD__ ); - } - self::reportProgress( "done.\n", $reportTo ); - } - - /** - * Create an index using the suitable SQL for various RDBMS. - * - * @since 1.8 - * @param DatabaseBase|Database $db Database handler - * @param string $type "INDEX", "UNIQUE" or similar - * @param string $indexName name fo the index as in DB - * @param string $tableName name of the table - * @param array $columns list of column names to index, comma separated - * @param object $reportTo object to report messages to - */ - protected static function createIndex( $db, $type, $indexName, $tableName, $columns, $reportTo = null ) { - global $wgDBtype; - - self::reportProgress( " ... creating new index $columns ...", $reportTo ); - if ( $wgDBtype == 'postgres' ) { // postgresql - if ( $db->indexInfo( $tableName, $indexName ) === false ) { - $db->query( "CREATE $type $indexName ON $tableName ($columns)", __METHOD__ ); - } - } elseif ( $wgDBtype == 'sqlite' ) { // SQLite - $db->query( "CREATE $type $indexName ON $tableName ($columns)", __METHOD__ ); - } else { // MySQL and default - $db->query( "ALTER TABLE $tableName ADD $type ($columns)", __METHOD__ ); - } - self::reportProgress( "done.\n", $reportTo ); - } - - /** - * Reports the given message to the reportProgress method of the - * $receiver. - * - * @param string $msg - * @param object $receiver - */ - protected static function reportProgress( $msg, $receiver ) { - if ( !is_null( $receiver ) ) $receiver->reportProgress( $msg ); - } - -} diff --git a/SemanticMediaWiki/includes/storage/SMW_Store.php b/SemanticMediaWiki/includes/storage/SMW_Store.php deleted file mode 100644 index 640b39fd..00000000 --- a/SemanticMediaWiki/includes/storage/SMW_Store.php +++ /dev/null @@ -1,418 +0,0 @@ -<?php - -namespace SMW; - -use HTMLFileCache; -use SMWDataItem; -use SMWQuery; -use SMWQueryResult; -use SMWRequestOptions; -use SMWSemanticData; -use Title; - -/** - * This group contains all parts of SMW that relate to storing and retrieving - * semantic data. SMW components that relate to semantic querying only have - * their own group. - * - * @defgroup SMWStore SMWStore - * @ingroup SMW - */ - -/** - * The abstract base class for all classes that implement access to some - * semantic store. Besides the relevant interface, this class provides default - * implementations for some optional methods, which inform the caller that - * these methods are not implemented. - * - * @ingroup SMWStore - * - * @author Markus Krötzsch - */ -abstract class Store { - - /** - * FIXME THIS SHOULD NOT BE STATIC - * - * getPropertyTables is used all over the Store in a static manner - * but its needs needs access to the configuration therefore once - * all static calls are removed, turn this into a normal protected - * variable - */ - protected static $configuration = null; - -///// Reading methods ///// - - /** - * Retrieve all data stored about the given subject and return it as a - * SMWSemanticData container. There are no options: it just returns all - * available data as shown in the page's Factbox. - * $filter is an array of strings that are datatype IDs. If given, the - * function will avoid any work that is not necessary if only - * properties of these types are of interest. - * - * @note There is no guarantee that the store does not retrieve more - * data than requested when a filter is used. Filtering just ensures - * that only necessary requests are made, i.e. it improves performance. - */ - public abstract function getSemanticData( DIWikiPage $subject, $filter = false ); - - /** - * Get an array of all property values stored for the given subject and - * property. The result is an array of DataItem objects. - * - * If called with $subject == null, all values for the given property - * are returned. - * - * @param $subject mixed SMWDIWikiPage or null - * @param $property DIProperty - * @param $requestoptions SMWRequestOptions - * - * @return array of SMWDataItem - */ - public abstract function getPropertyValues( $subject, DIProperty $property, $requestoptions = null ); - - /** - * Get an array of all subjects that have the given value for the given - * property. The result is an array of DIWikiPage objects. If null - * is given as a value, all subjects having that property are returned. - * - * @return DIWikiPage[] - */ - public abstract function getPropertySubjects( DIProperty $property, $value, $requestoptions = null ); - - /** - * Get an array of all subjects that have some value for the given - * property. The result is an array of DIWikiPage objects. - * - * @return DIWikiPage[] - */ - public abstract function getAllPropertySubjects( DIProperty $property, $requestoptions = null ); - - /** - * Get an array of all properties for which the given subject has some - * value. The result is an array of DIProperty objects. - * - * @param DIWikiPage $subject denoting the subject - * @param SMWRequestOptions|null $requestOptions optionally defining further options - * - * @return SMWDataItem - */ - public abstract function getProperties( DIWikiPage $subject, $requestOptions = null ); - - /** - * Get an array of all properties for which there is some subject that - * relates to the given value. The result is an array of SMWDIWikiPage - * objects. - * @note In some stores, this function might be implemented partially - * so that only values of type Page (_wpg) are supported. - */ - public abstract function getInProperties( SMWDataItem $object, $requestoptions = null ); - - /** - * Convenience method to find the sortkey of an SMWDIWikiPage. The - * result is based on the contents of this store, and may differ from - * the MediaWiki database entry about a Title objects sortkey. If no - * sortkey is stored, the default sortkey (title string) is returned. - * - * @param $wikiPage DIWikiPage to find the sortkey for - * @return string sortkey - */ - public function getWikiPageSortKey( DIWikiPage $wikiPage ) { - $sortkeyDataItems = $this->getPropertyValues( $wikiPage, new DIProperty( '_SKEY' ) ); - - if ( count( $sortkeyDataItems ) > 0 ) { - return end( $sortkeyDataItems )->getString(); - } else { - return str_replace( '_', ' ', $wikiPage->getDBkey() ); - } - } - - /** - * Convenience method to find the redirect target of a DIWikiPage - * or DIProperty object. Returns a dataitem of the same type that - * the input redirects to, or the input itself if there is no redirect. - * - * @param $dataItem SMWDataItem to find the redirect for. - * @return SMWDataItem - */ - public function getRedirectTarget( SMWDataItem $dataItem ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_PROPERTY ) { - if ( !$dataItem->isUserDefined() ) { - return $dataItem; - } - $wikipage = $dataItem->getDiWikiPage(); - } elseif ( $dataItem->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) { - $wikipage = $dataItem; - } else { - throw new InvalidArgumentException( 'SMWStore::getRedirectTarget() expects an object of type IProperty or SMWDIWikiPage.' ); - } - - $redirectDataItems = $this->getPropertyValues( $wikipage, new DIProperty( '_REDI' ) ); - if ( count( $redirectDataItems ) > 0 ) { - if ( $dataItem->getDIType() == SMWDataItem::TYPE_PROPERTY ) { - return new DIProperty( end( $redirectDataItems )->getDBkey() ); - } else { - return end( $redirectDataItems ); - } - } else { - return $dataItem; - } - } - -///// Writing methods ///// - - /** - * Delete all semantic properties that the given subject has. This - * includes relations, attributes, and special properties. This does - * not delete the respective text from the wiki, but only clears the - * stored data. - * - * @param Title $subject - */ - public abstract function deleteSubject( Title $subject ); - - /** - * Update the semantic data stored for some individual. The data is - * given as a SemanticData object, which contains all semantic data - * for one particular subject. - * - * @param SemanticData $data - */ - protected abstract function doDataUpdate( SemanticData $data ); - - /** - * Update the semantic data stored for some individual. The data is - * given as a SemanticData object, which contains all semantic data - * for one particular subject. - * - * @param $data SemanticData - */ - public function updateData( SemanticData $data ) { - /** - * @since 1.6 - */ - wfRunHooks( 'SMWStore::updateDataBefore', array( $this, $data ) ); - - // Invalidate the page, so data stored on it gets displayed immediately in queries. - global $smwgAutoRefreshSubject; - if ( $smwgAutoRefreshSubject && !wfReadOnly() ) { - $title = Title::makeTitle( $data->getSubject()->getNamespace(), $data->getSubject()->getDBkey() ); - $dbw = wfGetDB( DB_MASTER ); - - $dbw->update( - 'page', - array( 'page_touched' => $dbw->timestamp( time() + 4 ) ), - $title->pageCond(), - __METHOD__ - ); - - HTMLFileCache::clearFileCache( $title ); - } - - $this->doDataUpdate( $data ); - - /** - * @since 1.6 - */ - wfRunHooks( 'SMWStore::updateDataAfter', array( $this, $data ) ); - } - - /** - * Clear all semantic data specified for some page. - * - * @param DIWikiPage $di - */ - public function clearData( DIWikiPage $di ) { - $this->updateData( new SMWSemanticData( $di ) ); - } - - /** - * Update the store to reflect a renaming of some article. Normally - * this happens when moving pages in the wiki, and in this case there - * is also a new redirect page generated at the old position. The title - * objects given are only used to specify the name of the title before - * and after the move -- do not use their IDs for anything! The ID of - * the moved page is given in $pageid, and the ID of the newly created - * redirect, if any, is given by $redirid. If no new page was created, - * $redirid will be 0. - */ - public abstract function changeTitle( Title $oldtitle, Title $newtitle, $pageid, $redirid = 0 ); - -///// Query answering ///// - - /** - * Execute the provided query and return the result as an - * SMWQueryResult if the query was a usual instance retrieval query. In - * the case that the query asked for a plain string (querymode - * MODE_COUNT or MODE_DEBUG) a plain wiki and HTML-compatible string is - * returned. - * - * @param SMWQuery $query - * - * @return SMWQueryResult - */ - public abstract function getQueryResult( SMWQuery $query ); - -///// Special page functions ///// - - /** - * Return all properties that have been used on pages in the wiki. The - * result is an array of arrays, each containing a property data item - * and a count. The expected order is alphabetical w.r.t. to property - * names. - * - * If there is an error on creating some property object, then a - * suitable SMWDIError object might be returned in its place. Even if - * there are errors, the function should always return the number of - * results requested (otherwise callers might assume that there are no - * further results to ask for). - * - * @param SMWRequestOptions $requestoptions - * - * @return array of array( DIProperty|SMWDIError, integer ) - */ - public abstract function getPropertiesSpecial( $requestoptions = null ); - - /** - * Return all properties that have been declared in the wiki but that - * are not used on any page. Stores might restrict here to those - * properties that have been given a type if they have no efficient - * means of accessing the set of all pages in the property namespace. - * - * If there is an error on creating some property object, then a - * suitable SMWDIError object might be returned in its place. Even if - * there are errors, the function should always return the number of - * results requested (otherwise callers might assume that there are no - * further results to ask for). - * - * @param SMWRequestOptions $requestoptions - * - * @return array of DIProperty|SMWDIError - */ - public abstract function getUnusedPropertiesSpecial( $requestoptions = null ); - - /** - * Return all properties that are used on some page but that do not - * have any page describing them. Stores that have no efficient way of - * accessing the set of all existing pages can extend this list to all - * properties that are used but do not have a type assigned to them. - * - * @param SMWRequestOptions $requestoptions - * - * @return array of array( DIProperty, int ) - */ - public abstract function getWantedPropertiesSpecial( $requestoptions = null ); - - /** - * Return statistical information as an associative array with the - * following keys: - * - 'PROPUSES': Number of property instances (value assignments) in the datatbase - * - 'USEDPROPS': Number of properties that are used with at least one value - * - 'DECLPROPS': Number of properties that have been declared (i.e. assigned a type) - * - 'OWNPAGE': Number of properties with their own page - * - 'QUERY': Number of inline queries - * - 'QUERYSIZE': Represents collective query size - * - 'CONCEPTS': Number of declared concepts - * - 'SUBOBJECTS': Number of declared subobjects - * - * @return array - */ - public abstract function getStatistics(); - -///// Setup store ///// - - /** - * Setup all storage structures properly for using the store. This - * function performs tasks like creation of database tables. It is - * called upon installation as well as on upgrade: hence it must be - * able to upgrade existing storage structures if needed. It should - * return "true" if successful and return a meaningful string error - * message otherwise. - * - * The parameter $verbose determines whether the procedure is allowed - * to report on its progress. This is doen by just using print and - * possibly ob_flush/flush. This is also relevant for preventing - * timeouts during long operations. All output must be valid in an HTML - * context, but should preferrably be plain text, possibly with some - * linebreaks and weak markup. - * - * @param boolean $verbose - * - * @return boolean Success indicator - */ - public abstract function setup( $verbose = true ); - - /** - * Drop (delete) all storage structures created by setup(). This will - * delete all semantic data and possibly leave the wiki uninitialised. - * - * @param boolean $verbose - */ - public abstract function drop( $verbose = true ); - - /** - * Refresh some objects in the store, addressed by numerical ids. The - * meaning of the ids is private to the store, and does not need to - * reflect the use of IDs elsewhere (e.g. page ids). The store is to - * refresh $count objects starting from the given $index. Typically, - * updates are achieved by generating update jobs. After the operation, - * $index is set to the next index that should be used for continuing - * refreshing, or to -1 for signaling that no objects of higher index - * require refresh. The method returns a decimal number between 0 and 1 - * to indicate the overall progress of the refreshing (e.g. 0.7 if 70% - * of all objects were refreshed). - * - * The optional parameter $namespaces may contain an array of namespace - * constants. If given, only objects from those namespaces will be - * refreshed. The default value FALSE disables this feature. - * - * The optional parameter $usejobs indicates whether updates should be - * processed later using MediaWiki jobs, instead of doing all updates - * immediately. The default is TRUE. - * - * @param $index integer - * @param $count integer - * @param $namespaces mixed array or false - * @param $usejobs boolean - * - * @return float between 0 and 1 to indicate the overall progress of the refreshing - */ - public abstract function refreshData( &$index, $count, $namespaces = false, $usejobs = true ); - - /** - * Setup the store. - * - * @since 1.8 - * - * @param bool $verbose - * - * @return boolean Success indicator - */ - public static function setupStore( $verbose = true ) { - $result = \SMW\StoreFactory::getStore()->setup( $verbose ); - wfRunHooks( 'smwInitializeTables' ); - return $result; - } - - /** - * Returns the tables that should be added via the - * https://www.mediawiki.org/wiki/Manual:Hooks/ParserTestTables - * hook when it's run. - * - * @since 1.8 - * - * @return array - */ - public function getParserTestTables() { - return array(); - } - - /** - * @since 1.9.1.1 - */ - public function setConfiguration( Settings $configuration ) { - self::$configuration = $configuration; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/PropertiesCollector.php b/SemanticMediaWiki/includes/storage/SQLStore/PropertiesCollector.php deleted file mode 100644 index 3ab1e179..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/PropertiesCollector.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php - -namespace SMW\SQLStore; - -use SMW\Store\CacheableResultCollector; - -use SMW\InvalidPropertyException; -use SMW\SimpleDictionary; -use SMW\DIProperty; -use SMW\Settings; -use SMW\Profiler; -use SMW\Store; - -use SMWDIError; - -use Message; -use DatabaseBase; - -/** - * Collects properties from a store entity - * - * @ingroup SQLStore - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - * @author Nischay Nahata - */ -class PropertiesCollector extends CacheableResultCollector { - - /** @var Store */ - protected $store; - - /** @var Settings */ - protected $settings; - - /** @var DatabaseBase */ - protected $dbConnection; - - /** - * @since 1.9 - * - * @param Store $store - * @param DatabaseBase $dbw - * @param Settings $settings - */ - public function __construct( Store $store, DatabaseBase $dbw, Settings $settings ) { - $this->store = $store; - $this->dbConnection = $dbw; - $this->settings = $settings; - } - - /** - * @since 1.9 - * - * @return DIProperty[] - */ - public function runCollector() { - return $this->getProperties( $this->doQuery() ); - } - - /** - * @see CacheableObjectCollector::cacheSetup - * - * @since 1.9 - * - * @return ObjectDictionary - */ - protected function cacheSetup() { - return new SimpleDictionary( array( - 'id' => array( 'smwgPropertiesCache', (array)$this->requestOptions ), - 'type' => $this->settings->get( 'smwgCacheType' ), - 'enabled' => $this->settings->get( 'smwgPropertiesCache' ), - 'expiry' => $this->settings->get( 'smwgPropertiesCacheExpiry' ) - ) ); - } - - /** - * @since 1.9 - * - * @return array - */ - protected function doQuery() { - Profiler::In( __METHOD__ ); - - // the query needs to do the filtering of internal properties, else LIMIT is wrong - $options = array( 'ORDER BY' => 'smw_sortkey' ); - - $conditions = array( - 'smw_namespace' => SMW_NS_PROPERTY, - 'smw_iw' => '', - ); - - if ( $this->requestOptions !== null ) { - - if ( $this->requestOptions->limit > 0 ) { - $options['LIMIT'] = $this->requestOptions->limit; - $options['OFFSET'] = max( $this->requestOptions->offset, 0 ); - } - - if ( $this->requestOptions->getStringConditions() ) { - $conditions[] = $this->store->getSQLConditions( $this->requestOptions, '', 'smw_title', false ); - } - - } - - $res = $this->dbConnection->select( - $this->store->getObjectIds()->getIdTable(), - array( - 'smw_id', - 'smw_title' - ), - $conditions, - __METHOD__, - $options - ); - - Profiler::Out( __METHOD__ ); - return $res; - } - - /** - * Collect all properties in the SMW IDs table (based on their namespace) and - * getting their usage from the property statistics table. - * - * @since 1.9 - * - * @return DIProperty[] - */ - protected function getProperties( $res ) { - Profiler::In( __METHOD__ ); - - $result = array(); - $propertyIds = array(); - - foreach ( $res as $row ) { - $propertyIds[] = (int)$row->smw_id; - } - - $statsTable = new PropertyStatisticsTable( - $this->store->getDatabase(), - $this->store->getStatisticsTable() - ); - - $usageCounts = $statsTable->getUsageCounts( $propertyIds ); - - foreach ( $res as $row ) { - - try { - $property = new DIProperty( $row->smw_title ); - } catch ( InvalidPropertyException $e ) { - $property = new SMWDIError( new Message( 'smw_noproperty', array( $row->smw_title ) ) ); - } - - // If there is no key entry in the usageCount table for that - // particular property it is to be counted with usage 0 - $count = array_key_exists( (int)$row->smw_id, $usageCounts ) ? $usageCounts[(int)$row->smw_id] : 0; - $result[] = array( $property, $count ); - } - - Profiler::Out( __METHOD__ ); - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/PropertyStatisticsTable.php b/SemanticMediaWiki/includes/storage/SQLStore/PropertyStatisticsTable.php deleted file mode 100644 index 18e14eae..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/PropertyStatisticsTable.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php - -namespace SMW\SQLStore; - -use SMW\Store\PropertyStatisticsStore; -use SMW\MediaWiki\Database; - -use MWException; - -/** - * Simple implementation of PropertyStatisticsTable using MediaWikis - * database abstraction layer and a single table. - * - * @since 1.9 - * - * @ingroup SMWStore - * - * @license GNU GPL v2 or later - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author Nischay Nahata - */ -class PropertyStatisticsTable implements PropertyStatisticsStore { - - /** - * @since 1.9 - * @var string - */ - protected $table; - - /** - * @since 1.9 - * @var DatabaseBase - */ - protected $dbConnection; - - /** - * Constructor. - * - * @since 1.9 - * - * @param Database $dbConnection - * @param string $table - */ - public function __construct( Database $dbConnection, $table ) { - assert( is_string( $table ) ); - - $this->dbConnection = $dbConnection; - $this->table = $table; - } - - /** - * @see PropertyStatisticsStore::addToUsageCount - * - * @since 1.9 - * - * @param integer $propertyId - * @param integer $value - * - * @return boolean Success indicator - * @throws MWException - */ - public function addToUsageCount( $propertyId, $value ) { - if ( !is_int( $value ) ) { - throw new MWException( 'The value to add must be an integer' ); - } - - if ( !is_int( $propertyId ) || $propertyId <= 0 ) { - throw new MWException( 'The property id to add must be a positive integer' ); - } - - if ( $value == 0 ) { - return true; - } - - return $this->dbConnection->update( - $this->table, - array( - 'usage_count = usage_count ' . ( $value > 0 ? '+ ' : '- ' ) . $this->dbConnection->addQuotes( abs( $value ) ), - ), - array( - 'p_id' => $propertyId - ), - __METHOD__ - ); - } - - /** - * @see PropertyStatisticsStore::addToUsageCounts - * - * @since 1.9 - * - * @param array $additions - * - * @return boolean Success indicator - */ - public function addToUsageCounts( array $additions ) { - $success = true; - - // TODO: properly implement this - foreach ( $additions as $propertyId => $addition ) { - $success = $this->addToUsageCount( $propertyId, $addition ) && $success; - } - - return $success; - } - - /** - * @see PropertyStatisticsStore::setUsageCount - * - * @since 1.9 - * - * @param integer $propertyId - * @param integer $value - * - * @return boolean Success indicator - * @throws MWException - */ - public function setUsageCount( $propertyId, $value ) { - if ( !is_int( $value ) || $value < 0 ) { - throw new MWException( 'The value to add must be a positive integer' ); - } - - if ( !is_int( $propertyId ) || $propertyId <= 0 ) { - throw new MWException( 'The property id to add must be a positive integer' ); - } - - return $this->dbConnection->update( - $this->table, - array( - 'usage_count' => $value, - ), - array( - 'p_id' => $propertyId - ), - __METHOD__ - ); - } - - /** - * @see PropertyStatisticsStore::insertUsageCount - * - * @since 1.9 - * - * @param integer $propertyId - * @param integer $value - * - * @return boolean Success indicator - * @throws MWException - */ - public function insertUsageCount( $propertyId, $value ) { - if ( !is_int( $value ) || $value < 0 ) { - throw new MWException( 'The value to add must be a positive integer' ); - } - - if ( !is_int( $propertyId ) || $propertyId <= 0 ) { - throw new MWException( 'The property id to add must be a positive integer' ); - } - - return $this->dbConnection->insert( - $this->table, - array( - 'usage_count' => $value, - 'p_id' => $propertyId, - ), - __METHOD__ - ); - } - - /** - * @see PropertyStatisticsStore::getUsageCounts - * - * @since 1.9 - * - * @param array $propertyIds - * - * @return array - */ - public function getUsageCounts( array $propertyIds ) { - if ( $propertyIds === array() ) { - return array(); - } - - $propertyStatistics = $this->dbConnection->select( - $this->table, - array( - 'usage_count', - 'p_id', - ), - array( - 'p_id' => $propertyIds, - ), - __METHOD__ - ); - - $usageCounts = array(); - - foreach ( $propertyStatistics as $propertyStatistic ) { - assert( ctype_digit( $propertyStatistic->p_id ) ); - assert( ctype_digit( $propertyStatistic->usage_count ) ); - - $usageCounts[(int)$propertyStatistic->p_id] = (int)$propertyStatistic->usage_count; - } - - return $usageCounts; - } - - /** - * @see PropertyStatisticsStore::deleteAll - * - * @since 1.9 - * - * @return boolean Success indicator - */ - public function deleteAll() { - return $this->dbConnection->delete( - $this->table, - '*', - __METHOD__ - ); - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/PropertyTableDefinitionBuilder.php b/SemanticMediaWiki/includes/storage/SQLStore/PropertyTableDefinitionBuilder.php deleted file mode 100644 index c8657c6e..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/PropertyTableDefinitionBuilder.php +++ /dev/null @@ -1,203 +0,0 @@ -<?php - -namespace SMW\SQLStore; - -use SMW\DataTypeRegistry; -use SMWDIProperty; - -/** - * Class that generates property table definitions - * - * @ingroup SQLStore - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class PropertyTableDefinitionBuilder { - - /** @var TableDefinition[] */ - protected $propertyTables = array(); - - /** @var array */ - protected $fixedPropertyTableIds = array(); - - /** - * @since 1.9 - * - * @param array $diType - * @param array $specialProperties - * @param array $fixedProperties - */ - public function __construct( - array $diTypes, - array $specialProperties, - array $fixedProperties - ) { - $this->diTypes = $diTypes; - $this->specialProperties = $specialProperties; - $this->fixedProperties = $fixedProperties; - } - - /** - * Build definitions - * - * @since 1.9 - */ - public function runBuilder() { - wfProfileIn( __METHOD__ ); - - $this->getDITypes( $this->diTypes ); - $this->getSpecialProperties( $this->specialProperties ); - $this->getFixedProperties( $this->fixedProperties ); - - wfRunHooks( 'SMW::SQLStore::updatePropertyTableDefinitions', array( &$this->propertyTables ) ); - - $this->getFixedPropertyTableIds( $this->propertyTables ); - - wfProfileOut( __METHOD__ ); - } - - /** - * Returns table prefix - * - * @since 1.9 - * - * @return string - */ - public function getTablePrefix() { - return 'smw_fpt'; - } - - /** - * Returns fixed properties table Ids - * - * @since 1.9 - * - * @return array|null - */ - public function getTableIds() { - return $this->fixedPropertyTableIds; - } - - /** - * Returns property table definitions - * - * @since 1.9 - * - * @return TableDefinition[] - */ - public function getTableDefinitions() { - return $this->propertyTables; - } - - /** - * Returns new table definition - * - * @since 1.9 - * - * @param $diType - * @param $tableName - * @param $fixedProperty - * - * @return TableDefinition - */ - public function getDefinition( $diType, $tableName, $fixedProperty = false ) { - return new TableDefinition( $diType, $tableName, $fixedProperty ); - } - - /** - * Add property table definition - * - * @since 1.9 - * - * @param $diType - * @param $tableName - * @param $fixedProperty - */ - protected function addPropertyTable( $diType, $tableName, $fixedProperty = false ) { - $this->propertyTables[$tableName] = $this->getDefinition( $diType, $tableName, $fixedProperty ); - } - - /** - * Add DI type table definitions - * - * @since 1.9 - * - * @param array $diTypes - */ - protected function getDITypes( array $diTypes ) { - foreach( $diTypes as $tableDIType => $tableName ) { - $this->addPropertyTable( $tableDIType, $tableName ); - } - } - - /** - * Add special properties table definitions - * - * @since 1.9 - * - * @param array $specialProperties - */ - protected function getSpecialProperties( array $specialProperties ) { - foreach( $specialProperties as $propertyKey ) { - $this->addPropertyTable( - DataTypeRegistry::getInstance()->getDataItemId( SMWDIProperty::getPredefinedPropertyTypeId( $propertyKey ) ), - $this->getTablePrefix() . strtolower( $propertyKey ), - $propertyKey - ); - } - - // Redirect table uses another subject scheme for historic reasons - // TODO This should be changed if possible - $redirectTableName = $this->getTablePrefix() . '_redi'; - if ( isset( $this->propertyTables[$redirectTableName]) ) { - $this->propertyTables[$redirectTableName]->setUsesIdSubject( false ); - } - } - - /** - * Add fixed property table definitions - * - * Get all the tables for the properties that are declared as fixed - * (overly used and thus having separate tables) - * - * @see $smwgFixedProperties - * - * @since 1.9 - * - * @param array $fixedProperties - */ - protected function getFixedProperties( array $fixedProperties ) { - foreach( $fixedProperties as $propertyKey => $tableDIType ) { - $this->addPropertyTable( - $tableDIType, - $this->getTablePrefix() . '_' . md5( $propertyKey ), - $propertyKey - ); - } - } - - /** - * Build index for fixed property tables Ids - * - * @since 1.9 - * - * @param array $propertyTables - */ - protected function getFixedPropertyTableIds( array $propertyTables ) { - - foreach ( $propertyTables as $tid => $propTable ) { - if ( $propTable->isFixedPropertyTable() ) { - $this->fixedPropertyTableIds[$propTable->getFixedProperty()] = $tid; - } - } - - // Specifically set properties that must not be stored in any - // property table to null here. Any function that hits this - // null unprepared is doing something wrong anyway. - $this->fixedPropertyTableIds['_SKEY'] = null; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Blob.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Blob.php deleted file mode 100644 index cb3fcfbe..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Blob.php +++ /dev/null @@ -1,133 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItemsHandlers - */ - -/** - * This class implements Store access to blob (string) data items. - * - * @since 1.8 - * - * @author Nischay Nahata - * @ingroup SMWDataItemsHandlers - */ -class SMWDIHandlerBlob extends SMWDataItemHandler { - - /** - * Maximal number of bytes (chars) to be stored in the hash field of - * the table. Must not be bigger than 255 (the length of our VARCHAR - * field in the DB). Strings that are longer than this will be stored - * as a blob, and the hash will only start with the original string - * but the last 32 bytes are used for a hash. So the minimal portion - * of the string that is stored literally in the hash is 32 chars - * less. - * - * The value of 72 was chosen since it leads to a smaller index size - * at the cost of needing more blobs in cases where many strings are - * of length 73 to 255. But keeping the index small seems more - * important than saving disk space. Also, with 72 bytes there are at - * least 40 bytes of content available for sorting and prefix matching, - * which should be more than enough in most contexts. - * - * @since 1.8 - */ - const MAX_HASH_LENGTH = 72; - - /** - * Method to return array of fields for a DI type - * - * @return array - */ - public function getTableFields() { - return array( 'o_blob' => 'l', 'o_hash' => 't' ); - } - - /** - * @see SMWDataItemHandler::getFetchFields() - * - * @since 1.8 - * @return array - */ - public function getFetchFields() { - return array( 'o_blob' => 'l', 'o_hash' => 't' ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * - * @return array - */ - public function getWhereConds( SMWDataItem $dataItem ) { - return array( 'o_hash' => self::makeHash( $dataItem->getString() ) ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * This array is used to perform all insert operations into the DB - * To optimize return minimum fields having indexes - * - * @return array - */ - public function getInsertValues( SMWDataItem $dataItem ) { - $text = $dataItem->getString(); - return array( - 'o_blob' => strlen( $text ) <= self::MAX_HASH_LENGTH ? null : $text, - 'o_hash' => self::makeHash( $text ), - ); - } - - /** - * Method to return the field used to select this type of DataItem - * @since 1.8 - * @return string - */ - public function getIndexField() { - return 'o_hash'; - } - - /** - * Method to return the field used to select this type of DataItem - * using the label - * @since 1.8 - * @return string - */ - public function getLabelField() { - return 'o_hash'; - } - - /** - * @see SMWDataItemHandler::dataItemFromDBKeys() - * @since 1.8 - * @param array|string $dbkeys expecting array here - * - * @return SMWDataItem - */ - public function dataItemFromDBKeys( $dbkeys ) { - if ( !is_array( $dbkeys ) || count( $dbkeys ) != 2 ) { - throw new SMWDataItemException( 'Failed to create data item from DB keys.' ); - } - if ( $dbkeys[0] == '' ) { // empty blob: use "hash" string - return new SMWDIBlob( $dbkeys[1] ); - } else { - return new SMWDIBlob( $dbkeys[0] ); - } - } - - /** - * Method to make a hashed representation for strings of length greater - * than self::MAX_HASH_LENGTH to be used for selecting and sorting. - * - * @since 1.8 - * @param $string string - * - * @return string - */ - static protected function makeHash( $string ) { - if( strlen( $string ) <= self::MAX_HASH_LENGTH ) { - return $string; - } else { - return substr( $string, 0, self::MAX_HASH_LENGTH - 32 ) . md5( $string ); - } - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Bool.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Bool.php deleted file mode 100644 index bc5475c6..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Bool.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItemsHandlers - */ - -/** - * This class implements Store access to Boolean data items. - * - * @since 1.8 - * - * @author Nischay Nahata - * @ingroup SMWDataItemsHandlers - */ -class SMWDIHandlerBoolean extends SMWDataItemHandler { - - /** - * Method to return array of fields for a DI type - * - * @return array - */ - public function getTableFields() { - return array( 'o_value' => 'b' ); - } - - /** - * @see SMWDataItemHandler::getFetchFields() - * - * @since 1.8 - * @return array - */ - public function getFetchFields() { - return array( 'o_value' => 'b' ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * - * @return array - */ - public function getWhereConds( SMWDataItem $dataItem ) { - return array( - 'o_value' => $dataItem->getBoolean() ? 1 : 0, - ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * This array is used to perform all insert operations into the DB - * To optimize return minimum fields having indexes - * - * @return array - */ - public function getInsertValues( SMWDataItem $dataItem ) { - return array( - 'o_value' => $dataItem->getBoolean() ? 1 : 0, - ); - } - - /** - * Method to return the field used to select this type of DataItem - * @since 1.8 - * @return string - */ - public function getIndexField() { - return 'o_value'; - } - - /** - * Method to return the field used to select this type of DataItem - * using the label - * @since 1.8 - * @return string - */ - public function getLabelField() { - return 'o_value'; - } - - /** - * Method to create a dataitem from an array of DB keys. - * - * @since 1.8 - * @param array|string $dbkeys should be a string here - * - * @return SMWDataItem - */ - public function dataItemFromDBKeys( $dbkeys ) { - global $wgDBtype; - - //PgSQL returns as t and f and need special handling http://archives.postgresql.org/pgsql-php/2010-02/msg00005.php - if ( $wgDBtype == 'postgres' ) { - $value = ( $dbkeys == 't' ); - } else { - $value = ( $dbkeys == '1' ); - } - - return new SMWDIBoolean( $value ); - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Concept.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Concept.php deleted file mode 100644 index 841cf0a1..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Concept.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItemsHandlers - */ - -/** - * This class implements Store access to Concept data items. - * - * @note The table layout and behavior of this class is not coherent with the - * way that other DIs work. This is because of the unfortunate use of the - * concept table to store extra cache data, but also due to the design of - * concept DIs. This will be cleaned up at some point. - * - * @since 1.8 - * - * @author Nischay Nahata - * @ingroup SMWDataItemsHandlers - */ -class SMWDIHandlerConcept extends SMWDataItemHandler { - - /** - * Method to return array of fields for a DI type - * - * @return array - */ - public function getTableFields() { - return array( - 'concept_txt' => 'l', - 'concept_docu' => 'l', - 'concept_features' => 'n', - 'concept_size' => 'n', - 'concept_depth' => 'n', - 'cache_date' => 'j', - 'cache_count' => 'j' - ); - } - - /** - * @see SMWDataItemHandler::getFetchFields() - * - * @since 1.8 - * @return array - */ - public function getFetchFields() { - return array( - 'concept_txt' => 'l', - 'concept_docu' => 'l', - 'concept_features' => 'n', - 'concept_size' => 'n', - 'concept_depth' => 'n' - ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * - * @since 1.8 - * - * @param SMWDataItem $dataItem - * - * @return array - */ - public function getWhereConds( SMWDataItem $dataItem ) { - return array( - 'concept_txt' => $dataItem->getConceptQuery(), - 'concept_docu' => $dataItem->getDocumentation(), - 'concept_features' => $dataItem->getQueryFeatures(), - 'concept_size' => $dataItem->getSize(), - 'concept_depth' => $dataItem->getDepth() - ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * This array is used to perform all insert operations into the DB - * To optimize return minimum fields having indexes - * - * @since 1.8 - * - * @param SMWDataItem $dataItem - * - * @return array - */ - public function getInsertValues( SMWDataItem $dataItem ) { - return array( - 'concept_txt' => $dataItem->getConceptQuery(), - 'concept_docu' => $dataItem->getDocumentation(), - 'concept_features' => $dataItem->getQueryFeatures(), - 'concept_size' => $dataItem->getSize(), - 'concept_depth' => $dataItem->getDepth() - ); - } - - /** - * Method to return the field used to select this type of DataItem - * @since 1.8 - * @return string - */ - public function getIndexField() { - return 'concept_txt'; - } - - /** - * Method to return the field used to select this type of DataItem - * using the label - * @since 1.8 - * @return string - */ - public function getLabelField() { - return 'concept_txt'; - } - - /** - * Method to create a dataitem from an array of DB keys. - * - * @param array|string $dbkeys expecting array here - * - * @return SMWDataItem - */ - public function dataItemFromDBKeys( $dbkeys ) { - if ( is_array( $dbkeys) && count( $dbkeys ) == 5 ) { - return new \SMW\DIConcept( $dbkeys[0], smwfXMLContentEncode( $dbkeys[1] ), - $dbkeys[2], $dbkeys[3], $dbkeys[4] ); - } else { - throw new SMWDataItemException( 'Failed to create data item from DB keys.' ); - } - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_GeoCoord.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_GeoCoord.php deleted file mode 100644 index b5f2c511..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_GeoCoord.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItemsHandlers - */ - -/** - * This class implements store access to SMWDIGeoCoord data items. - * - * @since 1.8 - * - * @author Nischay Nahata - * @ingroup SMWDataItemsHandlers - */ -class SMWDIHandlerGeoCoord extends SMWDataItemHandler { - - /** - * Coordinates have three fields: a string version to keep the - * serialized value (exact), and two floating point columns for - * latitude and longitude (inexact, useful for bounding box selects). - * Altitude is not stored in an extra column since no operation uses - * this for anything so far. - * - * @see SMWDataItemHandler::getTableFields() - * @return array - */ - public function getTableFields() { - return array( 'o_serialized' => 't', 'o_lat' => 'f', 'o_lon' => 'f' ); - } - - /** - * @see SMWDataItemHandler::getFetchFields() - * - * @since 1.8 - * @return array - */ - public function getFetchFields() { - return array( 'o_serialized' => 't' ); - } - - /** - * @see SMWDataItemHandler::getTableIndexes() - * @return array - */ - public function getTableIndexes() { - return array( 'o_lat,o_lon' ); - } - - /** - * @see SMWDataItemHandler::getWhereConds() - * @return array - */ - public function getWhereConds( SMWDataItem $dataItem ) { - return array( - 'o_serialized' => $dataItem->getSerialization() - ); - } - - /** - * @see SMWDataItemHandler::getInsertValues() - * @return array - */ - public function getInsertValues( SMWDataItem $dataItem ) { - return array( - 'o_serialized' => $dataItem->getSerialization(), - 'o_lat' => $dataItem->getLatitude(), - 'o_lon' => $dataItem->getLongitude() - ); - } - - /** - * @see SMWDataItemHandler::getIndexField() - * @return string - */ - public function getIndexField() { - return 'o_serialized'; - } - - /** - * Coordinates do not have a general string version that - * could be used for string search, so this method returns - * no label column (empty string). - * - * @see SMWDataItemHandler::getLabelField() - * @since 1.8 - * @return string - */ - public function getLabelField() { - return ''; - } - - /** - * @see SMWDataItemHandler::dataItemFromDBKeys() - * @since 1.8 - * @param array|string $dbkeys expecting string here - * - * @return SMWDataItem - */ - public function dataItemFromDBKeys( $dbkeys ) { - if ( is_string( $dbkeys ) ) { - return SMWDIGeoCoord::doUnserialize( $dbkeys ); - } else { - throw new SMWDataItemException( 'Failed to create data item from DB keys.' ); - } - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Number.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Number.php deleted file mode 100644 index 79ec6889..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Number.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItemsHandlers - */ - -/** - * This class implements Store access to Number data items. - * - * @since 1.8 - * - * @author Nischay Nahata - * @ingroup SMWDataItemsHandlers - */ -class SMWDIHandlerNumber extends SMWDataItemHandler { - - /** - * @see SMWDataItemHandler::getTableFields() - * @return array - */ - public function getTableFields() { - return array( 'o_serialized' => 't', 'o_sortkey' => 'f' ); - } - - /** - * @see SMWDataItemHandler::getFetchFields() - * - * @since 1.8 - * @return array - */ - public function getFetchFields() { - return array( 'o_serialized' => 't' ); - } - - /** - * @see SMWDataItemHandler::getWhereConds - * @return array - */ - public function getWhereConds( SMWDataItem $dataItem ) { - return array( - 'o_sortkey' => floatval( $dataItem->getNumber() ) - ); - } - - /** - * @see SMWDataItemHandler::getInsertValues - * @return array - */ - public function getInsertValues( SMWDataItem $dataItem ) { - return array( - 'o_serialized' => $dataItem->getSerialization(), - 'o_sortkey' => floatval( $dataItem->getNumber() ) - ); - } - - /** - * @see SMWDataItemHandler::getIndexField - * @return string - */ - public function getIndexField() { - return 'o_sortkey'; - } - - /** - * @see SMWDataItemHandler::getLabelField - * @return string - */ - public function getLabelField() { - return ''; - } - - /** - * @see SMWDataItemHandler::dataItemFromDBKeys() - * @since 1.8 - * @param array|string $dbkeys expecting string here - * - * @return SMWDataItem - */ - public function dataItemFromDBKeys( $dbkeys ) { - if ( is_string( $dbkeys ) ) { - return SMWDINumber::doUnserialize( $dbkeys ); - } else { - throw new SMWDataItemException( 'Failed to create data item from DB keys.' ); - } - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Time.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Time.php deleted file mode 100644 index 081db598..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_Time.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItemsHandlers - */ - -/** - * This class implements Store access to Time data items. - * - * @since 1.8 - * - * @author Nischay Nahata - * @ingroup SMWDataItemsHandlers - */ -class SMWDIHandlerTime extends SMWDataItemHandler { - - /** - * Method to return array of fields for a DI type - * - * @return array - */ - public function getTableFields() { - return array( 'o_serialized' => 't', 'o_sortkey' => 'f' ); - } - - /** - * @see SMWDataItemHandler::getFetchFields() - * - * @since 1.8 - * @return array - */ - public function getFetchFields() { - return array( 'o_serialized' => 't' ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * - * @return array - */ - public function getWhereConds( SMWDataItem $dataItem ) { - return array( 'o_sortkey' => $dataItem->getSortKey() ); - } - - /** - * Method to return an array of fields=>values for a DataItem. - * This array is used to perform all insert operations into the DB. - * To optimize return minimum fields having indexes. - * - * @return array - */ - public function getInsertValues( SMWDataItem $dataItem ) { - return array( - 'o_serialized' => $dataItem->getSerialization(), - 'o_sortkey' => $dataItem->getSortKey() - ); - } - - /** - * This type is sorted by a numerical sortkey that maps time values to - * a time line. - * - * @since 1.8 - * @return string - */ - public function getIndexField() { - return 'o_sortkey'; - } - - /** - * This type does not have a label. The string value that we store - * internally is a technical serialisation that is not of interest for - * asking queries about, in particular since this serialisation might - * be changed. - * - * @since 1.8 - * @return string - */ - public function getLabelField() { - return ''; - } - - /** - * @see SMWDataItemHandler::dataItemFromDBKeys() - * @since 1.8 - * @param array|string $dbkeys expecting string here - * - * @return SMWDataItem - */ - public function dataItemFromDBKeys( $dbkeys ) { - if ( is_string( $dbkeys ) ) { - return SMWDITime::doUnserialize( $dbkeys ); - } else { - throw new SMWDataItemException( 'Failed to create data item from DB keys.' ); - } - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_URI.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_URI.php deleted file mode 100644 index 8c91f024..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_URI.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php -/** - * @file - * @ingroup SMWDataItemsHandlers - */ - -/** - * This class implements Store access to URI data items. - * - * @since 1.8 - * - * @author Nischay Nahata - * @ingroup SMWDataItemsHandlers - */ -class SMWDIHandlerUri extends SMWDataItemHandler { - - /** - * Method to return array of fields for a DI type - * - * @return array - */ - public function getTableFields() { - return array( 'o_serialized' => 't' ); - } - - /** - * @see SMWDataItemHandler::getFetchFields() - * - * @since 1.8 - * @return array - */ - public function getFetchFields() { - return array( 'o_serialized' => 't' ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * - * @return array - */ - public function getWhereConds( SMWDataItem $dataItem ) { - return array( 'o_serialized' => $dataItem->getSerialization() ); - } - - /** - * Method to return an array of fields=>values for a DataItem - * This array is used to perform all insert operations into the DB - * To optimize return minimum fields having indexes - * - * @return array - */ - public function getInsertValues( SMWDataItem $dataItem ) { - return array( 'o_serialized' => $dataItem->getSerialization() ); - } - - /** - * Method to return the field used to select this type of DataItem - * @since 1.8 - * @return string - */ - public function getIndexField() { - return 'o_serialized'; - } - - /** - * Method to return the field used to select this type of DataItem - * using the label - * @since 1.8 - * @return string - */ - public function getLabelField() { - return 'o_serialized'; - } - - /** - * @see SMWDataItemHandler::dataItemFromDBKeys() - * @since 1.8 - * @param array|string $dbkeys expecting string here - * - * @return SMWDataItem - */ - public function dataItemFromDBKeys( $dbkeys ) { - if ( is_string( $dbkeys ) ) { - return SMWDIUri::doUnserialize( $dbkeys ); - } else { - throw new SMWDataItemException( 'Failed to create data item from DB keys.' ); - } - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_WikiPage.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_WikiPage.php deleted file mode 100644 index 18faafb4..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DIHandler_WikiPage.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php -/** - * @file - * @author Nischay Nahata - * @author Markus Kroetzsch - * @ingroup SMWDataItemsHandlers - */ - -/** - * SMWDataItemHandler for dataitems of type SMWDIWikiPage. - * - * This handler is slightly different from other handlers since wikipages are - * stored in a separate table and referred to by numeric IDs. The handler thus - * returns IDs in most cases, but expects data from the SMW IDs table (with - * DBkey, namespace, interwiki, subobjectname) to be given for creating new - * dataitems. The store recognizes this special behavior from the field type - * 'p' that the handler reports for its only data field. - * - * @since 1.8 - * @ingroup SMWDataItemsHandlers - */ -class SMWDIHandlerWikiPage extends SMWDataItemHandler { - - /** - * @see SMWDataItemHandler::getTableFields() - * @since 1.8 - * @return array - */ - public function getTableFields() { - return array( 'o_id' => 'p' ); - } - - /** - * @see SMWDataItemHandler::getFetchFields() - * @since 1.8 - * @return array - */ - public function getFetchFields() { - return array( 'o_id' => 'p' ); - } - - /** - * @see SMWDataItemHandler::getTableIndexes() - * @since 1.8 - * @return array - */ - public function getTableIndexes() { - return array( 'o_id' ); - } - - /** - * @see SMWDataItemHandler::getWhereConds() - * @since 1.8 - * @param SMWDataItem $dataItem - * @return array - */ - public function getWhereConds( SMWDataItem $dataItem ) { - $oid = $this->store->smwIds->getSMWPageID( - $dataItem->getDBkey(), - $dataItem->getNamespace(), - $dataItem->getInterwiki(), - $dataItem->getSubobjectName() - ); - return array( 'o_id' => $oid ); - } - - /** - * @see SMWDataItemHandler::getInsertValues() - * @since 1.8 - * @param SMWDataItem $dataItem - * @return array - */ - public function getInsertValues( SMWDataItem $dataItem ) { - $oid = $this->store->smwIds->makeSMWPageID( - $dataItem->getDBkey(), - $dataItem->getNamespace(), - $dataItem->getInterwiki(), - $dataItem->getSubobjectName() - ); - return array( 'o_id' => $oid ); - } - - /** - * @see SMWDataItemHandler::getIndexField() - * @since 1.8 - * @return string - */ - public function getIndexField() { - return 'o_id'; - } - - /** - * @see SMWDataItemHandler::getLabelField() - * @since 1.8 - * @return string - */ - public function getLabelField() { - return 'o_id'; - } - - /** - * @see SMWDataItemHandler::dataItemFromDBKeys() - * @since 1.8 - * @param array|string $dbkeys expecting array here - * @throws SMWDataItemException - * @return SMWDataItem - */ - public function dataItemFromDBKeys( $dbkeys ) { - if ( is_array( $dbkeys ) && count( $dbkeys ) == 5 ) { - $namespace = intval( $dbkeys[1] ); - - if ( $namespace == SMW_NS_PROPERTY && $dbkeys[0] != '' && - $dbkeys[0]{0} == '_' && $dbkeys[2] == '' ) { - // Correctly interpret internal property keys - $property = new SMWDIProperty( $dbkeys[0] ); - $wikipage = $property->getDiWikiPage( $dbkeys[4] ); - if ( !is_null( $wikipage ) ) { - return $wikipage; - } - } else { - return new SMWDIWikiPage( $dbkeys[0], $namespace, $dbkeys[2], $dbkeys[4] ); - } - } - - throw new SMWDataItemException( 'Failed to create data item from DB keys.' ); - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DataItemHandler.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_DataItemHandler.php deleted file mode 100644 index 4a8ec124..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_DataItemHandler.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php -/** - * File holding abstract class SMWDataItemHandler, the base for all dataitem handlers in SMW. - * - * @author Nischay Nahata - * - * @file - * @ingroup SMWDataItemsHandlers - */ - -/** - * Classes extending this represent all store layout that is known about a certain dataitem - * - * @since 1.8 - * - * @ingroup SMWDataItemsHandlers - */ -abstract class SMWDataItemHandler { - - /** - * The store object. - * - * @since 1.8 - * @var SMWSQLStore3 - */ - protected $store; - - /** - * Constructor. - * - * @since 1.8 - * @param SMWSQLStore3 $store - */ - public function __construct( SMWSQLStore3 $store ){ - $this->store = $store; - } - - /** - * Return array of fields for a DI type. - * - * Tables declare value columns ("object fields") by specifying their - * name and type. Types are given using letters: - * - t for strings of the same maximal length as MediaWiki title names, - * - l for arbitrarily long strings; searching/sorting with such data - * may be limited for performance reasons, - * - w for strings as used in MediaWiki for encoding interwiki prefixes - * - n for namespace numbers (or other similar integers) - * - f for floating point numbers of double precision - * - p for a reference to an SMW ID as stored in the SMW IDs table; - * this corresponds to a data entry of ID "tnwt". - * - * @since 1.8 - * @return array - */ - abstract public function getTableFields(); - - /** - * Return an array with all the field names and types that need to be - * retrieved from the database in order to create a dataitem using - * dataItemFromDBKeys(). The result format is the same as for - * getTableFields(), but usually with fewer field names. - * - * @note In the future, we will most likely use a method that return - * only a single field name. Currently, we still need an array for - * concepts. - * - * @since 1.8 - * @return array - */ - abstract public function getFetchFields(); - - /** - * Return an array of additional indexes that should be provided for - * the table using this DI handler. By default, SMWSQLStore3 will - * already create indexes for all standard select operations, based - * on the indexfield provided by getIndexField(). Hence, most handlers - * do not need to define any indexes. - * - * @since 1.8 - * @return array - */ - public function getTableIndexes() { - return array(); - } - - /** - * Return an array of fields=>values to conditions (WHERE part) in SQL - * queries for the given SMWDataItem. This method can return fewer - * fields than getInstertValues as long as they are enough to identify - * an item for search. - * - * @since 1.8 - * @param SMWDataItem $dataItem - * @return array - */ - abstract public function getWhereConds( SMWDataItem $dataItem ); - - /** - * Return an array of fields=>values that is to be inserted when - * writing the given SMWDataItem to the database. Values should be set - * for all columns, even if NULL. This array is used to perform all - * insert operations into the DB. - * - * @since 1.8 - * @param SMWDataItem $dataItem - * @return array - */ - abstract public function getInsertValues( SMWDataItem $dataItem ); - - /** - * Return the field used to select this type of SMWDataItem. In - * particular, this identifies the column that is used to sort values - * of this kind. Every type of data returns a non-empty string here. - * - * @since 1.8 - * @return string - */ - abstract public function getIndexField(); - - /** - * Return the label field for this type of SMWDataItem. This should be - * a string column in the database table that can be used for selecting - * values using criteria such as "starts with". The return value can be - * empty if this is not supported. This is preferred for SMWDataItem - * classes that do not have an obvious canonical string writing anyway. - * - * The return value can be a column name or the empty string (if the - * give type of SMWDataItem does not have a label field). - * - * @since 1.8 - * @return string - */ - abstract public function getLabelField(); - - /** - * Create a dataitem from an array of DB keys or a single DB key - * string. May throw an SMWDataItemException if the given DB keys - * cannot be converted back into a dataitem. Each implementation - * of this method must otherwise run without errors for both array - * and string inputs. - * - * @since 1.8 - * @param array|string $dbkeys - * @throws SMWDataItemException - * @return SMWDataItem - */ - abstract public function dataItemFromDBKeys( $dbkeys ); - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3.php deleted file mode 100644 index 0f7ceb29..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3.php +++ /dev/null @@ -1,925 +0,0 @@ -<?php - -use SMW\SQLStore\PropertyTableDefinitionBuilder; -use SMW\SQLStore\WantedPropertiesCollector; -use SMW\SQLStore\UnusedPropertiesCollector; -use SMW\SQLStore\PropertiesCollector; -use SMW\SQLStore\StatisticsCollector; -use SMW\DataTypeRegistry; -use SMW\Settings; -use SMW\SQLStore\TableDefinition; -use SMW\MediaWiki\Database; -use SMW\MediaWiki\LazyDBConnectionProvider as DBConnectionProvider; -use SMW\DIWikiPage; -use SMW\DIProperty; -use SMW\SemanticData; - -/** - * SQL-based implementation of SMW's storage abstraction layer. - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author Nischay Nahata - * - * @since 1.8 - * - * @file - * @ingroup SMWStore - */ - -// The use of the following constants is explained in SMWSQLStore3::setup(): -define( 'SMW_SQL3_SMWIW_OUTDATED', ':smw' ); // virtual "interwiki prefix" for old-style special SMW objects (no longer used) -define( 'SMW_SQL3_SMWREDIIW', ':smw-redi' ); // virtual "interwiki prefix" for SMW objects that are redirected -define( 'SMW_SQL3_SMWBORDERIW', ':smw-border' ); // virtual "interwiki prefix" separating very important pre-defined properties from the rest -define( 'SMW_SQL3_SMWINTDEFIW', ':smw-intprop' ); // virtual "interwiki prefix" marking internal (invisible) predefined properties - -/** - * Storage access class for using the standard MediaWiki SQL database for - * keeping semantic data. - * - * @note Regarding the use of interwiki links in the store, there is currently - * no support for storing semantic data about interwiki objects, and hence - * queries that involve interwiki objects really make sense only for them - * occurring in object positions. Most methods still use the given input - * interwiki text as a simple way to filter out results that may be found if an - * interwiki object is given but a local object of the same name exists. It is - * currently not planned to support things like interwiki reuse of properties. - * - * @since 1.8 - * @ingroup SMWStore - */ -class SMWSQLStore3 extends SMWStore { - - /** - * Name of the table to store the concept cache in. - * - * @note This should never change. If it is changed, the concept caches - * will appear empty until they are recomputed. - */ - const CONCEPT_CACHE_TABLE = 'smw_concept_cache'; - - /** - * Name of the table to store the concept cache in. - * - * @note This should never change, but if it does then its contents can - * simply be rebuilt by running the setup. - */ - const PROPERTY_STATISTICS_TABLE = 'smw_prop_stats'; - - /** - * Object to access the SMW IDs table. - * - * @since 1.8 - * @var SMWSql3SmwIds - */ - public $smwIds; - - /** - * @var Database - * @since 1.9.0.2 - */ - protected $database = null; - - /** - * The reader object used by this store. Initialized by getReader() - * Always access using getReader() - * - * @since 1.8 - * @var SMWSQLStore3Readers - */ - protected $reader = false; - - /** - * The writer object used by this store. Initialized by getWriter(), - * which is the only way in which it should be accessed. - * - * @since 1.8 - * @var SMWSQLStore3Writers - */ - protected $writer = false; - - /** - * The SetupHandler object used by this store. Initialized by getSetupHandler(), - * which is the only way in which it should be accessed. - * - * @since 1.8 - * @var SMWSQLStore3SetupHandlers - */ - protected $setupHandler = false; - - /** - * Array of DIHandler objects used by this store. Initialized by getDIHandler(), - * which is the only way in which it should be accessed. - * - * @since 1.8 - * @var array - */ - protected $diHandlers = array(); - - /** - * Cache for SemanticData objects, indexed by SMW ID. - * - * @todo In the future, the cache should be managed by a helper class. - * - * @since 1.8 - * @var array - */ - public $m_semdata = array(); - - /** - * Like SMWSQLStore3::m_semdata, but containing flags indicating - * completeness of the SemanticData objs. - * - * @since 1.8 - * @var array - */ - public $m_sdstate = array(); - - /** - * Array for keeping property table table data, indexed by table id. - * Access this only by calling getPropertyTables(). - * - * @since 1.8 - * @var TableDefinition[] - */ - protected static $prop_tables; - - /** - * Array to cache "propkey => table id" associations for fixed property - * tables. Initialized by getPropertyTables(), which must be called - * before accessing this. - * - * @since 1.8 - * @var array|null - */ - protected static $fixedPropertyTableIds = null; - - /** - * Keys of special properties that should have their own - * fixed property table. - * - * @since 1.8 - * @var array - */ - protected static $customizableSpecialProperties = array( - '_MDAT', '_CDAT', '_NEWP', '_LEDT', '_MIME', '_MEDIA', - ); - - protected static $fixedSpecialProperties = array( - // property declarations - '_TYPE', '_UNIT', '_CONV', '_PVAL', '_LIST', '_SERV', - // query statistics (very frequently used) - '_ASK', '_ASKDE', '_ASKSI', '_ASKFO', '_ASKST', '_ASKDU', - // subproperties, classes, and instances - '_SUBP', '_SUBC', '_INST', - // redirects - '_REDI', - // has sub object - '_SOBJ', - // vocabulary import and URI assignments - '_IMPO', '_URI', - // Concepts - '_CONC', - // Semantic forms properties: - '_SF_DF', '_SF_AF', // FIXME if this is desired by SF than it should set up $smwgFixedProperties - ); - - /** - * Default tables to use for storing data of certain types. - * - * @since 1.8 - * @var array - */ - protected static $di_type_tables = array( - SMWDataItem::TYPE_NUMBER => 'smw_di_number', - SMWDataItem::TYPE_BLOB => 'smw_di_blob', - SMWDataItem::TYPE_BOOLEAN => 'smw_di_bool', - SMWDataItem::TYPE_URI => 'smw_di_uri', - SMWDataItem::TYPE_TIME => 'smw_di_time', - SMWDataItem::TYPE_GEO => 'smw_di_coords', // currently created only if Semantic Maps are installed - SMWDataItem::TYPE_WIKIPAGE => 'smw_di_wikipage', - //SMWDataItem::TYPE_CONCEPT => '', // _CONC is the only property of this type - ); - - /** - * Constructor. - * - * @since 1.8 - */ - public function __construct() { - $this->smwIds = new SMWSql3SmwIds( $this ); - } - - /** - * Get an object of the dataitem handler from the dataitem provided. - * - * @since 1.8 - * @param integer $diType - * @throws MWException if no handler exists for the given type - * @return SMWDataItemHandler - */ - public function getDataItemHandlerForDIType( $diType ) { - if( !array_key_exists( $diType, $this->diHandlers ) ) { - switch ( $diType ) { - case SMWDataItem::TYPE_NUMBER: - $this->diHandlers[$diType] = new SMWDIHandlerNumber( $this ); - break; - case SMWDataItem::TYPE_BLOB: - $this->diHandlers[$diType] = new SMWDIHandlerBlob( $this ); - break; - case SMWDataItem::TYPE_BOOLEAN: - $this->diHandlers[$diType] = new SMWDIHandlerBoolean( $this ); - break; - case SMWDataItem::TYPE_URI: - $this->diHandlers[$diType] = new SMWDIHandlerUri( $this ); - break; - case SMWDataItem::TYPE_TIME: - $this->diHandlers[$diType] = new SMWDIHandlerTime( $this ); - break; - case SMWDataItem::TYPE_GEO: - $this->diHandlers[$diType] = new SMWDIHandlerGeoCoord( $this ); - break; - case SMWDataItem::TYPE_WIKIPAGE: - $this->diHandlers[$diType] = new SMWDIHandlerWikiPage( $this ); - break; - case SMWDataItem::TYPE_CONCEPT: - $this->diHandlers[$diType] = new SMWDIHandlerConcept( $this ); - break; - case SMWDataItem::TYPE_PROPERTY: - throw new MWException( "There is no DI handler for SMWDataItem::TYPE_PROPERTY." ); - case SMWDataItem::TYPE_CONTAINER: - throw new MWException( "There is no DI handler for SMWDataItem::TYPE_CONTAINER." ); - case SMWDataItem::TYPE_ERROR: - throw new MWException( "There is no DI handler for SMWDataItem::TYPE_ERROR." ); - default: - throw new MWException( "The value \"$diType\" is not a valid dataitem ID." ); - } - } - return $this->diHandlers[$diType]; - } - - /** - * Convenience method to get a dataitem handler for a datatype id. - * - * @since 1.8 - * @param string $typeid - * @throws MWException if there is no handler for this type - * @return SMWDataItemHandler - */ - public function getDataItemHandlerForDatatype( $typeid ) { - $dataItemId = DataTypeRegistry::getInstance()->getDataItemId( $typeid ); - return $this->getDataItemHandlerForDIType( $dataItemId ); - } - -///// Reading methods ///// - - public function getReader() { - if( $this->reader == false ) - $this->reader = new SMWSQLStore3Readers( $this );//Initialize if not done already - - return $this->reader; - } - - public function getSemanticData( DIWikiPage $subject, $filter = false ) { - return $this->getReader()->getSemanticData( $subject, $filter ); - } - - public function getPropertyValues( $subject, DIProperty $property, $requestoptions = null ) { - return $this->getReader()->getPropertyValues( $subject, $property, $requestoptions ); - } - - public function getPropertySubjects( DIProperty $property, $value, $requestoptions = null ) { - return $this->getReader()->getPropertySubjects( $property, $value, $requestoptions ); - } - - public function getAllPropertySubjects( DIProperty $property, $requestoptions = null ) { - return $this->getReader()->getAllPropertySubjects( $property, $requestoptions ); - } - - public function getProperties( DIWikiPage $subject, $requestoptions = null ) { - return $this->getReader()->getProperties( $subject, $requestoptions ); - } - - public function getInProperties( SMWDataItem $value, $requestoptions = null ) { - return $this->getReader()->getInProperties( $value, $requestoptions ); - } - - -///// Writing methods ///// - - - public function getWriter() { - if( $this->writer == false ) - $this->writer = new SMWSQLStore3Writers( $this );//Initialize if not done already - - return $this->writer; - } - - public function deleteSubject( Title $subject ) { - return $this->getWriter()->deleteSubject( $subject ); - } - - protected function doDataUpdate( SemanticData $data ) { - return $this->getWriter()->doDataUpdate( $data ); - } - - public function changeTitle( Title $oldtitle, Title $newtitle, $pageid, $redirid = 0 ) { - return $this->getWriter()->changeTitle( $oldtitle, $newtitle, $pageid, $redirid ); - } - - -///// Query answering ///// - - /** - * @see SMWStore::getQueryResult - * - * @since 1.8 - * @param SMWQuery $query - * @return SMWQueryResult|string|integer depends on $query->querymode - */ - public function getQueryResult( SMWQuery $query ) { - wfProfileIn( 'SMWSQLStore3::getQueryResult (SMW)' ); - - $qe = new SMWSQLStore3QueryEngine( $this, wfGetDB( DB_SLAVE ) ); - $result = $qe->getQueryResult( $query ); - wfProfileOut( 'SMWSQLStore3::getQueryResult (SMW)' ); - - return $result; - } - -///// Special page functions ///// - - public function getPropertiesSpecial( $requestoptions = null ) { - - $propertiesCollector = new PropertiesCollector( - $this, - wfGetDB( DB_SLAVE ), - Settings::newFromGlobals() - ); - - return $propertiesCollector->setRequestOptions( $requestoptions ); - } - - public function getUnusedPropertiesSpecial( $requestoptions = null ) { - - $unusedPropertiesCollector = new UnusedPropertiesCollector( - $this, - wfGetDB( DB_SLAVE ), - Settings::newFromGlobals() - ); - - return $unusedPropertiesCollector->setRequestOptions( $requestoptions ); - } - - public function getWantedPropertiesSpecial( $requestoptions = null ) { - - $wantedPropertiesCollector = new WantedPropertiesCollector( - $this, - wfGetDB( DB_SLAVE ), - Settings::newFromGlobals() - ); - - return $wantedPropertiesCollector->setRequestOptions( $requestoptions ); - } - - public function getStatistics() { - - $statisticsCollector = new StatisticsCollector( - $this, - wfGetDB( DB_SLAVE ), - Settings::newFromGlobals() - ); - - return $statisticsCollector->getResults(); - } - - -///// Setup store ///// - - public function getSetupHandler() { - if( $this->setupHandler == false ) - $this->setupHandler = new SMWSQLStore3SetupHandlers( $this );//Initialize if not done already - - return $this->setupHandler; - } - - public function setup( $verbose = true ) { - return $this->getSetupHandler()->setup( $verbose ); - } - - public function drop( $verbose = true ) { - return $this->getSetupHandler()->drop( $verbose ); - } - - public function refreshData( &$index, $count, $namespaces = false, $usejobs = true ) { - return $this->getSetupHandler()->refreshData( $index, $count, $namespaces, $usejobs ); - } - - -///// Concept caching ///// - - /** - * Refresh the concept cache for the given concept. - * - * @since 1.8 - * @param Title $concept - * @return array of error strings (empty if no errors occurred) - */ - public function refreshConceptCache( Title $concept ) { - wfProfileIn( 'SMWSQLStore3::refreshConceptCache (SMW)' ); - - $qe = new SMWSQLStore3QueryEngine( $this, wfGetDB( DB_MASTER ) ); - $result = $qe->refreshConceptCache( $concept ); - - wfProfileOut( 'SMWSQLStore3::refreshConceptCache (SMW)' ); - - return $result; - } - - /** - * Delete the concept cache for the given concept. - * - * @since 1.8 - * @param Title $concept - */ - public function deleteConceptCache( $concept ) { - wfProfileIn( 'SMWSQLStore3::deleteConceptCache (SMW)' ); - - $qe = new SMWSQLStore3QueryEngine( $this, wfGetDB( DB_MASTER ) ); - $result = $qe->deleteConceptCache( $concept ); - - wfProfileOut( 'SMWSQLStore3::deleteConceptCache (SMW)' ); - - return $result; - } - - /** - * Return status of the concept cache for the given concept as an array - * with key 'status' ('empty': not cached, 'full': cached, 'no': not - * cachable). If status is not 'no', the array also contains keys 'size' - * (query size), 'depth' (query depth), 'features' (query features). If - * status is 'full', the array also contains keys 'date' (timestamp of - * cache), 'count' (number of results in cache). - * - * @since 1.8 - * @param Title|SMWWikiPageValue $concept - * - * @return SMW\DIConcept|null - */ - public function getConceptCacheStatus( $concept ) { - wfProfileIn( 'SMWSQLStore3::getConceptCacheStatus (SMW)' ); - - $db = $this->getDatabase(); - - $cid = $this->smwIds->getSMWPageID( - $concept->getDBkey(), - $concept->getNamespace(), - '', - '', - false - ); - - $row = $db->selectRow( - 'smw_fpt_conc', - array( 'concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date', 'cache_count' ), - array( 's_id' => $cid ), - __METHOD__ - ); - - if ( $row !== false ) { - - $dataItem = new SMW\DIConcept( - $concept, - null, - $row->concept_features, - $row->concept_size, - $row->concept_depth - ); - - if ( $row->cache_date ) { - $dataItem->setCacheStatus( 'full' ); - $dataItem->setCacheDate( $row->cache_date ); - $dataItem->setCacheCount( $row->cache_count ); - } else { - $dataItem->setCacheStatus( 'empty' ); - } - $result = $dataItem; - } else { - $result = null; - } - - wfProfileOut( 'SMWSQLStore3::getConceptCacheStatus (SMW)' ); - - return $result; - } - - -///// Helper methods, mostly protected ///// - - /** - * Transform input parameters into a suitable array of SQL options. - * The parameter $valuecol defines the string name of the column to which - * sorting requests etc. are to be applied. - * - * @since 1.8 - * @param SMWRequestOptions|null $requestoptions - * @param string $valuecol - * @return array - */ - public function getSQLOptions( SMWRequestOptions $requestoptions = null, $valuecol = '' ) { - $sql_options = array(); - - if ( $requestoptions !== null ) { - if ( $requestoptions->limit > 0 ) { - $sql_options['LIMIT'] = $requestoptions->limit; - } - - if ( $requestoptions->offset > 0 ) { - $sql_options['OFFSET'] = $requestoptions->offset; - } - - if ( ( $valuecol !== '' ) && ( $requestoptions->sort ) ) { - $sql_options['ORDER BY'] = $requestoptions->ascending ? $valuecol : $valuecol . ' DESC'; - } - } - - return $sql_options; - } - - /** - * Transform input parameters into a suitable string of additional SQL - * conditions. The parameter $valuecol defines the string name of the - * column to which value restrictions etc. are to be applied. - * - * @since 1.8 - * @param SMWRequestOptions|null $requestoptions - * @param string $valuecol name of SQL column to which conditions apply - * @param string $labelcol name of SQL column to which string conditions apply, if any - * @param boolean $addand indicate whether the string should begin with " AND " if non-empty - * @return string - */ - public function getSQLConditions( SMWRequestOptions $requestoptions = null, $valuecol = '', $labelcol = '', $addand = true ) { - $sql_conds = ''; - - if ( $requestoptions !== null ) { - $db = wfGetDB( DB_SLAVE ); /// TODO avoid doing this here again, all callers should have one - - if ( ( $valuecol !== '' ) && ( $requestoptions->boundary !== null ) ) { // Apply value boundary. - if ( $requestoptions->ascending ) { - $op = $requestoptions->include_boundary ? ' >= ' : ' > '; - } else { - $op = $requestoptions->include_boundary ? ' <= ' : ' < '; - } - $sql_conds .= ( $addand ? ' AND ' : '' ) . $valuecol . $op . $db->addQuotes( $requestoptions->boundary ); - } - - if ( $labelcol !== '' ) { // Apply string conditions. - foreach ( $requestoptions->getStringConditions() as $strcond ) { - $string = str_replace( '_', '\_', $strcond->string ); - - switch ( $strcond->condition ) { - case SMWStringCondition::STRCOND_PRE: $string .= '%'; break; - case SMWStringCondition::STRCOND_POST: $string = '%' . $string; break; - case SMWStringCondition::STRCOND_MID: $string = '%' . $string . '%'; break; - } - - $sql_conds .= ( ( $addand || ( $sql_conds !== '' ) ) ? ' AND ' : '' ) . $labelcol . ' LIKE ' . $db->addQuotes( $string ); - } - } - } - - return $sql_conds; - } - - /** - * Not in all cases can requestoptions be forwarded to the DB using - * getSQLConditions() and getSQLOptions(): some data comes from caches - * that do not respect the options yet. This method takes an array of - * results (SMWDataItem objects) *of the same type* and applies the - * given requestoptions as appropriate. - * - * @since 1.8 - * @param array $data array of SMWDataItem objects - * @param SMWRequestOptions|null $requestoptions - * @return SMWDataItem[] - */ - public function applyRequestOptions( array $data, SMWRequestOptions $requestoptions = null ) { - wfProfileIn( "SMWSQLStore3::applyRequestOptions (SMW)" ); - - if ( ( count( $data ) == 0 ) || is_null( $requestoptions ) ) { - wfProfileOut( "SMWSQLStore3::applyRequestOptions (SMW)" ); - return $data; - } - - $result = array(); - $sortres = array(); - - $sampleDataItem = reset( $data ); - $numeric = is_numeric( $sampleDataItem->getSortKey() ); - - $i = 0; - - foreach ( $data as $item ) { - $ok = true; // keep datavalue only if this remains true - - if ( $item instanceof DIWikiPage ) { - $label = $this->getWikiPageSortKey( $item ); - $value = $label; - } else { - $label = ( $item instanceof SMWDIBlob ) ? $item->getString() : ''; - $value = $item->getSortKey(); - } - - if ( $requestoptions->boundary !== null ) { // apply value boundary - $strc = $numeric ? 0 : strcmp( $value, $requestoptions->boundary ); - - if ( $requestoptions->ascending ) { - if ( $requestoptions->include_boundary ) { - $ok = $numeric ? ( $value >= $requestoptions->boundary ) : ( $strc >= 0 ); - } else { - $ok = $numeric ? ( $value > $requestoptions->boundary ) : ( $strc > 0 ); - } - } else { - if ( $requestoptions->include_boundary ) { - $ok = $numeric ? ( $value <= $requestoptions->boundary ) : ( $strc <= 0 ); - } else { - $ok = $numeric ? ( $value < $requestoptions->boundary ) : ( $strc < 0 ); - } - } - } - - foreach ( $requestoptions->getStringConditions() as $strcond ) { // apply string conditions - switch ( $strcond->condition ) { - case SMWStringCondition::STRCOND_PRE: - $ok = $ok && ( strpos( $label, $strcond->string ) === 0 ); - break; - case SMWStringCondition::STRCOND_POST: - $ok = $ok && ( strpos( strrev( $label ), strrev( $strcond->string ) ) === 0 ); - break; - case SMWStringCondition::STRCOND_MID: - $ok = $ok && ( strpos( $label, $strcond->string ) !== false ); - break; - } - } - - if ( $ok ) { - $result[$i] = $item; - $sortres[$i] = $value; - $i++; - } - } - - if ( $requestoptions->sort ) { - $flag = $numeric ? SORT_NUMERIC : SORT_LOCALE_STRING; - - if ( $requestoptions->ascending ) { - asort( $sortres, $flag ); - } else { - arsort( $sortres, $flag ); - } - - $newres = array(); - - foreach ( $sortres as $key => $value ) { - $newres[] = $result[$key]; - } - - $result = $newres; - } - - if ( $requestoptions->limit > 0 ) { - $result = array_slice( $result, $requestoptions->offset, $requestoptions->limit ); - } else { - $result = array_slice( $result, $requestoptions->offset ); - } - - wfProfileOut( "SMWSQLStore3::applyRequestOptions (SMW)" ); - - return $result; - } - - /** - * Find the id of a property table that is suitable for storing values of - * the given type. The type is specified by an SMW type id such as '_wpg'. - * An empty string is returned if no matching table could be found. - * - * @since 1.8 - * @param string $typeid - * @return string - */ - public function findTypeTableId( $typeid ) { - $dataItemId = DataTypeRegistry::getInstance()->getDataItemId( $typeid ); - return $this->findDiTypeTableId( $dataItemId ); - } - - /** - * Find the id of a property table that is normally used to store - * data items of the given type. The empty string is returned if - * no such table exists. - * - * @since 1.8 - * @param integer $dataItemId - * @return string - */ - public function findDiTypeTableId( $dataItemId ) { - if ( array_key_exists( $dataItemId, self::$di_type_tables ) ) { - return self::$di_type_tables[$dataItemId]; - } else { - return ''; - } - } - - /** - * Retrieve the id of the property table that is to be used for storing - * values for the given property object. - * - * @since 1.8 - * @param DIProperty $diProperty - * @return string - */ - public function findPropertyTableID( DIProperty $diProperty ) { - $propertyKey = $diProperty->getKey(); - - // This is needed to initialize the $fixedPropertyTableIds field - $this->getPropertyTables(); - - if ( array_key_exists( $propertyKey, self::$fixedPropertyTableIds ) ) { - return self::$fixedPropertyTableIds[$propertyKey]; - } else { - return $this->findTypeTableId( $diProperty->findPropertyTypeID() ); - } - } - - /** - * Change an SMW page id across all relevant tables. The redirect table - * is also updated (without much effect if the change happended due to - * some redirect, since the table should not contain the id of the - * redirected page). If namespaces are given, then they are used to - * delete any entries that are limited to one particular namespace (e.g. - * only properties can be used as properties) instead of moving them. - * - * The id in the SMW IDs table is not touched. - * - * @note This method only changes internal page IDs in SMW. It does not - * assume any change in (title-related) data, as e.g. in a page move. - * Internal objects (subobject) do not need to be updated since they - * refer to the title of their parent page, not to its ID. - * - * @since 1.8 - * @param integer $oldid numeric ID that is to be changed - * @param integer $newid numeric ID to which the records are to be changed - * @param integer $oldnamespace namespace of old id's page (-1 to ignore it) - * @param integer $newnamespace namespace of new id's page (-1 to ignore it) - * @param boolean $sdata stating whether to update subject references - * @param boolean $podata stating if to update property/object references - */ - public function changeSMWPageID( $oldid, $newid, $oldnamespace = -1, - $newnamespace = -1, $sdata = true, $podata = true ) { - $db = wfGetDB( DB_MASTER ); - - // Change all id entries in property tables: - foreach ( $this->getPropertyTables() as $proptable ) { - if ( $sdata && $proptable->usesIdSubject() ) { - $db->update( $proptable->getName(), array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ ); - } - - if ( $podata ) { - if ( ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_PROPERTY ) ) && ( !$proptable->isFixedPropertyTable() ) ) { - if ( ( $newnamespace == -1 ) || ( $newnamespace == SMW_NS_PROPERTY ) ) { - $db->update( $proptable->getName(), array( 'p_id' => $newid ), array( 'p_id' => $oldid ), __METHOD__ ); - } else { - $db->delete( $proptable->getName(), array( 'p_id' => $oldid ), __METHOD__ ); - } - } - - foreach ( $proptable->getFields( $this ) as $fieldname => $type ) { - if ( $type == 'p' ) { - $db->update( $proptable->getName(), array( $fieldname => $newid ), array( $fieldname => $oldid ), __METHOD__ ); - } - } - } - } - - // Change id entries in concept-related tables: - if ( $sdata && ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_CONCEPT ) ) ) { - if ( ( $newnamespace == -1 ) || ( $newnamespace == SMW_NS_CONCEPT ) ) { - $db->update( 'smw_fpt_conc', array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ ); - $db->update( SMWSQLStore3::CONCEPT_CACHE_TABLE, array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ ); - } else { - $db->delete( 'smw_fpt_conc', array( 's_id' => $oldid ), __METHOD__ ); - $db->delete( SMWSQLStore3::CONCEPT_CACHE_TABLE, array( 's_id' => $oldid ), __METHOD__ ); - } - } - - if ( $podata ) { - $db->update( SMWSQLStore3::CONCEPT_CACHE_TABLE, array( 'o_id' => $newid ), array( 'o_id' => $oldid ), __METHOD__ ); - } - } - - /** - * Return the array of predefined property table declarations, initialising - * it if necessary. The result is an array of SMWSQLStore3Table objects - * indexed by table ids. - * - * It is ensured that the keys of the returned array agree with the name of - * the table that they refer to. - * - * @since 1.8 - * @return TableDefinition[] - */ - public function getPropertyTables() { - - // Definitions are kept static to prevent them from being initialised twice - if ( isset( self::$prop_tables ) ) { - return self::$prop_tables; - } - - $enabledSpecialProperties = self::$fixedSpecialProperties; - $customizableSpecialProperties = array_flip( self::$customizableSpecialProperties ); - - $customFixedProperties = self::$configuration->get( 'smwgFixedProperties' ); - $customSpecialProperties = self::$configuration->get( 'smwgPageSpecialProperties' ); - - foreach ( $customSpecialProperties as $property ) { - if ( isset( $customizableSpecialProperties[$property] ) ) { - $enabledSpecialProperties[] = $property; - } - } - - $definitionBuilder = new PropertyTableDefinitionBuilder( - self::$di_type_tables, - $enabledSpecialProperties, - $customFixedProperties - ); - - $definitionBuilder->runBuilder(); - - self::$prop_tables = $definitionBuilder->getTableDefinitions(); - self::$fixedPropertyTableIds = $definitionBuilder->getTableIds(); - - return self::$prop_tables; - } - - /** - * Returns SMW Id object - * - * @since 1.9 - * - * @return SMWSql3SmwIds - */ - public function getObjectIds() { - return $this->smwIds; - } - - /** - * Returns the statics table - * - * @since 1.9 - * - * @return string - */ - public function getStatisticsTable() { - return self::PROPERTY_STATISTICS_TABLE; - } - - /** - * Resets internal objects - * - * @since 1.9.1.1 - */ - public function clear() { - self::$prop_tables = null; - $this->getObjectIds()->clearCaches(); - } - - /** - * @since 1.9.0.2 - * - * @param Database $database - */ - public function setDatabase( Database $database ) { - $this->database = $database; - return $this; - } - - /** - * @note DB_SLAVE (for read queries) or DB_MASTER (for write queries and read - * queries that need the newest information) - * - * @since 1.9.0.2 - * - * @return Database - */ - public function getDatabase() { - - if ( $this->database === null ) { - $this->database = new Database( - new DBConnectionProvider( DB_SLAVE ), - new DBConnectionProvider( DB_MASTER ) - ); - } - - return $this->database; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Queries.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Queries.php deleted file mode 100644 index 13dd273f..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Queries.php +++ /dev/null @@ -1,1256 +0,0 @@ -<?php - -use SMW\DataTypeRegistry; -use SMW\QueryOutputFormatter; - -/** - * Class for representing a single (sub)query description. Simple data - * container. - * - * @since 1.8 - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @ingroup SMWStore - */ -class SMWSQLStore3Query { - - /// Type of empty query without usable condition, dropped as soon as - /// discovered. This is used only during preparing the query (no - /// queries of this type should ever be added). - const Q_NOQUERY = 0; - /// Type of query that is a join with a query (jointable: internal - /// table name; joinfield/components/where use alias.fields; - /// from uses external table names, components interpreted - /// conjunctively (JOIN)). - const Q_TABLE = 1; - /// Type of query that matches a constant value (joinfield is a - /// disjunctive array of unquoted values, jointable empty, components - /// empty). - const Q_VALUE = 2; - /// Type of query that is a disjunction of other queries - /// (joinfield/jointable empty; only components relevant) - const Q_DISJUNCTION = 3; - /// Type of query that is a conjunction of other queries - /// (joinfield/jointable empty; only components relevant). - const Q_CONJUNCTION = 4; - /// Type of query that creates a temporary table of all superclasses - /// of given classes (only joinfield relevant: (disjunctive) array of - /// unquoted values). - const Q_CLASS_HIERARCHY = 5; - /// Type of query that creates a temporary table of all superproperties - /// of given properties (only joinfield relevant: (disjunctive) array - /// of unquoted values). - const Q_PROP_HIERARCHY = 6; - - public $type = SMWSQLStore3Query::Q_TABLE; - public $jointable = ''; - public $joinfield = ''; - public $from = ''; - public $where = ''; - public $components = array(); - - /** - * The alias to be used for jointable; read-only after construct! - * @var string - */ - public $alias; - - /** - * property dbkey => db field; passed down during query execution. - * @var array - */ - public $sortfields = array(); - - public $queryNumber; - - public static $qnum = 0; - - public function __construct() { - $this->queryNumber = self::$qnum; - $this->alias = 't' . self::$qnum; - self::$qnum++; - } -} - -/** - * Class that implements query answering for SMWSQLStore3. - * @ingroup SMWStore - */ -class SMWSQLStore3QueryEngine { - - /** Database slave to be used */ - protected $m_dbs; // TODO: should temporary tables be created on the master DB? - /** Parent SMWSQLStore3. */ - protected $m_store; - /** Query mode copied from given query. Some submethods act differently when in SMWQuery::MODE_DEBUG. */ - protected $m_qmode; - /** Array of generated SMWSQLStore3Query query descriptions (index => object). */ - protected $m_queries = array(); - /** Array of arrays of executed queries, indexed by the temporary table names results were fed into. */ - protected $m_querylog = array(); - /** - * Array of sorting requests ("Property_name" => "ASC"/"DESC"). Used during query - * processing (where these property names are searched while compiling the query - * conditions). - */ - protected $m_sortkeys; - /** Cache of computed hierarchy queries for reuse ("catetgory/property value string" => "tablename"). */ - protected $m_hierarchies = array(); - /** Local collection of error strings, passed on to callers if possible. */ - protected $m_errors = array(); - - public function __construct( SMWSQLStore3 $parentstore, $dbslave ) { - $this->m_store = $parentstore; - $this->m_dbs = $dbslave; - } - - /** - * Refresh the concept cache for the given concept. - * - * @since 1.8 - * @param $concept Title - * @return array of error strings (empty if no errors occurred) - */ - public function refreshConceptCache( Title $concept ) { - global $smwgQMaxLimit, $smwgQConceptFeatures, $wgDBtype; - - $fname = 'SMW::refreshConceptCache'; - - $db = $this->m_store->getDatabase(); - - $cid = $this->m_store->smwIds->getSMWPageID( $concept->getDBkey(), SMW_NS_CONCEPT, '', '' ); - $cid_c = $this->m_store->smwIds->getSMWPageID( $concept->getDBkey(), SMW_NS_CONCEPT, '', '', false ); - - if ( $cid != $cid_c ) { - $this->m_errors[] = "Skipping redirect concept."; - return $this->m_errors; - } - - $values = $this->m_store->getPropertyValues( - SMWDIWikiPage::newFromTitle( $concept ), - new SMWDIProperty( '_CONC' ) - ); - - $di = end( $values ); - $desctxt = ( $di !== false ) ? $di->getConceptQuery() : false; - $this->m_errors = array(); - - if ( $desctxt ) { // concept found - $this->m_qmode = SMWQuery::MODE_INSTANCES; - $this->m_queries = array(); - $this->m_hierarchies = array(); - $this->m_querylog = array(); - $this->m_sortkeys = array(); - SMWSQLStore3Query::$qnum = 0; - - // Pre-process query: - $qp = new SMWQueryParser( $smwgQConceptFeatures ); - $desc = $qp->getQueryDescription( $desctxt ); - $qid = $this->compileQueries( $desc ); - - if ( $qid < 0 ) { - return; - } - - $this->executeQueries( $this->m_queries[$qid] ); // execute query tree, resolve all dependencies - $qobj = $this->m_queries[$qid]; - - if ( $qobj->joinfield === '' ) { - return; - } - - // Update database: - $db->delete( - SMWSQLStore3::CONCEPT_CACHE_TABLE, - array( 'o_id' => $cid ), - __METHOD__ - ); - - $smw_conccache = $db->tablename( SMWSQLStore3::CONCEPT_CACHE_TABLE ); - - if ( $wgDBtype == 'postgres' ) { // PostgresQL: no INSERT IGNORE, check for duplicates explicitly - $where = $qobj->where . ( $qobj->where ? ' AND ' : '' ) . - "NOT EXISTS (SELECT NULL FROM $smw_conccache" . - " WHERE {$smw_conccache}.s_id = {$qobj->alias}.s_id " . - " AND {$smw_conccache}.o_id = {$qobj->alias}.o_id )"; - } else { // MySQL just uses INSERT IGNORE, no extra conditions - $where = $qobj->where; - } - - $db->query( "INSERT " . ( ( $wgDBtype == 'postgres' ) ? '' : 'IGNORE ' ) . - "INTO $smw_conccache" . - " SELECT DISTINCT {$qobj->joinfield} AS s_id, $cid AS o_id FROM " . - $db->tableName( $qobj->jointable ) . " AS {$qobj->alias}" . - $qobj->from . - ( $where ? ' WHERE ' : '' ) . $where . " LIMIT $smwgQMaxLimit", - $fname ); - - $db->update( - 'smw_fpt_conc', - array( 'cache_date' => strtotime( "now" ), 'cache_count' => $db->affectedRows() ), - array( 's_id' => $cid ), - __METHOD__ - ); - - } else { // no concept found; just delete old data if there is any - - $db->delete( - SMWSQLStore3::CONCEPT_CACHE_TABLE, - array( 'o_id' => $cid ), - __METHOD__ - ); - - $db->update( - 'smw_fpt_conc', - array( 'cache_date' => null, 'cache_count' => null ), - array( 's_id' => $cid ), - __METHOD__ - ); - - $this->m_errors[] = "No concept description found."; - } - - $this->cleanUp(); - - return $this->m_errors; - } - - /** - * Delete the concept cache for the given concept. - * - * @param $concept Title - */ - public function deleteConceptCache( $concept ) { - - $db = $this->m_store->getDatabase(); - - $cid = $this->m_store->smwIds->getSMWPageID( - $concept->getDBkey(), - SMW_NS_CONCEPT, - '', - '', - false - ); - - $db->delete( - SMWSQLStore3::CONCEPT_CACHE_TABLE, - array( 'o_id' => $cid ), - __METHOD__ - ); - - $db->update( - 'smw_fpt_conc', - array( 'cache_date' => null, 'cache_count' => null ), - array( 's_id' => $cid ), - __METHOD__ - ); - } - - /** - * The new SQL store's implementation of query answering. This function - * works in two stages: First, the nested conditions of the given query - * object are preprocessed to compute an abstract representation of the - * SQL query that is to be executed. Since query conditions correspond to - * joins with property tables in most cases, this abstract representation - * is essentially graph-like description of how property tables are joined. - * Moreover, this graph is tree-shaped, since all query conditions are - * tree-shaped. Each part of this abstract query structure is represented - * by an SMWSQLStore3Query object in the array m_queries. - * - * As a second stage of processing, the thus prepared SQL query is actually - * executed. Typically, this means that the joins are collapsed into one - * SQL query to retrieve results. In some cases, such as in dbug mode, the - * execution might be restricted and not actually perform the whole query. - * - * The two-stage process helps to separate tasks, and it also allows for - * better optimisations: it is left to the execution engine how exactly the - * query result is to be obtained. For example, one could pre-compute - * partial suib-results in temporary tables (or even cache them somewhere), - * instead of passing one large join query to the DB (of course, it might - * be large only if the configuration of SMW allows it). For some DBMS, a - * step-wise execution of the query might lead to better performance, since - * it exploits the tree-structure of the joins, which is important for fast - * processing -- not all DBMS might be able in seeing this by themselves. - * - * @param SMWQuery $query - * - * @return mixed: depends on $query->querymode - */ - public function getQueryResult( SMWQuery $query ) { - global $smwgIgnoreQueryErrors, $smwgQSortingSupport; - - if ( ( !$smwgIgnoreQueryErrors || $query->getDescription() instanceof SMWThingDescription ) && - $query->querymode != SMWQuery::MODE_DEBUG && - count( $query->getErrors() ) > 0 ) { - return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false ); - // NOTE: we check this here to prevent unnecessary work, but we check - // it after query processing below again in case more errors occurred. - } elseif ( $query->querymode == SMWQuery::MODE_NONE ) { - // don't query, but return something to printer - return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, true ); - } - - $this->m_qmode = $query->querymode; - $this->m_queries = array(); - $this->m_hierarchies = array(); - $this->m_querylog = array(); - $this->m_errors = array(); - SMWSQLStore3Query::$qnum = 0; - $this->m_sortkeys = $query->sortkeys; - - // *** First compute abstract representation of the query (compilation) ***// - wfProfileIn( 'SMWSQLStore3Queries::compileMainQuery (SMW)' ); - $qid = $this->compileQueries( $query->getDescription() ); // compile query, build query "plan" - wfProfileOut( 'SMWSQLStore3Queries::compileMainQuery (SMW)' ); - - if ( $qid < 0 ) { // no valid/supported condition; ensure that at least only proper pages are delivered - $qid = SMWSQLStore3Query::$qnum; - $q = new SMWSQLStore3Query(); - $q->jointable = SMWSql3SmwIds::tableName; - $q->joinfield = "$q->alias.smw_id"; - $q->where = "$q->alias.smw_iw!=" . $this->m_dbs->addQuotes( SMW_SQL3_SMWIW_OUTDATED ) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes( SMW_SQL3_SMWREDIIW ) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes( SMW_SQL3_SMWBORDERIW ) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes( SMW_SQL3_SMWINTDEFIW ); - $this->m_queries[$qid] = $q; - } - - if ( $this->m_queries[$qid]->jointable != SMWSql3SmwIds::tableName ) { - // manually make final root query (to retrieve namespace,title): - $rootid = SMWSQLStore3Query::$qnum; - $qobj = new SMWSQLStore3Query(); - $qobj->jointable = SMWSql3SmwIds::tableName; - $qobj->joinfield = "$qobj->alias.smw_id"; - $qobj->components = array( $qid => "$qobj->alias.smw_id" ); - $qobj->sortfields = $this->m_queries[$qid]->sortfields; - $this->m_queries[$rootid] = $qobj; - } else { // not such a common case, but worth avoiding the additional inner join: - $rootid = $qid; - } - - // Include order conditions (may extend query if needed for sorting): - if ( $smwgQSortingSupport ) { - $this->applyOrderConditions( $rootid ); - } - - // Possibly stop if new errors happened: - if ( !$smwgIgnoreQueryErrors && - $query->querymode != SMWQuery::MODE_DEBUG && - count( $this->m_errors ) > 0 ) { - $query->addErrors( $this->m_errors ); - return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false ); - } - - // *** Now execute the computed query ***// - wfProfileIn( 'SMWSQLStore3Queries::executeMainQuery (SMW)' ); - $this->executeQueries( $this->m_queries[$rootid] ); // execute query tree, resolve all dependencies - wfProfileOut( 'SMWSQLStore3Queries::executeMainQuery (SMW)' ); - - switch ( $query->querymode ) { - case SMWQuery::MODE_DEBUG: - $result = $this->getDebugQueryResult( $query, $rootid ); - break; - case SMWQuery::MODE_COUNT: - $result = $this->getCountQueryResult( $query, $rootid ); - break; - default: - $result = $this->getInstanceQueryResult( $query, $rootid ); - break; - } - - $this->cleanUp(); - $query->addErrors( $this->m_errors ); - - return $result; - } - - /** - * Using a preprocessed internal query description referenced by $rootid, compute - * the proper debug output for the given query. - * - * @param SMWQuery $query - * @param integer $rootid - * - * @return string - */ - protected function getDebugQueryResult( SMWQuery $query, $rootid ) { - $qobj = $this->m_queries[$rootid]; - - $db = $this->m_store->getDatabase(); - - $entries = array(); - - $sql_options = $this->getSQLOptions( $query, $rootid ); - list( $startOpts, $useIndex, $tailOpts ) = $db->makeSelectOptions( $sql_options ); - - if ( $qobj->joinfield !== '' ) { - $entries['SQL Query'] = - "<tt>SELECT DISTINCT $qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns FROM " . - $db->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from . - ( ( $qobj->where === '' ) ? '':' WHERE ' ) . $qobj->where . "$tailOpts LIMIT " . - $sql_options['LIMIT'] . ' OFFSET ' . $sql_options['OFFSET'] . ';</tt>'; - } else { - $entries['SQL Query'] = 'Empty result, no SQL query created.'; - } - - $auxtables = ''; - foreach ( $this->m_querylog as $table => $log ) { - $auxtables .= "<li>Temporary table $table"; - foreach ( $log as $q ) { - $auxtables .= "<br />  <tt>$q</tt>"; - } - $auxtables .= '</li>'; - } - if ( $auxtables ) { - $entries['Auxilliary Tables Used'] = "<ul>$auxtables</ul>"; - } else { - $entries['Auxilliary Tables Used'] = 'No auxilliary tables used.'; - } - - return QueryOutputFormatter::formatDebugOutput( 'SMWSQLStore3', $entries, $query ); - } - - /** - * Using a preprocessed internal query description referenced by $rootid, compute - * the proper counting output for the given query. - * - * @param SMWQuery $query - * @param integer $rootid - * - * @return integer - */ - protected function getCountQueryResult( SMWQuery $query, $rootid ) { - wfProfileIn( 'SMWSQLStore3Queries::getCountQueryResult (SMW)' ); - - $qobj = $this->m_queries[$rootid]; - - if ( $qobj->joinfield === '' ) { // empty result, no query needed - wfProfileOut( 'SMWSQLStore3Queries::getCountQueryResult (SMW)' ); - return 0; - } - - $sql_options = array( 'LIMIT' => $query->getLimit() + 1, 'OFFSET' => $query->getOffset() ); - $res = $this->m_dbs->select( $this->m_dbs->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from, "COUNT(DISTINCT $qobj->alias.smw_id) AS count", $qobj->where, 'SMW::getQueryResult', $sql_options ); - $row = $this->m_dbs->fetchObject( $res ); - - $count = $row->count; - $this->m_dbs->freeResult( $res ); - - wfProfileOut( 'SMWSQLStore3Queries::getCountQueryResult (SMW)' ); - - return $count; - } - - /** - * Using a preprocessed internal query description referenced by $rootid, - * compute the proper result instance output for the given query. - * @todo The SQL standard requires us to select all fields by which we sort, leading - * to wrong results regarding the given limit: the user expects limit to be applied to - * the number of distinct pages, but we can use DISTINCT only to whole rows. Thus, if - * rows contain sortfields, then pages with multiple values for that field are distinct - * and appear multiple times in the result. Filtering duplicates in post processing - * would still allow such duplicates to push aside wanted values, leading to less than - * "limit" results although there would have been "limit" really distinct results. For - * this reason, we select sortfields only for POSTGRES. MySQL is able to perform what - * we want here. It would be nice if we could eliminate the bug in POSTGRES as well. - * - * @param SMWQuery $query - * @param integer $rootid - * - * @return SMWQueryResult - */ - protected function getInstanceQueryResult( SMWQuery $query, $rootid ) { - global $wgDBtype; - - $db = $this->m_store->getDatabase(); - - wfProfileIn( 'SMWSQLStore3Queries::getInstanceQueryResult (SMW)' ); - $qobj = $this->m_queries[$rootid]; - - if ( $qobj->joinfield === '' ) { // empty result, no query needed - $result = new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false ); - wfProfileOut( 'SMWSQLStore3Queries::getInstanceQueryResult (SMW)' ); - return $result; - } - - $sql_options = $this->getSQLOptions( $query, $rootid ); - - // Selecting those is required in standard SQL (but MySQL does not require it). - $sortfields = implode( $qobj->sortfields, ',' ); - - $res = $db->select( $db->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from, - "DISTINCT $qobj->alias.smw_id AS id,$qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns,$qobj->alias.smw_iw AS iw,$qobj->alias.smw_subobject AS so,$qobj->alias.smw_sortkey AS sortkey" . - ( $wgDBtype == 'postgres' ? ( ( $sortfields ? ',' : '' ) . $sortfields ) : '' ), - $qobj->where, 'SMW::getQueryResult', $sql_options ); - - $qr = array(); - $count = 0; // the number of fetched results ( != number of valid results in array $qr) - $prs = $query->getDescription()->getPrintrequests(); - - $diHandler = $this->m_store->getDataItemHandlerForDIType( SMWDataItem::TYPE_WIKIPAGE ); - - while ( ( $count < $query->getLimit() ) && ( $row = $db->fetchObject( $res ) ) ) { - if ( $row->iw === '' || $row->iw{0} != ':' ) { - - // Catch exception for non-existing predefined properties that - // still registered within non-updated pages (@see bug 48711) - try { - $dataItem = $diHandler->dataItemFromDBKeys( array( - $row->t, - intval( $row->ns ), - $row->iw, - '', - $row->so - ) ); - } catch ( \SMW\InvalidPredefinedPropertyException $e ) { - wfDebugLog( __CLASS__, __METHOD__ . ': ' . $e->getMessage() ); - } - - if ( $dataItem instanceof SMWDIWikiPage ) { - $count++; - $qr[] = $dataItem; - // These IDs are usually needed for displaying the page (esp. if more property values are displayed): - $this->m_store->smwIds->setCache( $row->t, $row->ns, $row->iw, $row->so, $row->id, $row->sortkey ); - } - } - } - - if ( $db->fetchObject( $res ) ) { - $count++; - } - - $db->freeResult( $res ); - $result = new SMWQueryResult( $prs, $query, $qr, $this->m_store, ( $count > $query->getLimit() ) ); - - wfProfileOut( 'SMWSQLStore3Queries::getInstanceQueryResult (SMW)' ); - - return $result; - } - - /** - * Create a new SMWSQLStore3Query object that can be used to obtain results - * for the given description. The result is stored in $this->m_queries - * using a numeric key that is returned as a result of the function. - * Returns -1 if no query was created. - * @todo The case of nominal classes (top-level SMWValueDescription) still - * makes some assumptions about the table structure, especially about the - * name of the joinfield (o_id). Better extend - * compilePropertyValueDescription to deal with this case. - * - * @param SMWDescription $description - * - * @return integer - */ - protected function compileQueries( SMWDescription $description ) { - $query = new SMWSQLStore3Query(); - - if ( $description instanceof SMWSomeProperty ) { - $this->compileSomePropertyDescription( $query, $description ); - } elseif ( $description instanceof SMWNamespaceDescription ) { - // TODO: One instance of the SMW IDs table on s_id always suffices (swm_id is KEY)! Doable in execution ... (PERFORMANCE) - $query->jointable = SMWSql3SmwIds::tableName; - $query->joinfield = "$query->alias.smw_id"; - $query->where = "$query->alias.smw_namespace=" . $this->m_dbs->addQuotes( $description->getNamespace() ); - } elseif ( ( $description instanceof SMWConjunction ) || - ( $description instanceof SMWDisjunction ) ) { - $query->type = ( $description instanceof SMWConjunction ) ? SMWSQLStore3Query::Q_CONJUNCTION : SMWSQLStore3Query::Q_DISJUNCTION; - - foreach ( $description->getDescriptions() as $subdesc ) { - $sub = $this->compileQueries( $subdesc ); - if ( $sub >= 0 ) { - $query->components[$sub] = true; - } - } - - // All subconditions failed, drop this as well. - if ( count( $query->components ) == 0 ) { - $query->type = SMWSQLStore3Query::Q_NOQUERY; - } - } elseif ( $description instanceof SMWClassDescription ) { - $cqid = SMWSQLStore3Query::$qnum; - $cquery = new SMWSQLStore3Query(); - $cquery->type = SMWSQLStore3Query::Q_CLASS_HIERARCHY; - $cquery->joinfield = array(); - - foreach ( $description->getCategories() as $cat ) { - $cid = $this->m_store->smwIds->getSMWPageID( $cat->getDBkey(), NS_CATEGORY, $cat->getInterwiki(), '' ); - if ( $cid != 0 ) { - $cquery->joinfield[] = $cid; - } - } - - if ( count( $cquery->joinfield ) == 0 ) { // Empty result. - $query->type = SMWSQLStore3Query::Q_VALUE; - $query->jointable = ''; - $query->joinfield = ''; - } else { // Instance query with disjunction of classes (categories) - $query->jointable = $this->m_dbs->tableName( - $this->m_store->findPropertyTableID( - new SMWDIProperty( '_INST' ) ) ); - $query->joinfield = "$query->alias.s_id"; - $query->components[$cqid] = "$query->alias.o_id"; - $this->m_queries[$cqid] = $cquery; - } - } elseif ( $description instanceof SMWValueDescription ) { // Only type '_wpg' objects can appear on query level (essentially as nominal classes). - if ( $description->getDataItem() instanceof SMWDIWikiPage ) { - if ( $description->getComparator() == SMW_CMP_EQ ) { - $query->type = SMWSQLStore3Query::Q_VALUE; - $oid = $this->m_store->smwIds->getSMWPageID( - $description->getDataItem()->getDBkey(), - $description->getDataItem()->getNamespace(), - $description->getDataItem()->getInterwiki(), - $description->getDataItem()->getSubobjectName() ); - $query->joinfield = array( $oid ); - } else { // Join with SMW IDs table needed for other comparators (apply to title string). - $query->jointable = SMWSql3SmwIds::tableName; - $query->joinfield = "{$query->alias}.smw_id"; - $value = $description->getDataItem()->getSortKey(); - - switch ( $description->getComparator() ) { - case SMW_CMP_LEQ: $comp = '<='; break; - case SMW_CMP_GEQ: $comp = '>='; break; - case SMW_CMP_LESS: $comp = '<'; break; - case SMW_CMP_GRTR: $comp = '>'; break; - case SMW_CMP_NEQ: $comp = '!='; break; - case SMW_CMP_LIKE: case SMW_CMP_NLKE: - $comp = ' LIKE '; - if ( $description->getComparator() == SMW_CMP_NLKE ) $comp = " NOT{$comp}"; - $value = str_replace( array( '%', '_', '*', '?' ), array( '\%', '\_', '%', '_' ), $value ); - break; - } - $query->where = "{$query->alias}.smw_sortkey$comp" . $this->m_dbs->addQuotes( $value ); - } - } - } elseif ( $description instanceof SMWConceptDescription ) { // fetch concept definition and insert it here - $cid = $this->m_store->smwIds->getSMWPageID( $description->getConcept()->getDBkey(), SMW_NS_CONCEPT, '', '' ); - // We bypass the storage interface here (which is legal as we control it, and safe if we are careful with changes ...) - // This should be faster, but we must implement the unescaping that concepts do on getWikiValue() - $row = $this->m_dbs->selectRow( - 'smw_fpt_conc', - array( 'concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date' ), - array( 's_id' => $cid ), - 'SMWSQLStore3Queries::compileQueries' - ); - - if ( $row === false ) { // No description found, concept does not exist. - // keep the above query object, it yields an empty result - // TODO: announce an error here? (maybe not, since the query processor can check for - // non-existing concept pages which is probably the main reason for finding nothing here) - } else { - global $smwgQConceptCaching, $smwgQMaxSize, $smwgQMaxDepth, $smwgQFeatures, $smwgQConceptCacheLifetime; - - $may_be_computed = ( $smwgQConceptCaching == CONCEPT_CACHE_NONE ) || - ( ( $smwgQConceptCaching == CONCEPT_CACHE_HARD ) && ( ( ~( ~( $row->concept_features + 0 ) | $smwgQFeatures ) ) == 0 ) && - ( $smwgQMaxSize >= $row->concept_size ) && ( $smwgQMaxDepth >= $row->concept_depth ) ); - - if ( $row->cache_date && - ( ( $row->cache_date > ( strtotime( "now" ) - $smwgQConceptCacheLifetime * 60 ) ) || - !$may_be_computed ) ) { // Cached concept, use cache unless it is dead and can be revived. - - $query->jointable = SMWSQLStore3::CONCEPT_CACHE_TABLE; - $query->joinfield = "$query->alias.s_id"; - $query->where = "$query->alias.o_id=" . $this->m_dbs->addQuotes( $cid ); - } elseif ( $row->concept_txt ) { // Parse description and process it recursively. - if ( $may_be_computed ) { - $qp = new SMWQueryParser(); - - // No defaultnamespaces here; If any, these are already in the concept. - // Unescaping is the same as in SMW_DV_Conept's getWikiValue(). - $desc = $qp->getQueryDescription( str_replace( array( '<', '>', '&' ), array( '<', '>', '&' ), $row->concept_txt ) ); - $qid = $this->compileQueries( $desc ); - if ($qid != -1) { - $query = $this->m_queries[$qid]; - } else { // somehow the concept query is no longer valid; maybe some syntax changed (upgrade) or global settings were modified since storing it - $this->m_errors[] = wfMessage( 'smw_emptysubquery' )->text(); // not quite the right message, but this case is very rare; let us not make detailed messages for this - } - } else { - $this->m_errors[] = wfMessage( 'smw_concept_cache_miss', $description->getConcept()->getText() )->text(); - } - } // else: no cache, no description (this may happen); treat like empty concept - } - } else { // (e.g. SMWThingDescription) - $query->type = SMWSQLStore3Query::Q_NOQUERY; // no condition - } - - $this->registerQuery( $query ); - if ( $query->type != SMWSQLStore3Query::Q_NOQUERY ) { - return $query->queryNumber; - } else { - return -1; - } - } - - /** - * Register a query object to the internal query list, if the query is - * valid. Also make sure that sortkey information is propagated down - * from subqueries of this query. - */ - protected function registerQuery( SMWSQLStore3Query $query ) { - if ( $query->type != SMWSQLStore3Query::Q_NOQUERY ) { - $this->m_queries[$query->queryNumber] = $query; - - // Propagate sortkeys from subqueries: - if ( $query->type != SMWSQLStore3Query::Q_DISJUNCTION ) { - // Sortkeys are killed by disjunctions (not all parts may have them), - // NOTE: preprocessing might try to push disjunctions downwards to safe sortkey, but this seems to be minor - foreach ( $query->components as $cid => $field ) { - $query->sortfields = array_merge( $this->m_queries[$cid]->sortfields, $query->sortfields ); - } - } - } - } - - /** - * Modify the given query object to account for some property condition for - * the given property. If it is not possible to generate a query for the - * given data, the query type is changed to SMWSQLStore3Query::Q_NOQUERY. Callers need - * to check for this and discard the query in this case. - * - * @note This method does not support sortkey (_SKEY) property queries, - * since they do not have a normal property table. This should not be a - * problem since comparators on sortkeys are supported indirectly when - * using comparators on wikipages. There is no reason to create any - * query with _SKEY ad users cannot do so either (no user label). - * - * @since 1.8 - */ - protected function compileSomePropertyDescription( SMWSQLStore3Query $query, SMWSomeProperty $description ) { - - $db = $this->m_store->getDatabase(); - - $property = $description->getProperty(); - - $tableid = $this->m_store->findPropertyTableID( $property ); - if ( $tableid === '' ) { // Give up - $query->type = SMWSQLStore3Query::Q_NOQUERY; - return; - } - - $proptables = $this->m_store->getPropertyTables(); - $proptable = $proptables[$tableid]; - if ( !$proptable->usesIdSubject() ) { - // no queries with such tables - // (only redirects are affected in practice) - $query->type = SMWSQLStore3Query::Q_NOQUERY; - return; - } - - $typeid = $property->findPropertyTypeID(); - $diType = DataTypeRegistry::getInstance()->getDataItemId( $typeid ); - if ( $property->isInverse() && $diType != SMWDataItem::TYPE_WIKIPAGE ) { - // can only invert properties that point to pages - $query->type = SMWSQLStore3Query::Q_NOQUERY; - return; - } - $diHandler = $this->m_store->getDataItemHandlerForDIType( $diType ); - $indexField = $diHandler->getIndexField(); - $sortkey = $property->getKey(); // TODO: strictly speaking, the DB key is not what we want here, since sortkey is based on a "wiki value" - - // *** Now construct the query ... ***// - $query->jointable = $proptable->getName(); - - // *** Add conditions for selecting rows for this property ***// - if ( !$proptable->isFixedPropertyTable() ) { - $pid = $this->m_store->smwIds->getSMWPropertyID( $property ); - // Construct property hierarchy: - $pqid = SMWSQLStore3Query::$qnum; - $pquery = new SMWSQLStore3Query(); - $pquery->type = SMWSQLStore3Query::Q_PROP_HIERARCHY; - $pquery->joinfield = array( $pid ); - $query->components[$pqid] = "{$query->alias}.p_id"; - $this->m_queries[$pqid] = $pquery; - // Alternative code without property hierarchies: - // $query->where = "{$query->alias}.p_id=" . $this->m_dbs->addQuotes( $pid ); - } // else: no property column, no hierarchy queries - - // *** Add conditions on the value of the property ***// - if ( $diType == SMWDataItem::TYPE_WIKIPAGE ) { - $o_id = $indexField; - if ( $property->isInverse() ) { - $s_id = $o_id; - $o_id = 's_id'; - } else { - $s_id = 's_id'; - } - $query->joinfield = "{$query->alias}.{$s_id}"; - - // process page description like main query - $sub = $this->compileQueries( $description->getDescription() ); - if ( $sub >= 0 ) { - $query->components[$sub] = "{$query->alias}.{$o_id}"; - } - - if ( array_key_exists( $sortkey, $this->m_sortkeys ) ) { - // TODO: This SMW IDs table is possibly duplicated in the query. - // Example: [[has capital::!Berlin]] with sort=has capital - // Can we prevent that? (PERFORMANCE) - $query->from = ' INNER JOIN ' . $db->tableName( SMWSql3SmwIds::tableName ) . - " AS ids{$query->alias} ON ids{$query->alias}.smw_id={$query->alias}.{$o_id}"; - $query->sortfields[$sortkey] = "ids{$query->alias}.smw_sortkey"; - } - } else { // non-page value description - $query->joinfield = "{$query->alias}.s_id"; - $this->compilePropertyValueDescription( $query, $description->getDescription(), $proptable, $diHandler, 'AND' ); - if ( array_key_exists( $sortkey, $this->m_sortkeys ) ) { - $query->sortfields[$sortkey] = "{$query->alias}.{$indexField}"; - } - } - } - - /** - * Given an SMWDescription that is just a conjunction or disjunction of - * SMWValueDescription objects, create and return a plain WHERE condition - * string for it. - * - * @param $query - * @param SMWDescription $description - * @param SMWSQLStore3Table $proptable - * @param SMWDataItemHandler $diHandler for that table - * @param string $operator SQL operator "AND" or "OR" - */ - protected function compilePropertyValueDescription( - $query, SMWDescription $description, SMWSQLStore3Table $proptable, SMWDataItemHandler $diHandler, $operator ) { - if ( $description instanceof SMWValueDescription ) { - $this->compileValueDescription( $query, $description, $proptable, $diHandler, $operator ); - } elseif ( ( $description instanceof SMWConjunction ) || - ( $description instanceof SMWDisjunction ) ) { - $op = ( $description instanceof SMWConjunction ) ? 'AND' : 'OR'; - - foreach ( $description->getDescriptions() as $subdesc ) { - $this->compilePropertyValueDescription( $query, $subdesc, $proptable, $diHandler, $op ); - } - } elseif ( $description instanceof SMWThingDescription ) { - // nothing to do - } else { - throw new MWException( "Cannot process this type of SMWDescription." ); - } - } - - /** - * Given an SMWDescription that is just a conjunction or disjunction of - * SMWValueDescription objects, create and return a plain WHERE condition - * string for it. - * - * @param $query - * @param SMWDescription $description - * @param SMWSQLStore3Table $proptable - * @param SMWDataItemHandler $diHandler for that table - * @param string $operator SQL operator "AND" or "OR" - */ - protected function compileValueDescription( - $query, SMWValueDescription $description, SMWSQLStore3Table $proptable, SMWDataItemHandler $diHandler, $operator ) { - $where = ''; - $dataItem = $description->getDataItem(); - // TODO Better get the handle from the property type - // Some comparators (e.g. LIKE) could use DI values of - // a different type; we care about the property table, not - // about the value - $diType = $dataItem->getDIType(); - - // Try comparison based on value field and comparator, - // but only if no join with SMW IDs table is needed. - if ( $diType != SMWDataItem::TYPE_WIKIPAGE ) { - // Do not support smw_id joined data for now. - - // See if the getSQLCondition method exists and call it if this is the case. - if ( method_exists( $description, 'getSQLCondition' ) ) { - $fields = $diHandler->getTableFields(); - $where = $description->getSQLCondition( $query->alias, array_keys( $fields ), $this->m_dbs ); - } - - if ( $where == '' ) { - $indexField = $diHandler->getIndexField(); - //Hack to get to the field used as index - $keys = $diHandler->getWhereConds( $dataItem ); - $value = $keys[$indexField]; - - switch ( $description->getComparator() ) { - case SMW_CMP_EQ: $comparator = '='; break; - case SMW_CMP_LESS: $comparator = '<'; break; - case SMW_CMP_GRTR: $comparator = '>'; break; - case SMW_CMP_LEQ: $comparator = '<='; break; - case SMW_CMP_GEQ: $comparator = '>='; break; - case SMW_CMP_NEQ: $comparator = '!='; break; - case SMW_CMP_LIKE: case SMW_CMP_NLKE: - if ( $description->getComparator() == SMW_CMP_LIKE ) { - $comparator = ' LIKE '; - } else { - $comparator = ' NOT LIKE '; - } - // Escape to prepare string matching: - $value = str_replace( array( '%', '_', '*', '?' ), array( '\%', '\_', '%', '_' ), $value ); - break; - default: - throw new MWException( "Unsupported comparator '" . $description->getComparator() . "' in query condition." ); - } - - $where = "$query->alias.{$indexField}{$comparator}" . $this->m_dbs->addQuotes( $value ); - } - } else { // exact match (like comparator = above, but not using $valueField -throw new MWException("Debug -- this code might be dead."); - foreach ( $diHandler->getWhereConds( $dataItem ) as $fieldname => $value ) { - $where .= ( $where ? ' AND ' : '' ) . "{$query->alias}.$fieldname=" . $this->m_dbs->addQuotes( $value ); - } - } - - if ( $where !== '' ) { - $query->where .= ( $query->where ? " $operator " : '' ) . "($where)"; - } - } - - /** - * Process stored queries and change store accordingly. The query obj is modified - * so that it contains non-recursive description of a select to execute for getting - * the actual result. - * - * @param SMWSQLStore3Query $query - */ - protected function executeQueries( SMWSQLStore3Query &$query ) { - global $wgDBtype; - - $db = $this->m_store->getDatabase(); - - switch ( $query->type ) { - case SMWSQLStore3Query::Q_TABLE: // Normal query with conjunctive subcondition. - foreach ( $query->components as $qid => $joinfield ) { - $subquery = $this->m_queries[$qid]; - $this->executeQueries( $subquery ); - - if ( $subquery->jointable !== '' ) { // Join with jointable.joinfield - $query->from .= ' INNER JOIN ' . $db->tableName( $subquery->jointable ) . " AS $subquery->alias ON $joinfield=" . $subquery->joinfield; - } elseif ( $subquery->joinfield !== '' ) { // Require joinfield as "value" via WHERE. - $condition = ''; - - foreach ( $subquery->joinfield as $value ) { - $condition .= ( $condition ? ' OR ':'' ) . "$joinfield=" . $db->addQuotes( $value ); - } - - if ( count( $subquery->joinfield ) > 1 ) { - $condition = "($condition)"; - } - - $query->where .= ( ( $query->where === '' ) ? '':' AND ' ) . $condition; - } else { // interpret empty joinfields as impossible condition (empty result) - $query->joinfield = ''; // make whole query false - $query->jointable = ''; - $query->where = ''; - $query->from = ''; - break; - } - - if ( $subquery->where !== '' ) { - $query->where .= ( ( $query->where === '' ) ? '':' AND ' ) . '(' . $subquery->where . ')'; - } - - $query->from .= $subquery->from; - } - - $query->components = array(); - break; - case SMWSQLStore3Query::Q_CONJUNCTION: - // pick one subquery with jointable as anchor point ... - reset( $query->components ); - $key = false; - - foreach ( $query->components as $qkey => $qid ) { - if ( $this->m_queries[$qkey]->jointable !== '' ) { - $key = $qkey; - break; - } - } - - if ( $key !== false ) { - $result = $this->m_queries[$key]; - unset( $query->components[$key] ); - - // Execute it first (may change jointable and joinfield, e.g. when making temporary tables) - $this->executeQueries( $result ); - - // ... and append to this query the remaining queries. - foreach ( $query->components as $qid => $joinfield ) { - $result->components[$qid] = $result->joinfield; - } - - // Second execute, now incorporating remaining conditions. - $this->executeQueries( $result ); - } else { // Only fixed values in conjunction, make a new value without joining. - $key = $qkey; - $result = $this->m_queries[$key]; - unset( $query->components[$key] ); - - foreach ( $query->components as $qid => $joinfield ) { - if ( $result->joinfield != $this->m_queries[$qid]->joinfield ) { - $result->joinfield = ''; // all other values should already be '' - break; - } - } - } - $query = $result; - break; - case SMWSQLStore3Query::Q_DISJUNCTION: - if ( $this->m_qmode !== SMWQuery::MODE_DEBUG ) { - $db->query( $this->getCreateTempIDTableSQL( $db->tableName( $query->alias ) ), 'SMW::executeQueries' ); - } - - $this->m_querylog[$query->alias] = array(); - - foreach ( $query->components as $qid => $joinfield ) { - $subquery = $this->m_queries[$qid]; - $this->executeQueries( $subquery ); - $sql = ''; - - if ( $subquery->jointable !== '' ) { - $sql = 'INSERT ' . ( ( $wgDBtype == 'postgres' ) ? '':'IGNORE ' ) . 'INTO ' . - $db->tableName( $query->alias ) . - " SELECT $subquery->joinfield FROM " . $db->tableName( $subquery->jointable ) . - " AS $subquery->alias $subquery->from" . ( $subquery->where ? " WHERE $subquery->where":'' ); - } elseif ( $subquery->joinfield !== '' ) { - // NOTE: this works only for single "unconditional" values without further - // WHERE or FROM. The execution must take care of not creating any others. - $values = ''; - - foreach ( $subquery->joinfield as $value ) { - $values .= ( $values ? ',' : '' ) . '(' . $db->addQuotes( $value ) . ')'; - } - - $sql = 'INSERT ' . ( ( $wgDBtype == 'postgres' ) ? '':'IGNORE ' ) . 'INTO ' . $db->tableName( $query->alias ) . " (id) VALUES $values"; - } // else: // interpret empty joinfields as impossible condition (empty result), ignore - if ( $sql ) { - $this->m_querylog[$query->alias][] = $sql; - - if ( $this->m_qmode !== SMWQuery::MODE_DEBUG ) { - $db->query( $sql , 'SMW::executeQueries' ); - } - } - } - - $query->jointable = $query->alias; - $query->joinfield = "$query->alias.id"; - $query->sortfields = array(); // Make sure we got no sortfields. - // TODO: currently this eliminates sortkeys, possibly keep them (needs different temp table format though, maybe not such a good thing to do) - break; - case SMWSQLStore3Query::Q_PROP_HIERARCHY: - case SMWSQLStore3Query::Q_CLASS_HIERARCHY: // make a saturated hierarchy - $this->executeHierarchyQuery( $query ); - break; - case SMWSQLStore3Query::Q_VALUE: break; // nothing to do - } - } - - /** - * Find subproperties or subcategories. This may require iterative computation, - * and temporary tables are used in many cases. - * - * @param SMWSQLStore3Query $query - */ - protected function executeHierarchyQuery( SMWSQLStore3Query &$query ) { - global $wgDBtype, $smwgQSubpropertyDepth, $smwgQSubcategoryDepth; - - $fname = "SMWSQLStore3Queries::executeQueries-hierarchy-{$query->type} (SMW)"; - wfProfileIn( $fname ); - - $db = $this->m_store->getDatabase(); - - $depth = ( $query->type == SMWSQLStore3Query::Q_PROP_HIERARCHY ) ? $smwgQSubpropertyDepth : $smwgQSubcategoryDepth; - - if ( $depth <= 0 ) { // treat as value, no recursion - $query->type = SMWSQLStore3Query::Q_VALUE; - wfProfileOut( $fname ); - return; - } - - $values = ''; - $valuecond = ''; - - foreach ( $query->joinfield as $value ) { - $values .= ( $values ? ',':'' ) . '(' . $db->addQuotes( $value ) . ')'; - $valuecond .= ( $valuecond ? ' OR ':'' ) . 'o_id=' . $db->addQuotes( $value ); - } - - $propertyKey = ( $query->type == SMWSQLStore3Query::Q_PROP_HIERARCHY ) ? '_SUBP' : '_SUBC'; - $smwtable = $db->tableName( - $this->m_store->findPropertyTableID( new SMWDIProperty( $propertyKey ) ) ); - - // Try to safe time (SELECT is cheaper than creating/dropping 3 temp tables): - $res = $db->select( $smwtable, 's_id', $valuecond, __METHOD__, array( 'LIMIT' => 1 ) ); - - if ( !$db->fetchObject( $res ) ) { // no subobjects, we are done! - $db->freeResult( $res ); - $query->type = SMWSQLStore3Query::Q_VALUE; - wfProfileOut( $fname ); - return; - } - - $db->freeResult( $res ); - $tablename = $db->tableName( $query->alias ); - $this->m_querylog[$query->alias] = array( "Recursively computed hierarchy for element(s) $values." ); - $query->jointable = $query->alias; - $query->joinfield = "$query->alias.id"; - - if ( $this->m_qmode == SMWQuery::MODE_DEBUG ) { - wfProfileOut( $fname ); - return; // No real queries in debug mode. - } - - $db->query( $this->getCreateTempIDTableSQL( $tablename ), 'SMW::executeHierarchyQuery' ); - - if ( array_key_exists( $values, $this->m_hierarchies ) ) { // Just copy known result. - $db->query( "INSERT INTO $tablename (id) SELECT id" . - ' FROM ' . $this->m_hierarchies[$values], - 'SMW::executeHierarchyQuery' ); - wfProfileOut( $fname ); - return; - } - - // NOTE: we use two helper tables. One holds the results of each new iteration, one holds the - // results of the previous iteration. One could of course do with only the above result table, - // but then every iteration would use all elements of this table, while only the new ones - // obtained in the previous step are relevant. So this is a performance measure. - $tmpnew = 'smw_new'; - $tmpres = 'smw_res'; - $db->query( $this->getCreateTempIDTableSQL( $tmpnew ), 'SMW::executeQueries' ); - $db->query( $this->getCreateTempIDTableSQL( $tmpres ), 'SMW::executeQueries' ); - $db->query( "INSERT " . ( ( $wgDBtype == 'postgres' ) ? "" : "IGNORE" ) . " INTO $tablename (id) VALUES $values", 'SMW::executeHierarchyQuery' ); - $db->query( "INSERT " . ( ( $wgDBtype == 'postgres' ) ? "" : "IGNORE" ) . " INTO $tmpnew (id) VALUES $values", 'SMW::executeHierarchyQuery' ); - - for ( $i = 0; $i < $depth; $i++ ) { - $db->query( "INSERT " . ( ( $wgDBtype == 'postgres' ) ? '' : 'IGNORE ' ) . "INTO $tmpres (id) SELECT s_id" . ( $wgDBtype == 'postgres' ? '::integer':'' ) . " FROM $smwtable, $tmpnew WHERE o_id=id", - 'SMW::executeHierarchyQuery' ); - if ( $db->affectedRows() == 0 ) { // no change, exit loop - break; - } - - $db->query( "INSERT " . ( ( $wgDBtype == 'postgres' ) ? '' : 'IGNORE ' ) . "INTO $tablename (id) SELECT $tmpres.id FROM $tmpres", - 'SMW::executeHierarchyQuery' ); - - if ( $db->affectedRows() == 0 ) { // no change, exit loop - break; - } - - $db->query( 'TRUNCATE TABLE ' . $tmpnew, 'SMW::executeHierarchyQuery' ); // empty "new" table - $tmpname = $tmpnew; - $tmpnew = $tmpres; - $tmpres = $tmpname; - } - - $this->m_hierarchies[$values] = $tablename; - $db->query( ( ( $wgDBtype == 'postgres' ) ? 'DROP TABLE IF EXISTS smw_new' : 'DROP TEMPORARY TABLE smw_new' ), 'SMW::executeHierarchyQuery' ); - $db->query( ( ( $wgDBtype == 'postgres' ) ? 'DROP TABLE IF EXISTS smw_res' : 'DROP TEMPORARY TABLE smw_res' ), 'SMW::executeHierarchyQuery' ); - - wfProfileOut( $fname ); - } - - /** - * This function modifies the given query object at $qid to account for all ordering conditions - * in the SMWQuery $query. It is always required that $qid is the id of a query that joins with - * SMW IDs table so that the field alias.smw_title is $available for default sorting. - * - * @param integer $qid - */ - protected function applyOrderConditions( $qid ) { - $qobj = $this->m_queries[$qid]; - // (1) collect required extra property descriptions: - $extraproperties = array(); - - foreach ( $this->m_sortkeys as $propkey => $order ) { - if ( !array_key_exists( $propkey, $qobj->sortfields ) ) { // Find missing property to sort by. - if ( $propkey === '' ) { // Sort by first result column (page titles). - $qobj->sortfields[$propkey] = "$qobj->alias.smw_sortkey"; - } else { // Try to extend query. - $sortprop = SMWPropertyValue::makeUserProperty( $propkey ); - - if ( $sortprop->isValid() ) { - $extraproperties[] = new SMWSomeProperty( $sortprop->getDataItem(), new SMWThingDescription() ); - } - } - } - } - - // (2) compile according conditions and hack them into $qobj: - if ( count( $extraproperties ) > 0 ) { - $desc = new SMWConjunction( $extraproperties ); - $newqid = $this->compileQueries( $desc ); - $newqobj = $this->m_queries[$newqid]; // This is always an SMWSQLStore3Query::Q_CONJUNCTION ... - - foreach ( $newqobj->components as $cid => $field ) { // ... so just re-wire its dependencies - $qobj->components[$cid] = $qobj->joinfield; - $qobj->sortfields = array_merge( $qobj->sortfields, $this->m_queries[$cid]->sortfields ); - } - - $this->m_queries[$qid] = $qobj; - } - } - - /** - * Get a SQL option array for the given query and preprocessed query object at given id. - * - * @param SMWQuery $query - * @param integer $rootid - */ - protected function getSQLOptions( SMWQuery $query, $rootid ) { - global $smwgQSortingSupport, $smwgQRandSortingSupport; - - $result = array( 'LIMIT' => $query->getLimit() + 1, 'OFFSET' => $query->getOffset() ); - - // Build ORDER BY options using discovered sorting fields. - if ( $smwgQSortingSupport ) { - $qobj = $this->m_queries[$rootid]; - - foreach ( $this->m_sortkeys as $propkey => $order ) { - if ( ( $order != 'RANDOM' ) && array_key_exists( $propkey, $qobj->sortfields ) ) { // Field was successfully added. - $result['ORDER BY'] = ( array_key_exists( 'ORDER BY', $result ) ? $result['ORDER BY'] . ', ' : '' ) . $qobj->sortfields[$propkey] . " $order "; - } elseif ( ( $order == 'RANDOM' ) && $smwgQRandSortingSupport ) { - $result['ORDER BY'] = ( array_key_exists( 'ORDER BY', $result ) ? $result['ORDER BY'] . ', ' : '' ) . ' RAND() '; - } - } - } - return $result; - } - - /** - * After querying, make sure no temporary database tables are left. - * @todo I might be better to keep the tables and possibly reuse them later - * on. Being temporary, the tables will vanish with the session anyway. - */ - protected function cleanUp() { - global $wgDBtype; - - $db = $this->m_store->getDatabase(); - - if ( $this->m_qmode !== SMWQuery::MODE_DEBUG ) { - foreach ( $this->m_querylog as $table => $log ) { - $db->query( ( ( $wgDBtype == 'postgres' ) ? "DROP TABLE IF EXISTS ":"DROP TEMPORARY TABLE " ) . $db->tableName( $table ), 'SMW::getQueryResult' ); - } - } - } - - /** - * Get SQL code suitable to create a temporary table of the given name, used to store ids. - * MySQL can do that simply by creating new temporary tables. PostgreSQL first checks if such - * a table exists, so the code is ready to reuse existing tables if the code was modified to - * keep them after query answering. Also, PostgreSQL tables will use a RULE to achieve built-in - * duplicate elimination. The latter is done using INSERT IGNORE in MySQL. - * - * @param string $tablename - */ - protected function getCreateTempIDTableSQL( $tablename ) { - global $wgDBtype; - - if ( $wgDBtype == 'postgres' ) { // PostgreSQL: no memory tables, use RULE to emulate INSERT IGNORE - return "CREATE OR REPLACE FUNCTION create_" . $tablename . "() RETURNS void AS " - . "$$ " - . "BEGIN " - . " IF EXISTS(SELECT NULL FROM pg_tables WHERE tablename='" . $tablename . "' AND schemaname = ANY (current_schemas(true))) " - . " THEN DELETE FROM " . $tablename . "; " - . " ELSE " - . " CREATE TEMPORARY TABLE " . $tablename . " (id INTEGER PRIMARY KEY); " - . " CREATE RULE " . $tablename . "_ignore AS ON INSERT TO " . $tablename . " WHERE (EXISTS (SELECT NULL FROM " . $tablename - . " WHERE (" . $tablename . ".id = new.id))) DO INSTEAD NOTHING; " - . " END IF; " - . "END; " - . "$$ " - . "LANGUAGE 'plpgsql'; " - . "SELECT create_" . $tablename . "(); "; - } else { // MySQL_ just a temporary table, use INSERT IGNORE later - return "CREATE TEMPORARY TABLE " . $tablename . "( id INT UNSIGNED KEY ) ENGINE=MEMORY"; - } - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Readers.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Readers.php deleted file mode 100644 index f85e372d..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Readers.php +++ /dev/null @@ -1,660 +0,0 @@ -<?php - -use SMW\DataTypeRegistry; - -/** - * Class to provide all basic read methods for SMWSQLStore3. - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author Nischay Nahata - * - * @since 1.8 - * @ingroup SMWStore - */ -class SMWSQLStore3Readers { - - /** - * The store used by this store reader - * - * @since 1.8 - * @var SMWSQLStore3 - */ - protected $store; - - /// >0 while getSemanticData runs, used to prevent nested calls from clearing the cache while another call runs and is about to fill it with data - protected static $in_getSemanticData = 0; - - public function __construct( SMWSQLStore3 $parentstore ) { - $this->store = $parentstore; - } - - /** - * @see SMWStore::getSemanticData() - * @since 1.8 - */ - public function getSemanticData( SMWDIWikiPage $subject, $filter = false ) { - wfProfileIn( "SMWSQLStore3::getSemanticData (SMW)" ); - - // *** Find out if this subject exists ***// - $sortkey = ''; - $sid = $this->store->smwIds->getSMWPageIDandSort( $subject->getDBkey(), - $subject->getNamespace(), - $subject->getInterwiki(), - $subject->getSubobjectName(), - $sortkey, true, true ); - - if ( $sid == 0 ) { - // We consider redirects for getting $sid, - // so $sid == 0 also means "no redirects". - wfProfileOut( "SMWSQLStore3::getSemanticData (SMW)" ); - return new SMWSemanticData( $subject ); - } - - $propertyTableHashes = $this->store->smwIds->getPropertyTableHashes( $sid ); - - foreach ( $this->store->getPropertyTables() as $tid => $proptable ) { - if ( !array_key_exists( $proptable->getName(), $propertyTableHashes ) ) { - continue; - } - - if ( $filter !== false ) { - $relevant = false; - foreach ( $filter as $typeId ) { - $diType = DataTypeRegistry::getInstance()->getDataItemId( $typeId ); - $relevant = $relevant || ( $proptable->getDiType() == $diType ); - if ( $relevant ) break; - } - if ( !$relevant ) continue; - } - - $this->getSemanticDataFromTable( $sid, $subject, $proptable ); - } - - // Note: the sortkey is always set but belongs to no property table, - // hence no entry in $this->store->m_sdstate[$sid] is made. - self::$in_getSemanticData++; - $this->initSemanticDataCache( $sid, $subject ); - $this->store->m_semdata[$sid]->addPropertyStubValue( '_SKEY', array( '', $sortkey ) ); - self::$in_getSemanticData--; - - wfProfileOut( "SMWSQLStore3::getSemanticData (SMW)" ); - - return $this->store->m_semdata[$sid]; - } - - /** - * Helper method to make sure there is a cache entry for the data about - * the given subject with the given ID. - * - * @todo The management of this cache should be revisited. - * - * @since 1.8 - */ - protected function initSemanticDataCache( $sid, SMWDIWikiPage $subject ) { - // *** Prepare the cache ***// - if ( !array_key_exists( $sid, $this->store->m_semdata ) ) { // new cache entry - $this->store->m_semdata[$sid] = new SMWSql3StubSemanticData( $subject, $this->store, false ); - $this->store->m_sdstate[$sid] = array(); - } - - if ( ( count( $this->store->m_semdata ) > 20 ) && ( self::$in_getSemanticData == 1 ) ) { - // prevent memory leak; - // It is not so easy to find the sweet spot between cache size and performance gains (both memory and time), - // The value of 20 was chosen by profiling runtimes for large inline queries and heavily annotated pages. - // However, things might have changed in the meantime ... - $this->store->m_semdata = array( $sid => $this->store->m_semdata[$sid] ); - $this->store->m_sdstate = array( $sid => $this->store->m_sdstate[$sid] ); - } - } - - /** - * Fetch the data storder about one subject in one particular table. - * - * @param $sid integer - * @param $subject SMWDIWikiPage - * @param $proptable SMWSQLStore3Table - * @return SMWSemanticData - * @since 1.8 - */ - protected function getSemanticDataFromTable( $sid, SMWDIWikiPage $subject, SMWSQLStore3Table $proptable ) { - // Do not clear the cache when called recursively. - self::$in_getSemanticData++; - - $this->initSemanticDataCache( $sid, $subject ); - - if ( array_key_exists( $proptable->getName(), $this->store->m_sdstate[$sid] ) ) { - self::$in_getSemanticData--; - return $this->store->m_semdata[$sid]; - } - - // *** Read the data ***// - $data = $this->fetchSemanticData( $sid, $subject, $proptable ); - foreach ( $data as $d ) { - $this->store->m_semdata[$sid]->addPropertyStubValue( reset( $d ), end( $d ) ); - } - $this->store->m_sdstate[$sid][$proptable->getName()] = true; - - self::$in_getSemanticData--; - return $this->store->m_semdata[$sid]; - } - - /** - * @see SMWStore::getPropertyValues - * - * @todo Retrieving all sortkeys (values for _SKEY with $subject null) - * is not supported. An empty array will be given. - * - * @since 1.8 - * @param $subject mixed SMWDIWikiPage or null - * @param $property SMWDIProperty - * @param $requestoptions SMWRequestOptions - * @return array of SMWDataItem - */ - public function getPropertyValues( $subject, SMWDIProperty $property, $requestoptions = null ) { - wfProfileIn( "SMWSQLStore3::getPropertyValues (SMW)" ); - - if ( $property->isInverse() ) { // inverses are working differently - $noninverse = new SMWDIProperty( $property->getKey(), false ); - $result = $this->getPropertySubjects( $noninverse, $subject, $requestoptions ); - } elseif ( !is_null( $subject ) ) { // subject given, use semantic data cache - $sid = $this->store->smwIds->getSMWPageID( $subject->getDBkey(), - $subject->getNamespace(), $subject->getInterwiki(), - $subject->getSubobjectName(), true ); - if ( $sid == 0 ) { - $result = array(); - } elseif ( $property->getKey() == '_SKEY' ) { - $this->store->smwIds->getSMWPageIDandSort( $subject->getDBkey(), - $subject->getNamespace(), $subject->getInterwiki(), - $subject->getSubobjectName(), $sortKey, true ); - $sortKeyDi = new SMWDIBlob( $sortKey ); - $result = $this->store->applyRequestOptions( array( $sortKeyDi ), $requestoptions ); - } else { - $propTableId = $this->store->findPropertyTableID( $property ); - $proptables = $this->store->getPropertyTables(); - $sd = $this->getSemanticDataFromTable( $sid, $subject, $proptables[$propTableId] ); - $result = $this->store->applyRequestOptions( $sd->getPropertyValues( $property ), $requestoptions ); - } - } else { // no subject given, get all values for the given property - $pid = $this->store->smwIds->getSMWPropertyID( $property ); - $tableid = $this->store->findPropertyTableID( $property ); - - if ( ( $pid == 0 ) || ( $tableid === '' ) ) { - wfProfileOut( "SMWSQLStore3::getPropertyValues (SMW)" ); - return array(); - } - - $proptables = $this->store->getPropertyTables(); - $data = $this->fetchSemanticData( $pid, $property, $proptables[$tableid], false, $requestoptions ); - $result = array(); - $propertyTypeId = $property->findPropertyTypeID(); - $propertyDiId = DataTypeRegistry::getInstance()->getDataItemId( $propertyTypeId ); - - foreach ( $data as $dbkeys ) { - try { - $diHandler = $this->store->getDataItemHandlerForDIType( $propertyDiId ); - $result[] = $diHandler->dataItemFromDBKeys( $dbkeys ); - } catch ( SMWDataItemException $e ) { - // maybe type assignment changed since data was stored; - // don't worry, but we can only drop the data here - } - } - } - - wfProfileOut( "SMWSQLStore3::getPropertyValues (SMW)" ); - - return $result; - } - - /** - * Helper function for reading all data for from a given property table - * (specified by an SMWSQLStore3Table object), based on certain - * restrictions. The function can filter data based on the subject (1) - * or on the property it belongs to (2) -- but one of those must be - * done. The Boolean $issubject is true for (1) and false for (2). - * - * In case (1), the first two parameters are taken to refer to a - * subject; in case (2) they are taken to refer to a property. In any - * case, the retrieval is limited to the specified $proptable. The - * parameters are an internal $id (of a subject or property), and an - * $object (being an SMWDIWikiPage or SMWDIProperty). Moreover, when - * filtering by property, it is assumed that the given $proptable - * belongs to the property: if it is a table with fixed property, it - * will not be checked that this is the same property as the one that - * was given in $object. - * - * In case (1), the result in general is an array of pairs (arrays of - * size 2) consisting of a property key (string), and DB keys (array if - * many, string if one) from which a datvalue object for this value can - * be built. It is possible that some of the DB keys are based on - * internal objects; these will be represented by similar result arrays - * of (recursive calls of) fetchSemanticData(). - * - * In case (2), the result is simply an array of DB keys (array) - * without the property keys. Container objects will be encoded with - * nested arrays like in case (1). - * - * @todo Maybe share DB handler; asking for it seems to take quite some - * time and we do not want to change it in one call. - * - * @since 1.8 - * @param integer $id - * @param SMWDataItem $object - * @param SMWSQLStore3Table $proptable - * @param boolean $issubject - * @param SMWRequestOptions $requestoptions - * - * @return array - */ - protected function fetchSemanticData( $id, SMWDataItem $object = null, SMWSQLStore3Table $proptable, $issubject = true, SMWRequestOptions $requestoptions = null ) { - // stop if there is not enough data: - // properties always need to be given as object, - // subjects at least if !$proptable->idsubject - if ( ( $id == 0 ) || - ( is_null( $object ) && ( !$issubject || !$proptable->usesIdSubject() ) ) ) - return array(); - - wfProfileIn( "SMWSQLStore3::fetchSemanticData-" . $proptable->getName() . " (SMW)" ); - $result = array(); - $db = $this->store->getDatabase(); - - $diHandler = $this->store->getDataItemHandlerForDIType( $proptable->getDiType() ); - - // *** First build $from, $select, and $where for the DB query ***// - $from = $db->tableName( $proptable->getName() ); // always use actual table - - $select = ''; - $where = ''; - - if ( $issubject ) { // restrict subject, select property - $where .= ( $proptable->usesIdSubject() ) ? 's_id=' . $db->addQuotes( $id ) : - 's_title=' . $db->addQuotes( $object->getDBkey() ) . - ' AND s_namespace=' . $db->addQuotes( $object->getNamespace() ); - if ( !$proptable->isFixedPropertyTable() ) { // select property name - $from .= ' INNER JOIN ' . $db->tableName( SMWSql3SmwIds::tableName ) . ' AS p ON p_id=p.smw_id'; - $select .= 'p.smw_title as prop'; - } // else: fixed property, no select needed - } elseif ( !$proptable->isFixedPropertyTable() ) { // restrict property only - $where .= 'p_id=' . $db->addQuotes( $id ); - } - - $valuecount = 0; - // Don't use DISTINCT for value of one subject: - $usedistinct = !$issubject; - - $valueField = $diHandler->getIndexField(); - $labelField = $diHandler->getLabelField(); - $fields = $diHandler->getFetchFields(); - foreach ( $fields as $fieldname => $typeid ) { // select object column(s) - if ( $typeid == 'p' ) { // get data from ID table - $from .= ' INNER JOIN ' . $db->tableName( SMWSql3SmwIds::tableName ) . " AS o$valuecount ON $fieldname=o$valuecount.smw_id"; - $select .= ( ( $select !== '' ) ? ',' : '' ) . - "$fieldname AS id$valuecount" . - ",o$valuecount.smw_title AS v$valuecount" . - ",o$valuecount.smw_namespace AS v" . ( $valuecount + 1 ) . - ",o$valuecount.smw_iw AS v" . ( $valuecount + 2 ) . - ",o$valuecount.smw_sortkey AS v" . ( $valuecount + 3 ) . - ",o$valuecount.smw_subobject AS v" . ( $valuecount + 4 ); - - if ( $valueField == $fieldname ) { - $valueField = "o$valuecount.smw_sortkey"; - } - if ( $labelField == $fieldname ) { - $labelField = "o$valuecount.smw_sortkey"; - } - - $valuecount += 4; - } else { - $select .= ( ( $select !== '' ) ? ',' : '' ) . - "$fieldname AS v$valuecount"; - } - - $valuecount += 1; - } - - if ( !$issubject ) { // Apply sorting/string matching; only with given property - $where .= $this->store->getSQLConditions( $requestoptions, $valueField, $labelField, $where !== '' ); - } else { - $valueField = ''; - } - - // *** Now execute the query and read the results ***// - $res = $db->select( $from, $select, $where, __METHOD__, - ( $usedistinct ? - $this->store->getSQLOptions( $requestoptions, $valueField ) + array( 'DISTINCT' ) : - $this->store->getSQLOptions( $requestoptions, $valueField ) - ) ); - - foreach ( $res as $row ) { - if ( $issubject ) { // use joined or predefined property name - $propertykey = $proptable->isFixedPropertyTable() ? $proptable->getFixedProperty() : $row->prop; - } - - // Use enclosing array only for results with many values: - if ( $valuecount > 1 ) { - $valuekeys = array(); - for ( $i = 0; $i < $valuecount; $i += 1 ) { // read the value fields from the current row - $fieldname = "v$i"; - $valuekeys[] = $row->$fieldname; - } - } else { - $valuekeys = $row->v0; - } - - // Filter out any accidentally retrieved internal things (interwiki starts with ":"): - if ( $valuecount < 3 || implode( '', $fields ) != 'p' || - $valuekeys[2] === '' || $valuekeys[2]{0} != ':' ) { - $result[] = $issubject ? array( $propertykey, $valuekeys ) : $valuekeys; - } - } - - $db->freeResult( $res ); - wfProfileOut( "SMWSQLStore3::fetchSemanticData-" . $proptable->getName() . " (SMW)" ); - - return $result; - } - - /** - * @see SMWStore::getPropertySubjects - * - * @todo This method cannot retrieve subjects for sortkeys, i.e., for - * property _SKEY. Only empty arrays will be returned there. - * - * @param SMWDIProperty $property - * @param mixed $value SMWDataItem or null - * @param SMWRequestOptions $requestoptions - * - * @return array of SMWDIWikiPage - */ - public function getPropertySubjects( SMWDIProperty $property, $value, $requestoptions = null ) { - /// TODO: should we share code with #ask query computation here? Just use queries? - wfProfileIn( "SMWSQLStore3::getPropertySubjects (SMW)" ); - - if ( $property->isInverse() ) { // inverses are working differently - $noninverse = new SMWDIProperty( $property->getKey(), false ); - $result = $this->getPropertyValues( $value, $noninverse, $requestoptions ); - wfProfileOut( "SMWSQLStore3::getPropertySubjects (SMW)" ); - return $result; - } - - // First build $select, $from, and $where for the DB query - $where = $from = ''; - $pid = $this->store->smwIds->getSMWPropertyID( $property ); - $tableid = $this->store->findPropertyTableID( $property ); - - if ( ( $pid == 0 ) || ( $tableid === '' ) ) { - wfProfileOut( "SMWSQLStoreLight::getPropertySubjects (SMW)" ); - return array(); - } - - $proptables = $this->store->getPropertyTables(); - $proptable = $proptables[$tableid]; - $db = $this->store->getDatabase(); - - if ( $proptable->usesIdSubject() ) { // join with ID table to get title data - $from = $db->tableName( SMWSql3SmwIds::tableName ) . " INNER JOIN " . $db->tableName( $proptable->getName() ) . " AS t1 ON t1.s_id=smw_id"; - $select = 'smw_title, smw_namespace, smw_iw, smw_sortkey, smw_subobject'; - } else { // no join needed, title+namespace as given in proptable - $from = $db->tableName( $proptable->getName() ) . " AS t1"; - $select = 's_title AS smw_title, s_namespace AS smw_namespace, \'\' AS smw_iw, s_title AS smw_sortkey, \'\' AS smw_subobject'; - } - - if ( !$proptable->isFixedPropertyTable() ) { - $where .= ( $where ? ' AND ' : '' ) . "t1.p_id=" . $db->addQuotes( $pid ); - } - - $this->prepareValueQuery( $from, $where, $proptable, $value, 1 ); - - // *** Now execute the query and read the results ***// - $result = array(); - $res = $db->select( $from, 'DISTINCT ' . $select, - $where . $this->store->getSQLConditions( $requestoptions, 'smw_sortkey', 'smw_sortkey', $where !== '' ), - __METHOD__, $this->store->getSQLOptions( $requestoptions, 'smw_sortkey' ) ); - - $diHandler = $this->store->getDataItemHandlerForDIType( SMWDataItem::TYPE_WIKIPAGE ); - - foreach ( $res as $row ) { - try { - if ( $row->smw_iw === '' || $row->smw_iw{0} != ':' ) { // filter special objects - $result[] = $diHandler->dataItemFromDBKeys( array_values( (array)$row ) ); - } - } catch ( SMWDataItemException $e ) { - // silently drop data, should be extremely rare and will usually fix itself at next edit - } - } - - $db->freeResult( $res ); - wfProfileOut( "SMWSQLStore3::getPropertySubjects (SMW)" ); - - return $result; - } - - - /** - * Helper function to compute from and where strings for a DB query so that - * only rows of the given value object match. The parameter $tableindex - * counts that tables used in the query to avoid duplicate table names. The - * parameter $proptable provides the SMWSQLStore3Table object that is - * queried. - * - * @todo Maybe do something about redirects. The old code was - * $oid = $this->store->smwIds->getSMWPageID($value->getDBkey(),$value->getNamespace(),$value->getInterwiki(),false); - * - * @note This method cannot handle DIContainer objects with sortkey - * properties correctly. This should never occur, but it would be good - * to fail in a more controlled way if it ever does. - * - * @param string $from - * @param string $where - * @param SMWSQLStore3Table $proptable - * @param SMWDataItem $value - * @param integer $tableindex - */ - protected function prepareValueQuery( &$from, &$where, $proptable, $value, $tableindex = 1 ) { - $db = $this->store->getDatabase(); - - if ( $value instanceof SMWDIContainer ) { // recursive handling of containers - $keys = array_keys( $proptable->getFields( $this->store ) ); - $joinfield = "t$tableindex." . reset( $keys ); // this must be a type 'p' object - $proptables = $this->store->getPropertyTables(); - $semanticData = $value->getSemanticData(); - - foreach ( $semanticData->getProperties() as $subproperty ) { - $tableid = $this->store->findPropertyTableID( $subproperty ); - $subproptable = $proptables[$tableid]; - - foreach ( $semanticData->getPropertyValues( $subproperty ) as $subvalue ) { - $tableindex++; - - if ( $subproptable->usesIdSubject() ) { // simply add property table to check values - $from .= " INNER JOIN " . $db->tableName( $subproptable->getName() ) . " AS t$tableindex ON t$tableindex.s_id=$joinfield"; - } else { // exotic case with table that uses subject title+namespace in container object (should never happen in SMW core) - $from .= " INNER JOIN " . $db->tableName( SMWSql3SmwIds::tableName ) . " AS ids$tableindex ON ids$tableindex.smw_id=$joinfield" . - " INNER JOIN " . $db->tableName( $subproptable->getName() ) . " AS t$tableindex ON " . - "t$tableindex.s_title=ids$tableindex.smw_title AND t$tableindex.s_namespace=ids$tableindex.smw_namespace"; - } - - if ( !$subproptable->isFixedPropertyTable() ) { // the ID we get should be !=0, so no point in filtering the converse - $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.p_id=" . $db->addQuotes( $this->store->smwIds->getSMWPropertyID( $subproperty ) ); - } - - $this->prepareValueQuery( $from, $where, $subproptable, $subvalue, $tableindex ); - } - } - } elseif ( !is_null( $value ) ) { // add conditions for given value - $diHandler = $this->store->getDataItemHandlerForDIType( $value->getDIType() ); - foreach ( $diHandler->getWhereConds( $value ) as $fieldname => $value ) { - $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.$fieldname=" . $db->addQuotes( $value ); - } - } - } - - /** - * @see SMWStore::getAllPropertySubjects - * - * @param SMWDIProperty $property - * @param SMWRequestOptions $requestoptions - * - * @return array of SMWDIWikiPage - */ - public function getAllPropertySubjects( SMWDIProperty $property, $requestoptions = null ) { - wfProfileIn( "SMWSQLStore3::getAllPropertySubjects (SMW)" ); - $result = $this->getPropertySubjects( $property, null, $requestoptions ); - wfProfileOut( "SMWSQLStore3::getAllPropertySubjects (SMW)" ); - - return $result; - } - - /** - * @see Store::getProperties - * - * @param SMWDIWikiPage $subject - * @param SMWRequestOptions|null $requestOptions - * - * @return SMWDataItem[] - */ - public function getProperties( SMWDIWikiPage $subject, $requestOptions = null ) { - wfProfileIn( "SMWSQLStore3::getProperties (SMW)" ); - $sid = $this->store->smwIds->getSMWPageID( - $subject->getDBkey(), - $subject->getNamespace(), - $subject->getInterwiki(), - $subject->getSubobjectName() - ); - - if ( $sid == 0 ) { // no id, no page, no properties - wfProfileOut( "SMWSQLStore3::getProperties (SMW)" ); - return array(); - } - - $db = $this->store->getDatabase(); - $result = array(); - - // potentially need to get more results, since options apply to union - if ( $requestOptions !== null ) { - $suboptions = clone $requestOptions; - $suboptions->limit = $requestOptions->limit + $requestOptions->offset; - $suboptions->offset = 0; - } else { - $suboptions = null; - } - - foreach ( $this->store->getPropertyTables() as $propertyTable ) { - if ( $propertyTable->usesIdSubject() ) { - $where = 's_id=' . $db->addQuotes( $sid ); - } elseif ( $subject->getInterwiki() === '' ) { - $where = 's_title=' . $db->addQuotes( $subject->getDBkey() ) . ' AND s_namespace=' . $db->addQuotes( $subject->getNamespace() ); - } else { // subjects with non-emtpy interwiki cannot have properties - continue; - } - - if ( $propertyTable->isFixedPropertyTable() ) { - // just check if subject occurs in table - $res = $db->select( - $propertyTable->getName(), - '*', - $where, - __METHOD__, - array( 'LIMIT' => 1 ) - ); - - if ( $db->numRows( $res ) > 0 ) { - $result[] = new SMWDIProperty( $propertyTable->getFixedProperty() ); - } - - - } else { - // select all properties - $from = $db->tableName( $propertyTable->getName() ); - - $from .= " INNER JOIN " . $db->tableName( SMWSql3SmwIds::tableName ) . " ON smw_id=p_id"; - $res = $db->select( $from, 'DISTINCT smw_title,smw_sortkey', - // (select sortkey since it might be used in ordering (needed by Postgres)) - $where . $this->store->getSQLConditions( $suboptions, 'smw_sortkey', 'smw_sortkey' ), - __METHOD__, $this->store->getSQLOptions( $suboptions, 'smw_sortkey' ) ); - - foreach ( $res as $row ) { - $result[] = new SMWDIProperty( $row->smw_title ); - } - } - - $db->freeResult( $res ); - } - - // apply options to overall result - $result = $this->store->applyRequestOptions( $result, $requestOptions ); - - wfProfileOut( "SMWSQLStore3::getProperties (SMW)" ); - - return $result; - } - - /** - * Implementation of SMWStore::getInProperties(). This function is meant to - * be used for finding properties that link to wiki pages. - * - * @since 1.8 - * @see SMWStore::getInProperties - * @param SMWDataItem $value - * @param SMWRequestOptions $requestoptions - * - * @return array of SMWWikiPageValue - */ - public function getInProperties( SMWDataItem $value, $requestoptions = null ) { - wfProfileIn( "SMWSQLStore3::getInProperties (SMW)" ); - - $db = $this->store->getDatabase(); - $result = array(); - - // Potentially need to get more results, since options apply to union. - if ( $requestoptions !== null ) { - $suboptions = clone $requestoptions; - $suboptions->limit = $requestoptions->limit + $requestoptions->offset; - $suboptions->offset = 0; - } else { - $suboptions = null; - } - - $diType = $value->getDIType(); - - foreach ( $this->store->getPropertyTables() as $proptable ) { - if ( $diType != $proptable->getDiType() ) { - continue; - } - - $where = $from = ''; - if ( !$proptable->isFixedPropertyTable() ) { // join ID table to get property titles - $from = $db->tableName( SMWSql3SmwIds::tableName ) . " INNER JOIN " . $db->tableName( $proptable->getName() ) . " AS t1 ON t1.p_id=smw_id"; - $this->prepareValueQuery( $from, $where, $proptable, $value, 1 ); - - $res = $db->select( $from, 'DISTINCT smw_title,smw_sortkey', - // select sortkey since it might be used in ordering (needed by Postgres) - $where . $this->store->getSQLConditions( $suboptions, 'smw_sortkey', 'smw_sortkey', $where !== '' ), - __METHOD__, $this->store->getSQLOptions( $suboptions, 'smw_sortkey' ) ); - - foreach ( $res as $row ) { - try { - $result[] = new SMWDIProperty( $row->smw_title ); - } catch (SMWDataItemException $e) { - // has been observed to happen (empty property title); cause unclear; ignore this data - } - } - } else { - $from = $db->tableName( $proptable->getName() ) . " AS t1"; - $this->prepareValueQuery( $from, $where, $proptable, $value, 1 ); - $res = $db->select( $from, '*', $where, __METHOD__, array( 'LIMIT' => 1 ) ); - - if ( $db->numRows( $res ) > 0 ) { - $result[] = new SMWDIProperty( $proptable->getFixedProperty() ); - } - } - $db->freeResult( $res ); - } - - $result = $this->store->applyRequestOptions( $result, $requestoptions ); // apply options to overall result - wfProfileOut( "SMWSQLStore3::getInProperties (SMW)" ); - - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_SetupHandlers.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_SetupHandlers.php deleted file mode 100755 index 23293f81..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_SetupHandlers.php +++ /dev/null @@ -1,448 +0,0 @@ -<?php - -use SMW\MediaWiki\Jobs\UpdateJob; -use SMW\Reporter\MessageReporter; - -/** - * @file - * @ingroup SMWStore - * @since 1.8 - */ - -/** - * Class Handling all the setup methods for SMWSQLStore3 - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author Nischay Nahata - * - * @since 1.8 - * @ingroup SMWStore - */ -class SMWSQLStore3SetupHandlers implements MessageReporter { - - /** - * The store used by this setupHandler - * - * @since 1.8 - * @var SMWSQLStore3 - */ - protected $store; - - public function __construct( SMWSQLStore3 $parentstore ) { - $this->store = $parentstore; - } - - public function setup( $verbose = true ) { - $this->reportProgress( "Setting up standard database configuration for SMW ...\n\n", $verbose ); - $this->reportProgress( "Selected storage engine is \"SMWSQLStore3\" (or an extension thereof)\n\n", $verbose ); - - $db = $this->store->getDatabase()->acquireWriteConnection(); - - $this->setupTables( $verbose, $db ); - $this->setupPredefinedProperties( $verbose, $db ); - - return true; - } - - /** - * Create required SQL tables. This function also performs upgrades of - * table contents when required. - * - * @see SMWSql3SmwIds for documentation of the SMW IDs table. - * - * @since 1.8 - * @param boolean $verbose - * @param DatabaseBase $db used for writing - */ - protected function setupTables( $verbose, $db ) { - global $wgDBtype; - - $reportTo = $verbose ? $this : null; // Use $this to report back from static SMWSQLHelpers. - - // Repeatedly used DB field types defined here for convenience. - $dbtypes = array( - 'b' => ( $wgDBtype == 'postgres' ? 'BOOLEAN' : 'TINYINT(1)' ), - 't' => SMWSQLHelpers::getStandardDBType( 'title' ), - 'l' => SMWSQLHelpers::getStandardDBType( 'blob' ), - 'f' => ( $wgDBtype == 'postgres' ? 'DOUBLE PRECISION' : 'DOUBLE' ), - 'i' => ( $wgDBtype == 'postgres' ? 'bigint' : 'INT(8)' ), - 'j' => ( $wgDBtype == 'postgres' || $wgDBtype == 'sqlite' ? 'INTEGER' : 'INT(8) UNSIGNED' ), - 'p' => SMWSQLHelpers::getStandardDBType( 'id' ), - 'n' => SMWSQLHelpers::getStandardDBType( 'namespace' ), - 'w' => SMWSQLHelpers::getStandardDBType( 'iw' ) - ); - - switch ( $wgDBtype ) { - case 'sqlite': - $idType = $dbtypes['p'] . ' NOT NULL PRIMARY KEY AUTOINCREMENT'; - break; - case 'postgres': - $idType = $dbtypes['p'] . ' NOT NULL PRIMARY KEY'; - break; - default: - $idType = $dbtypes['p'] . ' NOT NULL KEY AUTO_INCREMENT'; - break; - } - - // Set up table for internal IDs used in this store: - SMWSQLHelpers::setupTable( - SMWSql3SmwIds::tableName, - array( - 'smw_id' => $idType, - 'smw_namespace' => $dbtypes['n'] . ' NOT NULL', - 'smw_title' => $dbtypes['t'] . ' NOT NULL', - 'smw_iw' => $dbtypes['w'] . ' NOT NULL', - 'smw_subobject' => $dbtypes['t'] . ' NOT NULL', - 'smw_sortkey' => $dbtypes['t'] . ' NOT NULL', - 'smw_proptable_hash' => $dbtypes['l'] - ), - $db, - $reportTo - ); - - SMWSQLHelpers::setupIndex( - SMWSql3SmwIds::tableName, - array( - 'smw_id', - 'smw_id,smw_sortkey', - 'smw_title,smw_namespace,smw_iw,smw_subobject', // id lookup - 'smw_sortkey' // select by sortkey (range queries) - ), - $db - ); - - // Set up concept cache: member elements (s)->concepts (o) - SMWSQLHelpers::setupTable( - SMWSQLStore3::CONCEPT_CACHE_TABLE, - array( - 's_id' => $dbtypes['p'] . ' NOT NULL', - 'o_id' => $dbtypes['p'] . ' NOT NULL' - ), - $db, - $reportTo - ); - - SMWSQLHelpers::setupIndex( SMWSQLStore3::CONCEPT_CACHE_TABLE, array( 'o_id' ), $db ); - - // Set up table for stats on Properties (only counts for now) - SMWSQLHelpers::setupTable( - SMWSQLStore3::PROPERTY_STATISTICS_TABLE, - array( - 'p_id' => $dbtypes['p'], - 'usage_count' => ( $wgDBtype == 'postgres' ? $dbtypes['i'] : $dbtypes['j'] ) - ), - $db, - $reportTo - ); - - SMWSQLHelpers::setupIndex( SMWSQLStore3::PROPERTY_STATISTICS_TABLE, array( array( 'p_id', 'UNIQUE INDEX' ), 'usage_count' ), $db ); - - // Set up all property tables as defined: - $this->setupPropertyTables( $dbtypes, $db, $reportTo ); - - $this->reportProgress( "Database initialized successfully.\n\n", $verbose ); - } - - /** - * Sets up the property tables. - * - * @since 1.8 - * @param array $dbtypes - * @param DatabaseBase|Database $db - * @param SMWSQLStore3SetupHandlers|null $reportTo - */ - protected function setupPropertyTables( array $dbtypes, $db, SMWSQLStore3SetupHandlers $reportTo = null ) { - $addedCustomTypeSignatures = false; - - foreach ( $this->store->getPropertyTables() as $proptable ) { - $diHandler = $this->store->getDataItemHandlerForDIType( $proptable->getDiType() ); - - // Prepare indexes. By default, property-value tables - // have the following indexes: - // - // sp: getPropertyValues(), getSemanticData(), getProperties() - // po: ask, getPropertySubjects() - // - // The "p" component is omitted for tables with fixed property. - $indexes = array(); - if ( $proptable->usesIdSubject() ) { - $fieldarray = array( 's_id' => $dbtypes['p'] . ' NOT NULL' ); - $indexes['sp'] = 's_id'; - } else { - $fieldarray = array( 's_title' => $dbtypes['t'] . ' NOT NULL', 's_namespace' => $dbtypes['n'] . ' NOT NULL' ); - $indexes['sp'] = 's_title,s_namespace'; - } - - $indexes['po'] = $diHandler->getIndexField(); - - if ( !$proptable->isFixedPropertyTable() ) { - $fieldarray['p_id'] = $dbtypes['p'] . ' NOT NULL'; - $indexes['po'] = 'p_id,' . $indexes['po']; - $indexes['sp'] = $indexes['sp'] . ',p_id'; - } - - // TODO Special handling; concepts should be handled differently - // in the future. See comments in SMW_DIHandler_Concept.php. - if ( $proptable->getDiType() == SMWDataItem::TYPE_CONCEPT ) { - unset( $indexes['po'] ); - } - - $indexes = array_merge( $indexes, $diHandler->getTableIndexes() ); - $indexes = array_unique( $indexes ); - - foreach ( $diHandler->getTableFields() as $fieldname => $typeid ) { - // If the type signature is not recognized and the custom signatures have not been added, add them. - if ( !$addedCustomTypeSignatures && !array_key_exists( $typeid, $dbtypes ) ) { - wfRunHooks( 'SMWCustomSQLStoreFieldType', array( &$dbtypes ) ); - $addedCustomTypeSignatures = true; - } - - // Only add the type when the signature was recognized, otherwise ignore it silently. - if ( array_key_exists( $typeid, $dbtypes ) ) { - $fieldarray[$fieldname] = $dbtypes[$typeid]; - } - } - - SMWSQLHelpers::setupTable( $proptable->getName(), $fieldarray, $db, $reportTo ); - - SMWSQLHelpers::setupIndex( $proptable->getName(), $indexes, $db, $reportTo ); - } - } - - /** - * Create some initial DB entries for important built-in properties. Having the DB contents predefined - * allows us to safe DB calls when certain data is needed. At the same time, the entries in the DB - * make sure that DB-based functions work as with all other properties. - */ - protected function setupPredefinedProperties( $verbose, DatabaseBase $db ) { - global $wgDBtype; - - $this->reportProgress( "Setting up internal property indices ...\n", $verbose ); - - // Check if we already have this structure - $borderiw = $db->selectField( SMWSql3SmwIds::tableName, 'smw_iw', 'smw_id=' . $db->addQuotes( 50 ) ); - - if ( $borderiw != SMW_SQL3_SMWBORDERIW ) { - $this->reportProgress( " ... allocating space for internal properties ...\n", $verbose ); - $this->store->smwIds->moveSMWPageID( 50 ); // make sure position 50 is empty - - $db->insert( SMWSql3SmwIds::tableName, array( - 'smw_id' => 50, - 'smw_title' => '', - 'smw_namespace' => 0, - 'smw_iw' => SMW_SQL3_SMWBORDERIW, - 'smw_subobject' => '', - 'smw_sortkey' => '' - ), 'SMW::setup' - ); // put dummy "border element" on index 50 - - $this->reportProgress( ' ', $verbose ); - - for ( $i = 0; $i < 50; $i++ ) { // make way for built-in ids - $this->store->smwIds->moveSMWPageID( $i ); - $this->reportProgress( '.', $verbose ); - } - - $this->reportProgress( " done.\n", $verbose ); - } else { - $this->reportProgress( " ... space for internal properties already allocated.\n", $verbose ); - } - - // now write actual properties; do that each time, it is cheap enough and we can update sortkeys by current language - $this->reportProgress( " ... writing entries for internal properties ...", $verbose ); - - foreach ( SMWSql3SmwIds::$special_ids as $prop => $id ) { - $p = new SMWDIProperty( $prop ); - $db->replace( SMWSql3SmwIds::tableName, array( 'smw_id' ), array( - 'smw_id' => $id, - 'smw_title' => $p->getKey(), - 'smw_namespace' => SMW_NS_PROPERTY, - 'smw_iw' => $this->store->smwIds->getPropertyInterwiki( $p ), - 'smw_subobject' => '', - 'smw_sortkey' => $p->getLabel() - ), 'SMW::setup' - ); - } - - $this->reportProgress( " done.\n", $verbose ); - - if ( $wgDBtype == 'postgres' ) { - $sequenceIndex = SMWSql3SmwIds::tableName . '_smw_id_seq'; - - $this->reportProgress( " ... updating {$sequenceIndex} sequence accordingly.\n", $verbose ); - - $max = $db->selectField( SMWSql3SmwIds::tableName, 'max(smw_id)', array(), __METHOD__ ); - $max += 1; - - $db->query( "ALTER SEQUENCE {$sequenceIndex} RESTART WITH {$max}", __METHOD__ ); - } - - $this->reportProgress( "Internal properties initialized successfully.\n", $verbose ); - } - - public function drop( $verbose = true ) { - global $wgDBtype; - - $this->reportProgress( "Deleting all database content and tables generated by SMW ...\n\n", $verbose ); - $dbw = wfGetDB( DB_MASTER ); - $tables = array( SMWSql3SmwIds::tableName, SMWSQLStore3::CONCEPT_CACHE_TABLE, SMWSQLStore3::PROPERTY_STATISTICS_TABLE ); - - foreach ( $this->store->getPropertyTables() as $proptable ) { - $tables[] = $proptable->getName(); - } - - foreach ( $tables as $table ) { - $name = $dbw->tableName( $table ); - $dbw->query( 'DROP TABLE ' . ( $wgDBtype == 'postgres' ? '' : 'IF EXISTS ' ) . $name, 'SMWSQLStore3::drop' ); - $this->reportProgress( " ... dropped table $name.\n", $verbose ); - } - - $this->reportProgress( "All data removed successfully.\n", $verbose ); - - return true; - } - - /** - * @see SMWStore::refreshData - * - * @todo This method will be overhauled in SMW 1.9 to become cleaner - * and more robust. - * - * @param integer $index - * @param integer $count - * @param mixed $namespaces Array or false - * @param boolean $usejobs - * - * @return decimal between 0 and 1 to indicate the overall progress of the refreshing - */ - public function refreshData( &$index, $count, $namespaces = false, $usejobs = true ) { - $updatejobs = array(); - $emptyrange = true; // was nothing done in this run? - - // Update by MediaWiki page id --> make sure we get all pages. - $tids = array(); - - // Array of ids - for ( $i = $index; $i < $index + $count; $i++ ) { - $tids[] = $i; - } - - $titles = Title::newFromIDs( $tids ); - - foreach ( $titles as $title ) { - if ( ( $namespaces == false ) || ( in_array( $title->getNamespace(), $namespaces ) ) ) { - $updatejobs[] = new SMWUpdateJob( $title ); - $emptyrange = false; - } - } - - // update by internal SMW id --> make sure we get all objects in SMW - $dbr = wfGetDB( DB_SLAVE ); - - $res = $dbr->select( - SMWSql3SmwIds::tableName, - array( 'smw_id', 'smw_title', 'smw_namespace', 'smw_iw', 'smw_subobject' ), - array( - "smw_id >= $index ", - " smw_id < " . $dbr->addQuotes( $index + $count ) - ), - __METHOD__ - ); - - foreach ( $res as $row ) { - $emptyrange = false; // note this even if no jobs were created - - if ( $namespaces && !in_array( $row->smw_namespace, $namespaces ) ) continue; - - // Find page to refresh, even for special properties: - if ( $row->smw_title != '' && $row->smw_title{0} != '_' ) { - $titleKey = $row->smw_title; - } elseif ( $row->smw_namespace == SMW_NS_PROPERTY && $row->smw_iw == '' && $row->smw_subobject == '' ) { - $titleKey = str_replace( ' ', '_', SMWDIProperty::findPropertyLabel( $row->smw_title ) ); - } else { - $titleKey = ''; - } - - if ( $row->smw_subobject !== '' ) { - // leave subobjects alone; they ought to be changed with their pages - } elseif ( ( $row->smw_iw === '' || $row->smw_iw == SMW_SQL3_SMWREDIIW ) && - $titleKey != '' ){ - // objects representing pages - // TODO: special treament of redirects needed, since the store will - // not act on redirects that did not change according to its records - $title = Title::makeTitleSafe( $row->smw_namespace, $titleKey ); - - if ( $title !== null && !$title->exists() ) { - $updatejobs[] = new UpdateJob( $title ); - } - } elseif ( $row->smw_iw == SMW_SQL3_SMWIW_OUTDATED ) { // remove outdated internal object references - $dbw = wfGetDB( DB_MASTER ); - foreach ( $this->store->getPropertyTables() as $proptable ) { - if ( $proptable->usesIdSubject() ) { - $dbw->delete( $proptable->getName(), array( 's_id' => $row->smw_id ), __METHOD__ ); - } - } - - $dbw->delete( SMWSql3SmwIds::tableName, array( 'smw_id' => $row->smw_id ), __METHOD__ ); - } elseif ( $titleKey != '' ) { // "normal" interwiki pages or outdated internal objects -- delete - $diWikiPage = new SMWDIWikiPage( $titleKey, $row->smw_namespace, $row->smw_iw ); - $emptySemanticData = new SMWSemanticData( $diWikiPage ); - $this->store->updateData( $emptySemanticData ); - } - } - $dbr->freeResult( $res ); - - wfRunHooks('smwRefreshDataJobs', array(&$updatejobs)); - - if ( $usejobs ) { - Job::batchInsert( $updatejobs ); - } else { - foreach ( $updatejobs as $job ) { - $job->run(); - } - } - - $nextpos = $index + $count; - - if ( $emptyrange ) { // nothing found, check if there will be more pages later on - $next1 = $dbr->selectField( 'page', 'page_id', "page_id >= $nextpos", __METHOD__, array( 'ORDER BY' => "page_id ASC" ) ); - $next2 = $dbr->selectField( SMWSql3SmwIds::tableName, 'smw_id', "smw_id >= $nextpos", __METHOD__, array( 'ORDER BY' => "smw_id ASC" ) ); - $nextpos = $next2 != 0 && $next2 < $next1 ? $next2 : $next1; - } - - $max1 = $dbr->selectField( 'page', 'MAX(page_id)', '', __METHOD__ ); - $max2 = $dbr->selectField( SMWSql3SmwIds::tableName, 'MAX(smw_id)', '', __METHOD__ ); - $index = $nextpos ? $nextpos : -1; - - return $index > 0 ? $index / max( $max1, $max2 ) : 1; - } - - /** - * Print some output to indicate progress. The output message is given by - * $msg, while $verbose indicates whether or not output is desired at all. - */ - public function reportProgress( $msg, $verbose = true ) { - if ( $verbose ) { - if ( ob_get_level() == 0 ) { // be sure to have some buffer, otherwise some PHPs complain - ob_start(); - } - - print $msg; - ob_flush(); - flush(); - } - } - - /** - * @see MessageReporter::reportMessage - * - * @since 1.9 - * - * @param string $message - */ - public function reportMessage( $message ) { - $this->reportProgress( $message ); - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Writers.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Writers.php deleted file mode 100644 index 07d08e31..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_SQLStore3_Writers.php +++ /dev/null @@ -1,1180 +0,0 @@ -<?php - -use SMW\MediaWiki\Jobs\UpdateJob; -use SMW\SQLStore\PropertyStatisticsTable; -use SMW\SemanticData; -use SMW\DIWikiPage; - -/** - * Class Handling all the write and update methods for SMWSQLStore3. - * - * @note Writing may also require some reading operations. Operations that are - * only needed in helper methods of this class should be implemented here, not - * in SMWSQLStore3Readers. - * - * @author Markus Krötzsch - * @author Jeroen De Dauw - * @author Nischay Nahata - * - * @since 1.8 - * @ingroup SMWStore - */ -class SMWSQLStore3Writers { - - /** - * The store used by this store writer. - * - * @since 1.8 - * @var SMWSQLStore3 - */ - protected $store; - - /** - * Constructor. - * - * @since 1.8 - * @param SMWSQLStore3 $parentStore - */ - public function __construct( SMWSQLStore3 $parentStore ) { - $this->store = $parentStore; - } - - - /** - * @see SMWStore::deleteSubject - * - * @since 1.8 - * @param Title $title - */ - public function deleteSubject( Title $title ) { - wfProfileIn( __METHOD__ ); - wfRunHooks( 'SMWSQLStore3::deleteSubjectBefore', array( $this->store, $title ) ); - - $emptySemanticData = new SemanticData( DIWikiPage::newFromTitle( $title ) ); - $this->doDataUpdate( $emptySemanticData ); - - if ( $title->getNamespace() === SMW_NS_CONCEPT ) { // make sure to clear caches - $db = $this->store->getDatabase(); - - $id = $this->store->getObjectIds()->getSMWPageID( - $title->getDBkey(), - $title->getNamespace(), - $title->getInterwiki(), - '', - false - ); - - $db->delete( - 'smw_fpt_conc', - array( 's_id' => $id ), - 'SMW::deleteSubject::Conc' - ); - - $db->delete( - SMWSQLStore3::CONCEPT_CACHE_TABLE, - array( 'o_id' => $id ), - 'SMW::deleteSubject::Conccache' - ); - } - - // 1.9.0.1 - // The update of possible associative entities is handled by DeleteSubjectJob which is invoked during - // the ArticleDelete hook - - ///TODO: Possibly delete ID here (at least for non-properties/categories, if not used in any place in rels2) - - wfRunHooks( 'SMWSQLStore3::deleteSubjectAfter', array( $this->store, $title ) ); - - wfProfileOut( __METHOD__ ); - } - - /** - * @see SMWStore::doDataUpdate - * - * @since 1.8 - * @param SMWSemanticData $data - */ - public function doDataUpdate( SMWSemanticData $data ) { - wfProfileIn( "SMWSQLStore3::updateData (SMW)" ); - wfRunHooks( 'SMWSQLStore3::updateDataBefore', array( $this->store, $data ) ); - - // Update data about our main subject - $this->doFlatDataUpdate( $data ); - - // Update data about our subobjects - $subSemanticData = $data->getSubSemanticData(); - - foreach( $subSemanticData as $subobjectData ) { - $this->doFlatDataUpdate( $subobjectData ); - } - - // Delete data about other subobjects no longer used - $subobjects = $this->getSubobjects( $data->getSubject() ); - - foreach( $subobjects as $smw_id => $subobject ) { - if( !array_key_exists( $subobject->getSubobjectName(), $subSemanticData ) ) { - $emptySemanticData = new SMWSemanticData( $subobject ); - $this->doFlatDataUpdate( $emptySemanticData ); - //TODO make delete job to find out if IDs can be deleted altogether - } - } - - // TODO Make overall diff SMWSemanticData containers and run a hook - - wfRunHooks( 'SMWSQLStore3::updateDataAfter', array( $this->store, $data ) ); - - wfProfileOut( "SMWSQLStore3::updateData (SMW)" ); - } - - /** - * Update the store to contain the given data, without taking any - * subobject data into account. - * - * @since 1.8 - * @param SMWSemanticData $data - */ - protected function doFlatDataUpdate( SMWSemanticData $data ) { - $subject = $data->getSubject(); - - // Take care of redirects - $redirects = $data->getPropertyValues( new SMWDIProperty( '_REDI' ) ); - - if ( count( $redirects ) > 0 ) { - $redirect = end( $redirects ); // at most one redirect per page - $this->updateRedirects( - $subject->getDBkey(), - $subject->getNamespace(), - $redirect->getDBkey(), - $redirect->getNameSpace() - ); - // Stop here: - // * no support for annotations on redirect pages - // * updateRedirects takes care of deleting any previous data - return; - } else { - $this->updateRedirects( - $subject->getDBkey(), - $subject->getNamespace() - ); - } - - // Take care of the sortkey - $sortkeyDataItems = $data->getPropertyValues( new SMWDIProperty( '_SKEY' ) ); - $sortkeyDataItem = end( $sortkeyDataItems ); - - if ( $sortkeyDataItem instanceof SMWDIBlob ) { - $sortkey = $sortkeyDataItem->getString(); - } else { // default sortkey - $sortkey = str_replace( '_', ' ', $subject->getDBkey() ); - } - - // Always make an ID; this also writes sortkey and namespace data - $sid = $this->store->getObjectIds()->makeSMWPageID( - $subject->getDBkey(), - $subject->getNamespace(), - $subject->getInterwiki(), - $subject->getSubobjectName(), - true, - $sortkey, - true - ); - - // Take care of all remaining property table data - list( $deleteRows, $insertRows, $newHashes ) = $this->preparePropertyTableUpdates( $sid, $data ); - - $this->writePropertyTableUpdates( - $sid, - $deleteRows, - $insertRows, - $newHashes - ); - - // Update caches (may be important if jobs are directly following this call) - $this->setSemanticDataCache( $sid, $data ); - - // TODO Make overall diff SMWSemanticData containers and return them. - // This can only be done here, since the $deleteRows/$insertRows - // alone do not have enough information to compute this later (sortkey - // and redirects may also change). - } - - /** - * Method to get all subobjects for a given subject. - * - * @since 1.8 - * @param SMWDIWikiPage $subject - * - * @return array of smw_id => SMWDIWikiPage - */ - protected function getSubobjects( SMWDIWikiPage $subject ) { - - $db = $this->store->getDatabase(); - - $res = $db->select( SMWSql3SmwIds::tableName, - 'smw_id,smw_subobject', - 'smw_title = ' . $db->addQuotes( $subject->getDBkey() ) . ' AND ' . - 'smw_namespace = ' . $db->addQuotes( $subject->getNamespace() ) . ' AND ' . - 'smw_iw = ' . $db->addQuotes( $subject->getInterwiki() ) . ' AND ' . - 'smw_subobject != ' . $db->addQuotes( '' ), // The "!=" is why we cannot use MW array syntax here - __METHOD__ - ); - - $diHandler = $this->store->getDataItemHandlerForDIType( SMWDataItem::TYPE_WIKIPAGE ); - - $subobjects = array(); - foreach ( $res as $row ) { - $subobjects[$row->smw_id] = $diHandler->dataItemFromDBKeys( array( - $subject->getDBkey(), - $subject->getNamespace(), - $subject->getInterwiki(), - '', - $row->smw_subobject - ) ); - } - - $db->freeResult( $res ); - - return $subobjects; - } - - /** - * Create an array of rows to insert into property tables in order to - * store the given SMWSemanticData. The given $sid (subject page id) is - * used directly and must belong to the subject of the data container. - * Sortkeys are ignored since they are not stored in a property table - * but in the ID table. - * - * The returned array uses property table names as keys and arrays of - * table rows as values. Each table row is an array mapping column - * names to values. - * - * @note Property tables that do not use ids as subjects are ignored. - * This just excludes redirects that are handled differently anyway; - * it would not make a difference to include them here. - * - * @since 1.8 - * @param integer $sid - * @param SMWSemanticData $data - * @return array - */ - protected function preparePropertyTableInserts( $sid, SMWSemanticData $data ) { - $updates = array(); - - $subject = $data->getSubject(); - $propertyTables = $this->store->getPropertyTables(); - - foreach ( $data->getProperties() as $property ) { - - $tableId = $this->store->findPropertyTableID( $property ); - if ( is_null( $tableId ) ) { // not stored in a property table, e.g., sortkeys - continue; - } - - $propertyTable = $propertyTables[$tableId]; - if ( !$propertyTable->usesIdSubject() ) { // not using subject ids, e.g., redirects - continue; - } - - $insertValues = array( 's_id' => $sid ); - if ( !$propertyTable->isFixedPropertyTable() ) { - $insertValues['p_id'] = $this->store->smwIds->makeSMWPropertyID( $property ); - } - - foreach ( $data->getPropertyValues( $property ) as $di ) { - if ( $di instanceof SMWDIError ) { // ignore error values - continue; - } - if ( !array_key_exists( $propertyTable->getName(), $updates ) ) { - $updates[$propertyTable->getName()] = array(); - } - - $diHandler = $this->store->getDataItemHandlerForDIType( $di->getDIType() ); - // Note that array_merge creates a new array; not overwriting past entries here - $insertValues = array_merge( $insertValues, $diHandler->getInsertValues( $di ) ); - $updates[$propertyTable->getName()][] = $insertValues; - } - } - - // Special handling of Concepts - if ( $subject->getNamespace() === SMW_NS_CONCEPT && $subject->getSubobjectName() == '' ) { - $this->prepareConceptTableInserts( $sid, $updates ); - } - - return $updates; - } - - /** - * Add cache information to concept data and make sure that there is - * exactly one value for the concept table. - * - * @note This code will vanish when concepts have a more standard - * handling. So not point in optimizing this much now. - * - * @since 1.8 - * @param integer $sid - * @param &array $insertData - */ - private function prepareConceptTableInserts( $sid, &$insertData ) { - - $db = $this->store->getDatabase(); - - // Make sure that there is exactly one row to be written: - if ( array_key_exists( 'smw_fpt_conc', $insertData ) && !empty( $insertData['smw_fpt_conc'] ) ) { - $insertValues = end( $insertData['smw_fpt_conc'] ); - } else { - $insertValues = array( - 's_id' => $sid, - 'concept_txt' => '', - 'concept_docu' => '', - 'concept_features' => 0, - 'concept_size' => -1, - 'concept_depth' => -1 - ); - } - - // Add existing cache status data to this row: - $row = $db->selectRow( - 'smw_fpt_conc', - array( 'cache_date', 'cache_count' ), - array( 's_id' => $sid ), - 'SMWSQLStoreQueries::updateConcData' - ); - if ( $row === false ) { - $insertValues['cache_date'] = null; - $insertValues['cache_count'] = null; - } else { - $insertValues['cache_date'] = $row->cache_date; - $insertValues['cache_count'] = $row->cache_count; - } - - $insertData['smw_fpt_conc'] = array( $insertValues ); - } - - /** - * Create a string key for hashing an array of values that represents a - * row in the database. Used to eliminate duplicates and to support - * diff computation. This is not stored in the database, so it can be - * changed without causing any problems with legacy data. - * - * @since 1.8 - * @param array $databaseRow - * @return string - */ - protected static function makeDatabaseRowKey( array $databaseRow ) { - // Do not use serialize(): the MW database does not round-trip - // PHP objects reliably (they loose their type and become strings) - $keyString = ''; - foreach ( $databaseRow as $column => $value ) { - $keyString .= "#$column##$value#"; - } - return md5( $keyString ); - } - - /** - * Delete all matching values from old and new arrays and return the - * remaining new values as insert values and the remaining old values as - * delete values. - * - * @param array $oldValues - * @param array $newValues - * @return array - */ - protected function arrayDeleteMatchingValues( $oldValues, $newValues ) { - - // cycle through old values - foreach ( $oldValues as $oldKey => $oldValue ) { - - // cycle through new values - foreach ( $newValues as $newKey => $newValue ) { - // delete matching values; - // use of == is intentional to account for oldValues only - // containing strings while new values might also contain other - // types - if ( $newValue == $oldValue ) { - unset( $newValues[$newKey] ); - unset( $oldValues[$oldKey] ); - } - } - }; - - // arrays have to be renumbered because database functions expect an - // element with index 0 to be present in the array - return array( array_values( $newValues ), array_values( $oldValues ) ); - } - - /** - * Compute necessary insertions, deletions, and new table hashes for - * updating the database to contain $newData for the subject with ID - * $sid. Insertions and deletions are returned in as an array mapping - * table names to arrays of table rows. Each row is an array mapping - * column names to values as usual. The table hashes are returned as - * an array mapping table names to hash values. - * - * It is ensured that the table names (keys) in the returned insert - * data are exaclty the same as the table names (keys) in the delete - * data, even if one of them maps to an empty array (no changes). If - * a table needs neither insertions nor deletions, then it will not - * be mentioned as a key anywhere. - * - * The given database is only needed for reading the data that is - * currently stored about $sid. - * - * @since 1.8 - * @param integer $sid - * @param SMWSemanticData $data - * @return array( array, array, array ) - */ - protected function preparePropertyTableUpdates( $sid, SMWSemanticData $data ) { - $tablesDeleteRows = array(); - $tablesInsertRows = array(); - - $oldHashes = $this->store->getObjectIds()->getPropertyTableHashes( $sid ); - $newHashes = array(); - - $newData = $this->preparePropertyTableInserts( $sid, $data ); - $propertyTables = $this->store->getPropertyTables(); - - foreach ( $propertyTables as $propertyTable ) { - if ( !$propertyTable->usesIdSubject() ) { // ignore; only affects redirects anyway - continue; - } - - $tableName = $propertyTable->getName(); - - if ( array_key_exists( $tableName, $newData ) ) { - // Note: the order within arrays should remain the same while page is not updated. - // Hence we do not sort before serializing. It is hoped that this assumption is valid. - $newHash = md5( serialize( array_values( $newData[$tableName] ) ) ); - $newHashes[$tableName] = $newHash; - - if ( array_key_exists( $tableName, $oldHashes ) && $newHash == $oldHashes[$tableName] ) { - // Table contains data and should contain the same data after update - continue; - } else { // Table contains no data or contains data that is different from the new - $oldTableData = $this->getCurrentPropertyTableContents( $sid, $propertyTable ); - - list( $tablesInsertRows[$tableName], $tablesDeleteRows[$tableName]) = $this->arrayDeleteMatchingValues( $oldTableData, $newData[$tableName] ); - } - } elseif ( array_key_exists( $tableName, $oldHashes ) ) { - // Table contains data but should not contain any after update - $tablesInsertRows[$tableName] = array(); - $tablesDeleteRows[$tableName] = $this->getCurrentPropertyTableContents( $sid, $propertyTable ); - } - } - - return array( $tablesInsertRows, $tablesDeleteRows, $newHashes ); - } - - /** - * Get the current data stored for the given ID in the given database - * table. The result is an array of updates, formatted like the one of - * the table insertion arrays created by preparePropertyTableInserts(). - * - * @note Tables without IDs as subject are not supported. They will - * hopefully vanish soon anyway. - * - * @since 1.8 - * @param integer $sid - * @param SMWSQLStore3Table $tableDeclaration - * @return array - */ - protected function getCurrentPropertyTableContents( $sid, SMWSQLStore3Table $propertyTable ) { - - if ( !$propertyTable->usesIdSubject() ) { // does not occur, but let's be strict - throw new InvalidArgumentException('Operation not supported for tables without subject IDs.'); - } - - $contents = array(); - $db = $this->store->getDatabase(); - - $result = $db->select( - $propertyTable->getName(), - '*', - array( 's_id' => $sid ), - __METHOD__ - ); - - foreach( $result as $row ) { - if ( is_object( $row ) ) { - $contents[] = (array)$row; - } - } - - return $contents; - } - - /** - * Update all property tables and any dependent data (hashes, - * statistics, etc.) by inserting/deleting the given values. The ID of - * the page that is updated, and the hashes of the properties must be - * given explicitly (the hashes could not be computed from the insert - * and delete data alone anyway). - * - * It is assumed and required that the tables mentioned in - * $tablesInsertRows and $tablesDeleteRows are the same, and that all - * $rows in these datasets refer to the same subject ID. - * - * @since 1.8 - * - * @param integer $sid - * @param array $tablesInsertRows array mapping table names to arrays of rows - * @param array $tablesDeleteRows array mapping table names to arrays of rows - * @param array $newHashes - */ - protected function writePropertyTableUpdates( $sid, array $tablesInsertRows, array $tablesDeleteRows, array $newHashes ) { - $propertyUseIncrements = array(); - - $propertyTables = $this->store->getPropertyTables(); - - foreach ( $tablesInsertRows as $tableName => $insertRows ) { - // Note: by construction, the inserts and deletes have the same table keys. - // Note: by construction, the inserts and deletes are currently disjoint; - // yet we delete first to make the method more robust/versatile. - $this->writePropertyTableRowUpdates( $propertyUseIncrements, $propertyTables[$tableName], $tablesDeleteRows[$tableName], false ); - $this->writePropertyTableRowUpdates( $propertyUseIncrements, $propertyTables[$tableName], $insertRows, true ); - } - - if ( !empty( $tablesInsertRows ) || !empty( $tablesDeleteRows ) ) { - $this->store->smwIds->setPropertyTableHashes( $sid, $newHashes ); - } - - $statsTable = new PropertyStatisticsTable( - $this->store->getDatabase(), - SMWSQLStore3::PROPERTY_STATISTICS_TABLE - ); - - $statsTable->addToUsageCounts( $propertyUseIncrements ); - } - - /** - * Update one property table by inserting or deleting rows, and compute - * the changes that this entails for the property usage counts. The - * given rows are inserted into the table if $insert is true; otherwise - * they are deleted. The property usage counts are recorded in the - * call-by-ref parameter $propertyUseIncrements. - * - * The method assumes that all of the given rows are about the same - * subject. This is ensured by callers. - * - * @since 1.8 - * @param array $propertyUseIncrements - * @param SMWSQLStore3Table $propertyTable - * @param array $rows array of rows to insert/delete - * @param boolean $insert - */ - protected function writePropertyTableRowUpdates( array &$propertyUseIncrements, SMWSQLStore3Table $propertyTable, array $rows, $insert ) { - if ( empty( $rows ) ) { - return; - } - - if ( !$propertyTable->usesIdSubject() ) { // does not occur, but let's be strict - throw new InvalidArgumentException('Operation not supported for tables without subject IDs.'); - } - - $db = $this->store->getDatabase(); - - if ( $insert ) { - $db->insert( - $propertyTable->getName(), - $rows, - "SMW::writePropertyTableRowUpdates-insert-{$propertyTable->getName()}" - ); - } else { - $this->deleteRows( - $rows, - $propertyTable - ); - } - - if ( $propertyTable->isFixedPropertyTable() ) { - $property = new SMWDIProperty( $propertyTable->getFixedProperty() ); - $pid = $this->store->getObjectIds()->makeSMWPropertyID( $property ); - } - - foreach ( $rows as $row ) { - - if ( !$propertyTable->isFixedPropertyTable() ) { - $pid = $row['p_id']; - } - - if ( !array_key_exists( $pid, $propertyUseIncrements ) ) { - $propertyUseIncrements[$pid] = 0; - } - - $propertyUseIncrements[$pid] += ( $insert ? 1 : -1 ); - } - } - - protected function deleteRows( array $rows, SMWSQLStore3Table $propertyTable ) { - - $condition = ''; - $db = $this->store->getDatabase(); - - // We build a condition that mentions s_id only once, - // since it must be the same for all rows. This should - // help the DBMS in selecting the rows (it would not be - // easy for to detect that all tuples share one s_id). - $sid = false; - foreach ( $rows as $row ) { - if ( $sid === false ) { - if ( !array_key_exists( 's_id', (array)$row ) ) { - // FIXME: The assumption that s_id is present does not hold. - // This return is there to prevent fatal errors, but does not fix the issue of this code being broken - return; - } - - $sid = $row['s_id']; // 's_id' exists for all tables with $propertyTable->usesIdSubject() - } - unset( $row['s_id'] ); - if ( $condition != '' ) { - $condition .= ' OR '; - } - $condition .= '(' . $db->makeList( $row, LIST_AND ) . ')'; - } - - $condition = "s_id=" . $db->addQuotes( $sid ) . " AND ($condition)"; - - $db->delete( - $propertyTable->getName(), - array( $condition ), - "SMW::writePropertyTableRowUpdates-delete-{$propertyTable->getName()}" - ); - } - - /** - * Set the semantic data cache to hold exactly the given value for the - * given ID. - * - * @since 1.8 - * @param integer $sid - * @param SMWSemanticData $semanticData - */ - protected function setSemanticDataCache( $sid, SMWSemanticData $semanticData ) { - $this->store->m_semdata[$sid] = SMWSql3StubSemanticData::newFromSemanticData( $semanticData, $this->store ); - // This is everything one can know: - $this->store->m_sdstate[$sid] = array(); - $propertyTables = $this->store->getPropertyTables(); - - foreach ( $propertyTables as $tableId => $tableDeclaration ) { - $this->store->m_sdstate[$sid][$tableId] = true; - } - } - - /** - * Implementation of SMWStore::changeTitle(). In contrast to - * updateRedirects(), this function does not simply write a redirect - * from the old page to the new one, but also deletes all data that may - * already be stored for the new title (normally the new title should - * belong to an empty page that has no data but at least it could have a - * redirect to the old page), and moves all data that exists for the old - * title to the new location. Thus, the function executes three steps: - * delete data at newtitle, move data from oldtitle to newtitle, and set - * redirect from oldtitle to newtitle. In some cases, the goal can be - * achieved more efficiently, e.g. if the new title does not occur in SMW - * yet: then we can just change the ID records for the titles instead of - * changing all data tables - * - * Note that the implementation ignores the MediaWiki IDs since this - * store has its own ID management. Also, the function requires that both - * titles are local, i.e. have empty interwiki prefix. - * - * @todo Currently the sortkey is not moved with the remaining data. It is - * not possible to move it reliably in all cases: we cannot distinguish an - * unset sortkey from one that was set to the name of oldtitle. Maybe use - * update jobs right away? - * - * @since 1.8 - * @param Title $oldtitle - * @param Title $newtitle - * @param integer $pageid - * @param integer $redirid - */ - public function changeTitle( Title $oldtitle, Title $newtitle, $pageid, $redirid = 0 ) { - global $smwgQEqualitySupport; - wfProfileIn( "SMWSQLStore3::changeTitle (SMW)" ); - - $db = $this->store->getDatabase(); - - // get IDs but do not resolve redirects: - $sid = $this->store->getObjectIds()->getSMWPageID( - $oldtitle->getDBkey(), - $oldtitle->getNamespace(), - '', - '', - false - ); - - $tid = $this->store->getObjectIds()->getSMWPageID( - $newtitle->getDBkey(), - $newtitle->getNamespace(), - '', - '', - false - ); - - // Easy case: target not used anywhere yet, just hijack its title for our current id - if ( ( $tid == 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { - // This condition may not hold even if $newtitle is - // currently unused/non-existing since we keep old IDs. - // If equality support is off, then this simple move - // does too much; fall back to general case below. - if ( $sid != 0 ) { // change id entry to refer to the new title - // Note that this also changes the reference for internal objects (subobjects) - $db->update( - SMWSql3SmwIds::tableName, - array( - 'smw_title' => $newtitle->getDBkey(), - 'smw_namespace' => $newtitle->getNamespace(), - 'smw_iw' => '' - ), - array( - 'smw_title' => $oldtitle->getDBkey(), - 'smw_namespace' => $oldtitle->getNamespace(), - 'smw_iw' => '' - ), - __METHOD__ - ); - - $this->store->getObjectIds()->moveSubobjects( - $oldtitle->getDBkey(), - $oldtitle->getNamespace(), - $newtitle->getDBkey(), - $newtitle->getNamespace() - ); - - $this->store->getObjectIds()->setCache( - $oldtitle->getDBkey(), - $oldtitle->getNamespace(), - '', - '', - 0, - '' - ); - - // We do not know the new sortkey, so just clear the cache: - $this->store->getObjectIds()->deleteCache( - $newtitle->getDBkey(), - $newtitle->getNamespace(), - '', - '' - ); - - } else { // make new (target) id for use in redirect table - $sid = $this->store->getObjectIds()->makeSMWPageID( - $newtitle->getDBkey(), - $newtitle->getNamespace(), - '', - '' - ); - } // at this point, $sid is the id of the target page (according to the IDs table) - - // make redirect id for oldtitle: - $this->store->getObjectIds()->makeSMWPageID( - $oldtitle->getDBkey(), - $oldtitle->getNamespace(), - SMW_SQL3_SMWREDIIW, - '' - ); - - $db->insert( 'smw_fpt_redi', - array( - 's_title' => $oldtitle->getDBkey(), - 's_namespace' => $oldtitle->getNamespace(), - 'o_id' => $sid - ), - __METHOD__ - ); - - $statsTable = new PropertyStatisticsTable( - $db, - SMWSQLStore3::PROPERTY_STATISTICS_TABLE - ); - - $statsTable->addToUsageCount( - $this->store->getObjectIds()->getSMWPropertyID( new SMWDIProperty( '_REDI' ) ), - 1 - ); - - /// NOTE: there is the (bad) case that the moved page is a redirect. As chains of - /// redirects are not supported by MW or SMW, the above is maximally correct in this case too. - /// NOTE: this temporarily leaves existing redirects to oldtitle point to newtitle as well, which - /// will be lost after the next update. Since double redirects are an error anyway, this is not - /// a bad behavior: everything will continue to work until the existing redirects are updated, - /// which will hopefully be done to fix the double redirect. - } else { // General move method: should always be correct - // (equality support respected when updating redirects) - - // Delete any existing data (including redirects) from new title - // ($newtitle should not have data, but let's be sure) - $emptyNewSemanticData = new SMWSemanticData( SMWDIWikiPage::newFromTitle( $newtitle ) ); - $this->doDataUpdate( $emptyNewSemanticData ); - - // Move all data of old title to new position: - if ( $sid != 0 ) { - $this->store->changeSMWPageID( - $sid, - $tid, - $oldtitle->getNamespace(), - $newtitle->getNamespace(), - true, - false - ); - } - - // Associate internal objects (subobjects) with the new title: - $table = $db->tableName( SMWSql3SmwIds::tableName ); - - $values = array( - 'smw_title' => $newtitle->getDBkey(), - 'smw_namespace' => $newtitle->getNamespace(), - 'smw_iw' => '' - ); - - $sql = "UPDATE $table SET " . $db->makeList( $values, LIST_SET ) . - ' WHERE smw_title = ' . $db->addQuotes( $oldtitle->getDBkey() ) . ' AND ' . - 'smw_namespace = ' . $db->addQuotes( $oldtitle->getNamespace() ) . ' AND ' . - 'smw_iw = ' . $db->addQuotes( '' ) . ' AND ' . - 'smw_subobject != ' . $db->addQuotes( '' ); // The "!=" is why we cannot use MW array syntax here - - $db->query( $sql, __METHOD__ ); - - $this->store->getObjectIds()->moveSubobjects( - $oldtitle->getDBkey(), - $oldtitle->getNamespace(), - $newtitle->getDBkey(), - $newtitle->getNamespace() - ); - - // $redirid == 0 means that the oldTitle was not supposed to be a redirect - // (oldTitle is delete from the db) but instead of deleting all - // references we will still copy data from old to new during updateRedirects() - // and clear the semantic data container for the oldTitle instance - // to ensure that no ghost references exists for an deleted oldTitle - // @see Title::moveTo(), createRedirect - if ( $redirid == 0 ) { - - // Delete any existing data (including redirects) from old title - $this->updateRedirects( - $oldtitle->getDBkey(), - $oldtitle->getNamespace() - ); - - } else { - - // Write a redirect from old title to new one: - // (this also updates references in other tables as needed.) - // TODO: may not be optimal for the standard case that newtitle - // existed and redirected to oldtitle (PERFORMANCE) - $this->updateRedirects( - $oldtitle->getDBkey(), - $oldtitle->getNamespace(), - $newtitle->getDBkey(), - $newtitle->getNamespace() - ); - - } - - } - - wfProfileOut( "SMWSQLStore3::changeTitle (SMW)" ); - } - - /** - * Helper method to write information about some redirect. Various updates - * can be necessary if redirects are resolved as identities in SMW. The - * title and namespace of the affected page and of its updated redirect - * target are given. The target can be empty ('') to delete any redirect. - * Returns the canonical ID that is now to be used for the subject. - * - * This method does not change the ids of the affected pages, and thus it - * is not concerned with updates of the data that is currently stored for - * the subject. Normally, a subject that is a redirect will not have other - * data, but this method does not depend on this. - * - * @note Please make sure you fully understand this code before making any - * changes here. Keeping the redirect structure consistent is important, - * and errors in this code can go unnoticed for quite some time. - * - * @note This method merely handles the addition or deletion of a redirect - * statement in the wiki. It does not assume that any page contents has - * been changed (e.g. moved). See changeTitle() for additional handling in - * this case. - * - * @todo Clean up this code. - * - * @since 1.8 - * @param string $subject_t - * @param integer $subject_ns - * @param string $curtarget_t - * @param integer $curtarget_ns - * @return integer the new canonical ID of the subject - */ - protected function updateRedirects( $subject_t, $subject_ns, $curtarget_t = '', $curtarget_ns = -1 ) { - global $smwgQEqualitySupport, $smwgEnableUpdateJobs; - - $count = 0; //track count changes for redi property - $db = $this->store->getDatabase(); - - // *** First get id of subject, old redirect target, and current (new) redirect target ***// - - $sid_sort = ''; - - // find real id of subject, if any - $sid = $this->store->getObjectIds()->getSMWPageIDandSort( - $subject_t, - $subject_ns, - '', - '', - $sid_sort, - false - ); - - /// NOTE: $sid can be 0 here; this is useful to know since it means that fewer table updates are needed - $new_tid = $curtarget_t ? ( $this->store->getObjectIds()->makeSMWPageID( $curtarget_t, $curtarget_ns, '', '', false ) ) : 0; // real id of new target, if given - - $row = $db->selectRow( - array( 'smw_fpt_redi' ), - 'o_id', - array( 's_title' => $subject_t, 's_namespace' => $subject_ns ), - __METHOD__ - ); - - $old_tid = ( $row !== false ) ? $row->o_id : 0; // real id of old target, if any - /// NOTE: $old_tid and $new_tid both (intentionally) ignore further redirects: no redirect chains - - if ( $old_tid == $new_tid ) { // no change, all happy - return ( $new_tid == 0 ) ? $sid : $new_tid; - } // note that this means $old_tid != $new_tid in all cases below - - // *** Make relevant changes in property tables (don't write the new redirect yet) ***// - $jobs = array(); - - if ( ( $old_tid == 0 ) && ( $sid != 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { // new redirect - // $smwgQEqualitySupport requires us to change all tables' page references from $sid to $new_tid. - // Since references must not be 0, we don't have to do this is $sid == 0. - $this->store->changeSMWPageID( - $sid, - $new_tid, - $subject_ns, - $curtarget_ns, - false, - true - ); - - $jobs = $this->makeUpdateJobsForNewRedirect( - $subject_t, - $subject_ns, - $curtarget_t, - $curtarget_ns - ); - - } elseif ( $old_tid != 0 ) { // existing redirect is changed or deleted - $db->delete( - 'smw_fpt_redi', - array( 's_title' => $subject_t, 's_namespace' => $subject_ns ), - __METHOD__ - ); - - $count--; - - if ( $smwgEnableUpdateJobs && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { - // entries that refer to old target may in fact refer to subject, - // but we don't know which: schedule affected pages for update - $propertyTables = $this->store->getPropertyTables(); - - foreach ( $propertyTables as $proptable ) { - if ( $proptable->getName() == 'smw_fpt_redi' ) { - continue; // can safely be skipped - } - - if ( $proptable->usesIdSubject() ) { - $from = $db->tableName( $proptable->getName() ) . ' INNER JOIN ' . - $db->tableName( SMWSql3SmwIds::tableName ) . ' ON s_id=smw_id'; - $select = 'DISTINCT smw_title AS t,smw_namespace AS ns'; - } else { - $from = $db->tableName( $proptable->getName() ); - $select = 'DISTINCT s_title AS t,s_namespace AS ns'; - } - - if ( $subject_ns === SMW_NS_PROPERTY && !$proptable->isFixedPropertyTable() ) { - - $res = $db->select( - $from, - $select, - array( 'p_id' => $old_tid ), - __METHOD__ - ); - - foreach ( $res as $row ) { - $title = Title::makeTitleSafe( $row->ns, $row->t ); - if ( !is_null( $title ) ) { - $jobs[] = new UpdateJob( $title ); - } - } - - $db->freeResult( $res ); - } - - foreach ( $proptable->getFields( $this->store ) as $fieldname => $type ) { - if ( $type == 'p' ) { - - $res = $db->select( - $from, - $select, - array( $fieldname => $old_tid ), - __METHOD__ - ); - - foreach ( $res as $row ) { - $title = Title::makeTitleSafe( $row->ns, $row->t ); - if ( !is_null( $title ) ) { - $jobs[] = new UpdateJob( $title ); - } - } - - $db->freeResult( $res ); - } - } - } - - /// NOTE: we do not update the concept cache here; this remains an offline task - - } - } - - /// NOTE: this only happens if $smwgEnableUpdateJobs is true - if ( $smwgEnableUpdateJobs ) { - Job::batchInsert( $jobs ); - } - - // *** Finally, write the new redirect data ***// - - if ( $new_tid != 0 ) { // record a new redirect - // Redirecting done right: - // (1) make a new ID with iw SMW_SQL3_SMWREDIIW or - // change iw field of current ID in this way, - // (2) write smw_fpt_redi table, - // (3) update canonical cache. - // This order must be obeyed unless you really understand what you are doing! - - if ( ( $old_tid == 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { - // mark subject as redirect (if it was no redirect before) - if ( $sid == 0 ) { // every redirect page must have an ID - $sid = $this->store->getObjectIds()->makeSMWPageID( - $subject_t, - $subject_ns, - SMW_SQL3_SMWREDIIW, - '', - false - ); - } else { - $db->update( - SMWSql3SmwIds::tableName, - array( 'smw_iw' => SMW_SQL3_SMWREDIIW ), - array( 'smw_id' => $sid ), - __METHOD__ - ); - - $this->store->getObjectIds()->setCache( - $subject_t, - $subject_ns, - '', - '', - 0, - '' - ); - - $this->store->getObjectIds()->setCache( - $subject_t, - $subject_ns, - SMW_SQL3_SMWREDIIW, - '', - $sid, - $sid_sort - ); - } - } - - $db->insert( - 'smw_fpt_redi', - array( - 's_title' => $subject_t, - 's_namespace' => $subject_ns, - 'o_id' => $new_tid ), - __METHOD__ - ); - - $count++; - - } else { // delete old redirect - // This case implies $old_tid != 0 (or we would have new_tid == old_tid above). - // Therefore $subject had a redirect, and it must also have an ID. - // This shows that $sid != 0 here. - if ( $smwgQEqualitySupport != SMW_EQ_NONE ) { // mark subject as non-redirect - - $db->update( - SMWSql3SmwIds::tableName, - array( 'smw_iw' => '' ), - array( 'smw_id' => $sid ), - __METHOD__ - ); - - $this->store->getObjectIds()->setCache( - $subject_t, - $subject_ns, - SMW_SQL3_SMWREDIIW, - '', - 0, - '' - ); - - $this->store->getObjectIds()->setCache( - $subject_t, - $subject_ns, - '', - '', - $sid, - $sid_sort - ); - } - } - - // *** Flush some caches to be safe, though they are not essential in runs with redirect updates ***// - unset( $this->store->m_semdata[$sid] ); - unset( $this->store->m_semdata[$new_tid] ); - unset( $this->store->m_semdata[$old_tid] ); - - unset( $this->store->m_sdstate[$sid] ); - unset( $this->store->m_sdstate[$new_tid] ); - unset( $this->store->m_sdstate[$old_tid] ); - - // *** Update reference count for _REDI property ***// - $statsTable = new PropertyStatisticsTable( - $db, - SMWSQLStore3::PROPERTY_STATISTICS_TABLE - ); - - $statsTable->addToUsageCount( - $this->store->getObjectIds()->getSMWPropertyID( new SMWDIProperty( '_REDI' ) ), - $count - ); - - return ( $new_tid == 0 ) ? $sid : $new_tid; - } - - private function makeUpdateJobsForNewRedirect( $subjectDBKey, $subjectNS, $targetDBKey, $targetNS ) { - - $jobs = array(); - - $title = Title::makeTitleSafe( $subjectNS, $subjectDBKey ); - $jobs[] = new UpdateJob( $title ); - - if ( $targetDBKey !== '' && $targetNS !== -1 ) { - $title = Title::makeTitleSafe( $targetNS, $targetDBKey ); - $jobs[] = new UpdateJob( $title ); - } - - return $jobs; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_Sql3SmwIds.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_Sql3SmwIds.php deleted file mode 100644 index 99765851..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_Sql3SmwIds.php +++ /dev/null @@ -1,1019 +0,0 @@ -<?php - -use SMW\SQLStore\PropertyStatisticsTable; - -/** - * @file - * @ingroup SMWStore - * @since 1.8 - * @author Markus Krötzsch - */ - -/** - * Class to access the SMW IDs table in SQLStore3. - * Provides transparent in-memory caching facilities. - * - * Documentation for the SMW IDs table: This table is a dictionary that - * assigns integer IDs to pages, properties, and other objects used by SMW. - * All tables that refer to such objects store these IDs instead. If the ID - * information is lost (e.g., table gets deleted), then the data stored in SMW - * is no longer meaningful: all tables need to be dropped, recreated, and - * refreshed to get back to a working database. - * - * The table has a column for storing interwiki prefixes, used to refer to - * pages on external sites (like in MediaWiki). This column is also used to - * mark some special objects in the table, using "interwiki prefixes" that - * cannot occur in MediaWiki: - * - * - Rows with iw SMW_SQL3_SMWREDIIW are similar to normal entries for - * (internal) wiki pages, but the iw indicates that the page is a redirect, the - * (target of which should be sought using the smw_fpt_redi table. - * - * - The (unique) row with iw SMW_SQL3_SMWBORDERIW just marks the border - * between predefined ids (rows that are reserved for hardcoded ids built into - * SMW) and normal entries. It is no object, but makes sure that SQL's auto - * increment counter is high enough to not add any objects before that marked - * "border". - * - * @note Do not call the constructor of SMWDIWikiPage using data from the SMW - * IDs table; use SMWDIHandlerWikiPage::dataItemFromDBKeys() instead. The table - * does not always contain data as required wiki pages. Especially predefined - * properties are represented by language-independent keys rather than proper - * titles. SMWDIHandlerWikiPage takes care of this. - * - * @since 1.8 - * - * @ingroup SMWStore - */ -class SMWSql3SmwIds { - - /** - * Name of the table to store IDs in. - * - * @note This should never change. Existing wikis will have to drop and - * rebuild their SMW tables completely to recover from any change here. - */ - const tableName = 'smw_object_ids'; - - /** - * Id for which property table hashes are cached, if any. - * - * @since 1.8 - * @var integer - */ - protected $hashCacheId = 0; - - /** - * Cached property table hashes for $hashCacheId. - * - * @since 1.8 - * @var string - */ - protected $hashCacheContents = ''; - - /** - * Maximal number of cached property IDs. - * - * @since 1.8 - * @var integer - */ - public static $PROP_CACHE_MAX_SIZE = 250; - - /** - * Maximal number of cached non-property IDs. - * - * @since 1.8 - * @var integer - */ - public static $PAGE_CACHE_MAX_SIZE = 500; - - protected $selectrow_sort_debug = 0; - protected $selectrow_redi_debug = 0; - protected $prophit_debug = 0; - protected $propmiss_debug = 0; - protected $reghit_debug = 0; - protected $regmiss_debug = 0; - static protected $singleton_debug = null; - - /** - * Parent SMWSQLStore3. - * - * @since 1.8 - * @var SMWSQLStore3 - */ - public $store; - - /** - * Cache for property IDs. - * - * @note Tests indicate that it is more memory efficient to have two - * arrays (IDs and sortkeys) than to have one array that stores both - * values in some data structure (other than a single string). - * - * @since 1.8 - * @var array - */ - protected $prop_ids = array(); - - /** - * Cache for property sortkeys. - * - * @since 1.8 - * @var array - */ - protected $prop_sortkeys = array(); - - /** - * Cache for non-property IDs. - * - * @since 1.8 - * @var array - */ - protected $regular_ids = array(); - - /** - * Cache for non-property sortkeys. - * - * @since 1.8 - * @var array - */ - protected $regular_sortkeys = array(); - - /** - * Use pre-defined ids for Very Important Properties, avoiding frequent - * ID lookups for those. - * - * @note These constants also occur in the store. Changing them will - * require to run setup.php again. They can also not be larger than 50. - * - * @since 1.8 - * @var array - */ - public static $special_ids = array( - '_TYPE' => 1, - '_URI' => 2, - '_INST' => 4, - '_UNIT' => 7, - '_IMPO' => 8, - '_CONV' => 12, - '_SERV' => 13, - '_PVAL' => 14, - '_REDI' => 15, - '_SUBP' => 17, - '_SUBC' => 18, - '_CONC' => 19, - '_SF_DF' => 20, // Semantic Form's default form property - '_SF_AF' => 21, // Semantic Form's alternate form property - '_ERRP' => 22, -// '_1' => 23, // properties for encoding (short) lists -// '_2' => 24, -// '_3' => 25, -// '_4' => 26, -// '_5' => 27, - '_LIST' => 28, - '_MDAT' => 29, - '_CDAT' => 30, - '_NEWP' => 31, - '_LEDT' => 32, - // properties related to query management - '_ASK' => 33, - '_ASKST' => 34, - '_ASKFO' => 35, - '_ASKSI' => 36, - '_ASKDE' => 37, - ); - - /** - * Constructor. - * - * @since 1.8 - * @param SMWSQLStore3 $store - */ - public function __construct( SMWSQLStore3 $store ) { - $this->store = $store; - // Yes, this is a hack, but we only use it for convenient debugging: - self::$singleton_debug = $this; - } - - /** - * Find the numeric ID used for the page of the given title, - * namespace, interwiki, and subobject. If $canonical is set to true, - * redirects are taken into account to find the canonical alias ID for - * the given page. If no such ID exists, 0 is returned. The Call-By-Ref - * parameter $sortkey is set to the current sortkey, or to '' if no ID - * exists. - * - * If $fetchhashes is true, the property table hash blob will be - * retrieved in passing if the opportunity arises, and cached - * internally. This will speed up a subsequent call to - * getPropertyTableHashes() for this id. This should only be done - * if such a call is intended, both to safe the previous cache and - * to avoid extra work (even if only a little) to fill it. - * - * @since 1.8 - * @param string $title DB key - * @param integer $namespace namespace - * @param string $iw interwiki prefix - * @param string $subobjectName name of subobject - * @param string $sortkey call-by-ref will be set to sortkey - * @param boolean $canonical should redirects be resolved? - * @param boolean $fetchHashes should the property hashes be obtained and cached? - * @return integer SMW id or 0 if there is none - */ - public function getSMWPageIDandSort( $title, $namespace, $iw, $subobjectName, &$sortkey, $canonical, $fetchHashes = false ) { - $id = $this->getPredefinedData( $title, $namespace, $iw, $subobjectName, $sortkey ); - if ( $id != 0 ) { - return $id; - } else { - return $this->getDatabaseIdAndSort( $title, $namespace, $iw, $subobjectName, $sortkey, $canonical, $fetchHashes ); - } - } - - /** - * Find the numeric ID used for the page of the given normalized title, - * namespace, interwiki, and subobjectName. Predefined IDs are not - * taken into account (however, they would still be found correctly by - * an avoidable database read if they are stored correctly in the - * database; this should always be the case). In all other aspects, the - * method works just like getSMWPageIDandSort(). - * - * @since 1.8 - * @param string $title DB key - * @param integer $namespace namespace - * @param string $iw interwiki prefix - * @param string $subobjectName name of subobject - * @param string $sortkey call-by-ref will be set to sortkey - * @param boolean $canonical should redirects be resolved? - * @param boolean $fetchHashes should the property hashes be obtained and cached? - * @return integer SMW id or 0 if there is none - */ - protected function getDatabaseIdAndSort( $title, $namespace, $iw, $subobjectName, &$sortkey, $canonical, $fetchHashes ) { - global $smwgQEqualitySupport; - - $db = $this->store->getDatabase(); - - $id = $this->getCachedId( - $title, - $namespace, - $iw, - $subobjectName - ); - - if ( $id !== false ) { // cache hit - $sortkey = $this->getCachedSortKey( $title, $namespace, $iw, $subobjectName ); - } elseif ( $iw == SMW_SQL3_SMWREDIIW && $canonical && - $smwgQEqualitySupport != SMW_EQ_NONE && $subobjectName === '' ) { - $id = $this->getRedirectId( $title, $namespace ); - if ( $id != 0 ) { - - if ( $fetchHashes ) { - $select = array( 'smw_sortkey', 'smw_proptable_hash' ); - } else { - $select = array( 'smw_sortkey' ); - } - - $row = $db->selectRow( - self::tableName, - $select, - array( 'smw_id' => $id ), - __METHOD__ - ); - - if ( $row !== false ) { - $sortkey = $row->smw_sortkey; - if ( $fetchHashes ) { - $this->setPropertyTableHashesCache( $id, $row->smw_proptable_hash ); - } - } else { // inconsistent DB; just recover somehow - $sortkey = str_replace( '_', ' ', $title ); - } - } else { - $sortkey = ''; - } - $this->setCache( $title, $namespace, $iw, $subobjectName, $id, $sortkey ); - } else { - - if ( $fetchHashes ) { - $select = array( 'smw_id', 'smw_sortkey', 'smw_proptable_hash' ); - } else { - $select = array( 'smw_id', 'smw_sortkey' ); - } - - $row = $db->selectRow( - self::tableName, - $select, - array( - 'smw_title' => $title, - 'smw_namespace' => $namespace, - 'smw_iw' => $iw, - 'smw_subobject' => $subobjectName - ), - __METHOD__ - ); - - $this->selectrow_sort_debug++; - - if ( $row !== false ) { - $id = $row->smw_id; - $sortkey = $row->smw_sortkey; - if ( $fetchHashes ) { - $this->setPropertyTableHashesCache( $id, $row->smw_proptable_hash); - } - } else { - $id = 0; - $sortkey = ''; - } - - $this->setCache( - $title, - $namespace, - $iw, - $subobjectName, - $id, - $sortkey - ); - } - - if ( $id == 0 && $subobjectName === '' && $iw === '' ) { // could be a redirect; check - $id = $this->getSMWPageIDandSort( - $title, - $namespace, - SMW_SQL3_SMWREDIIW, - $subobjectName, - $sortkey, - $canonical, - $fetchHashes - ); - } - - return $id; - } - - /** - * Convenience method for calling getSMWPageIDandSort without - * specifying a sortkey (if not asked for). - * - * @since 1.8 - * @param string $title DB key - * @param integer $namespace namespace - * @param string $iw interwiki prefix - * @param string $subobjectName name of subobject - * @param boolean $canonical should redirects be resolved? - * @param boolean $fetchHashes should the property hashes be obtained and cached? - * @return integer SMW id or 0 if there is none - */ - public function getSMWPageID( $title, $namespace, $iw, $subobjectName, $canonical = true, $fetchHashes = false ) { - $sort = ''; - return $this->getSMWPageIDandSort( $title, $namespace, $iw, $subobjectName, $sort, $canonical, $fetchHashes ); - } - - /** - * Return the ID that a page redirects to. This is only used internally - * and it is not cached since the results will affect the SMW IDs table - * cache, which will prevent duplicate queries for the same redirect - * anyway. - * - * @since 1.8 - * @param string $title DB key - * @param integer $namespace - * @return integer - */ - protected function getRedirectId( $title, $namespace ) { - $row = $this->store->getDatabase()->selectRow( - 'smw_fpt_redi', - 'o_id', - array( - 's_title' => $title, - 's_namespace' => $namespace - ), - __METHOD__ - ); - - $this->selectrow_redi_debug++; - return ( $row === false ) ? 0 : $row->o_id; - } - - /** - * Find the numeric ID used for the page of the given title, namespace, - * interwiki, and subobjectName. If $canonical is set to true, - * redirects are taken into account to find the canonical alias ID for - * the given page. If no such ID exists, a new ID is created and - * returned. In any case, the current sortkey is set to the given one - * unless $sortkey is empty. - * - * @note Using this with $canonical==false can make sense, especially when - * the title is a redirect target (we do not want chains of redirects). - * But it is of no relevance if the title does not have an id yet. - * - * @since 1.8 - * @param string $title DB key - * @param integer $namespace namespace - * @param string $iw interwiki prefix - * @param string $subobjectName name of subobject - * @param boolean $canonical should redirects be resolved? - * @param string $sortkey call-by-ref will be set to sortkey - * @param boolean $fetchHashes should the property hashes be obtained and cached? - * @return integer SMW id or 0 if there is none - */ - public function makeSMWPageID( $title, $namespace, $iw, $subobjectName, $canonical = true, $sortkey = '', $fetchHashes = false ) { - $id = $this->getPredefinedData( $title, $namespace, $iw, $subobjectName, $sortkey ); - if ( $id != 0 ) { - return $id; - } else { - return $this->makeDatabaseId( $title, $namespace, $iw, $subobjectName, $canonical, $sortkey, $fetchHashes ); - } - } - - /** - * Find the numeric ID used for the page of the given normalized title, - * namespace, interwiki, and subobjectName. Predefined IDs are not - * taken into account (however, they would still be found correctly by - * an avoidable database read if they are stored correctly in the - * database; this should always be the case). In all other aspects, the - * method works just like makeSMWPageID(). Especially, if no ID exists, - * a new ID is created and returned. - * - * @since 1.8 - * @param string $title DB key - * @param integer $namespace namespace - * @param string $iw interwiki prefix - * @param string $subobjectName name of subobject - * @param boolean $canonical should redirects be resolved? - * @param string $sortkey call-by-ref will be set to sortkey - * @param boolean $fetchHashes should the property hashes be obtained and cached? - * @return integer SMW id or 0 if there is none - */ - protected function makeDatabaseId( $title, $namespace, $iw, $subobjectName, $canonical, $sortkey, $fetchHashes ) { - - $oldsort = ''; - $id = $this->getDatabaseIdAndSort( $title, $namespace, $iw, $subobjectName, $oldsort, $canonical, $fetchHashes ); - $db = $this->store->getDatabase(); - - if ( $id == 0 ) { - $sortkey = $sortkey ? $sortkey : ( str_replace( '_', ' ', $title ) ); - $sequenceValue = $db->nextSequenceValue( $this->getIdTable() . '_smw_id_seq' ); // Bug 42659 - - $db->insert( - self::tableName, - array( - 'smw_id' => $sequenceValue, - 'smw_title' => $title, - 'smw_namespace' => $namespace, - 'smw_iw' => $iw, - 'smw_subobject' => $subobjectName, - 'smw_sortkey' => $sortkey - ), - __METHOD__ - ); - - $id = $db->insertId(); - - // Properties also need to be in the property statistics table - if( $namespace === SMW_NS_PROPERTY ) { - - $statsStore = new PropertyStatisticsTable( - $db, - SMWSQLStore3::PROPERTY_STATISTICS_TABLE - ); - - $statsStore->insertUsageCount( $id, 0 ); - } - - $this->setCache( $title, $namespace, $iw, $subobjectName, $id, $sortkey ); - - if ( $fetchHashes ) { - $this->setPropertyTableHashesCache( $id, null ); - } - - } elseif ( $sortkey !== '' && $sortkey != $oldsort ) { - $db->update( - self::tableName, - array( 'smw_sortkey' => $sortkey ), - array( 'smw_id' => $id ), - __METHOD__ - ); - - $this->setCache( $title, $namespace, $iw, $subobjectName, $id, $sortkey ); - } - - return $id; - } - - /** - * Properties have a mechanisms for being predefined (i.e. in PHP instead - * of in wiki). Special "interwiki" prefixes separate the ids of such - * predefined properties from the ids for the current pages (which may, - * e.g., be moved, while the predefined object is not movable). - * - * @todo This documentation is out of date. Right now, the special - * interwiki is used only for special properties without a label, i.e., - * which cannot be shown to a user. This allows us to filter such cases - * from all queries that retrieve lists of properties. It should be - * checked that this is really the only use that this has throughout - * the code. - * - * @since 1.8 - * @param SMWDIProperty $property - * @return string - */ - public function getPropertyInterwiki( SMWDIProperty $property ) { - return ( $property->getLabel() !== '' ) ? '' : SMW_SQL3_SMWINTDEFIW; - } - - /** - * Fetch the ID for an SMWDIProperty object. This method achieves the - * same as getSMWPageID(), but avoids additional normalization steps - * that have already been performed when creating an SMWDIProperty - * object. - * - * @note There is no distinction between properties and inverse - * properties here. A property and its inverse have the same ID in SMW. - * - * @param SMWDIProperty $property - * @return integer - */ - public function getSMWPropertyID( SMWDIProperty $property ) { - if ( array_key_exists( $property->getKey(), self::$special_ids ) ) { - return self::$special_ids[$property->getKey()]; - } else { - $sortkey = ''; - return $this->getDatabaseIdAndSort( $property->getKey(), SMW_NS_PROPERTY, $this->getPropertyInterwiki( $property ), '', $sortkey, true, false ); - } - } - - /** - * Fetch and possibly create the ID for an SMWDIProperty object. The - * method achieves the same as getSMWPageID() but avoids additional - * normalization steps that have already been performed when creating - * an SMWDIProperty object. - * - * @see getSMWPropertyID - * @param SMWDIProperty $property - * @return integer - */ - public function makeSMWPropertyID( SMWDIProperty $property ) { - if ( array_key_exists( $property->getKey(), self::$special_ids ) ) { - return self::$special_ids[$property->getKey()]; - } else { - return $this->makeDatabaseId( - $property->getKey(), - SMW_NS_PROPERTY, - $this->getPropertyInterwiki( $property ), - '', - true, - $property->getLabel(), - false - ); - } - } - - /** - * Normalize the information for an SMW object (page etc.) and return - * the predefined ID if any. All parameters are call-by-reference and - * will be changed to perform any kind of built-in normalization that - * SMW requires. This mainly applies to predefined properties that - * should always use their property key as a title, have fixed - * sortkeys, etc. Some very special properties also have fixed IDs that - * do not require any DB lookups. In such cases, the method returns - * this ID; otherwise it returns 0. - * - * @note This function could be extended to account for further kinds - * of normalization and predefined ID. However, both getSMWPropertyID - * and makeSMWPropertyID must then also be adjusted to do the same. - * - * @since 1.8 - * @param string $title DB key - * @param integer $namespace namespace - * @param string $iw interwiki prefix - * @param string $subobjectName - * @param string $sortkey - * @return integer predefined id or 0 if none - */ - protected function getPredefinedData( &$title, &$namespace, &$iw, &$subobjectName, &$sortkey ) { - if ( $namespace == SMW_NS_PROPERTY && - ( $iw === '' || $iw == SMW_SQL3_SMWINTDEFIW ) && $title != '' ) { - - // Check if this is a predefined property: - if ( $title{0} != '_' ) { - // This normalization also applies to - // subobjects of predefined properties. - $newTitle = SMWDIProperty::findPropertyID( str_replace( '_', ' ', $title ) ); - if ( $newTitle ) { - $title = $newTitle; - $sortkey = SMWDIProperty::findPropertyLabel( $title ); - if ( $sortkey === '' ) { - $iw = SMW_SQL3_SMWINTDEFIW; - } - } - } - - // Check if this is a property with a fixed SMW ID: - if ( $subobjectName === '' && array_key_exists( $title, self::$special_ids ) ) { - return self::$special_ids[$title]; - } - } - - return 0; - } - - /** - * Change an internal id to another value. If no target value is given, the - * value is changed to become the last id entry (based on the automatic id - * increment of the database). Whatever currently occupies this id will be - * moved consistently in all relevant tables. Whatever currently occupies - * the target id will be ignored (it should be ensured that nothing is - * moved to an id that is still in use somewhere). - * - * @since 1.8 - * @param integer $curid - * @param integer $targetid - */ - public function moveSMWPageID( $curid, $targetid = 0 ) { - $db = $this->store->getDatabase(); - - $row = $db->selectRow( - self::tableName, - '*', - array( 'smw_id' => $curid ), - __METHOD__ - ); - - if ( $row === false ) return; // no id at current position, ignore - - if ( $targetid == 0 ) { // append new id - $sequenceValue = $db->nextSequenceValue( $this->getIdTable() . '_smw_id_seq' ); // Bug 42659 - - $db->insert( - self::tableName, - array( - 'smw_id' => $sequenceValue, - 'smw_title' => $row->smw_title, - 'smw_namespace' => $row->smw_namespace, - 'smw_iw' => $row->smw_iw, - 'smw_subobject' => $row->smw_subobject, - 'smw_sortkey' => $row->smw_sortkey - ), - __METHOD__ - ); - - $targetid = $db->insertId(); - } else { // change to given id - $db->insert( - self::tableName, - array( 'smw_id' => $targetid, - 'smw_title' => $row->smw_title, - 'smw_namespace' => $row->smw_namespace, - 'smw_iw' => $row->smw_iw, - 'smw_subobject' => $row->smw_subobject, - 'smw_sortkey' => $row->smw_sortkey - ), - __METHOD__ - ); - } - - $db->delete( - self::tableName, - array( - 'smw_id' => $curid - ), - __METHOD__ - ); - - $this->setCache( - $row->smw_title, - $row->smw_namespace, - $row->smw_iw, - $row->smw_subobject, - $targetid, - $row->smw_sortkey - ); - - $this->store->changeSMWPageID( - $curid, - $targetid, - $row->smw_namespace, - $row->smw_namespace - ); - - } - - /** - * Add or modify a cache entry. The key consists of the - * parameters $title, $namespace, $interwiki, and $subobject. The - * cached data is $id and $sortkey. - * - * @since 1.8 - * @param string $title - * @param integer $namespace - * @param string $interwiki - * @param string $subobject - * @param integer $id - * @param string $sortkey - */ - public function setCache( $title, $namespace, $interwiki, $subobject, $id, $sortkey ) { - if ( strpos( $title, ' ' ) !== false ) { - throw new MWException("Somebody tried to use spaces in a cache title! ($title)"); - } - if ( $namespace == SMW_NS_PROPERTY && $interwiki === '' && $subobject === '' ) { - $this->checkPropertySizeLimit(); - $this->prop_ids[$title] = $id; - $this->prop_sortkeys[$title] = $sortkey; - } else { - $hashKey = self::getRegularHashKey( $title, $namespace, $interwiki, $subobject ); - $this->checkRegularSizeLimit(); - $this->regular_ids[$hashKey] = $id; - $this->regular_sortkeys[$hashKey] = $sortkey; - } - if ( $interwiki == SMW_SQL3_SMWREDIIW ) { // speed up detection of redirects when fetching IDs - $this->setCache( $title, $namespace, '', $subobject, 0, '' ); - } - } - - /** - * Get a cached SMW ID, or false if no cache entry is found. - * - * @since 1.8 - * @param string $title - * @param integer $namespace - * @param string $interwiki - * @param string $subobject - * @return integer|boolean - */ - protected function getCachedId( $title, $namespace, $interwiki, $subobject ) { - if ( $namespace == SMW_NS_PROPERTY && $interwiki === '' && $subobject === '' ) { - if ( array_key_exists( $title, $this->prop_ids ) ) { - $this->prophit_debug++; - return $this->prop_ids[$title]; - } else { - $this->propmiss_debug++; - return false; - } - } else { - $hashKey = self::getRegularHashKey( $title, $namespace, $interwiki, $subobject ); - if ( array_key_exists( $hashKey, $this->regular_ids ) ) { - $this->reghit_debug++; - return $this->regular_ids[$hashKey]; - } else { - $this->regmiss_debug++; - return false; - } - } - } - - /** - * Get a cached SMW sortkey, or false if no cache entry is found. - * - * @since 1.8 - * @param string $title - * @param integer $namespace - * @param string $interwiki - * @param string $subobject - * @return string|boolean - */ - protected function getCachedSortKey( $title, $namespace, $interwiki, $subobject ) { - if ( $namespace == SMW_NS_PROPERTY && $interwiki === '' && $subobject === '' ) { - if ( array_key_exists( $title, $this->prop_sortkeys ) ) { - return $this->prop_sortkeys[$title]; - } else { - return false; - } - } else { - $hashKey = self::getRegularHashKey( $title, $namespace, $interwiki, $subobject ); - if ( array_key_exists( $hashKey, $this->regular_sortkeys ) ) { - return $this->regular_sortkeys[$hashKey]; - } else { - return false; - } - } - } - - /** - * Remove any cache entry for the given data. The key consists of the - * parameters $title, $namespace, $interwiki, and $subobject. The - * cached data is $id and $sortkey. - * - * @since 1.8 - * @param string $title - * @param integer $namespace - * @param string $interwiki - * @param string $subobject - */ - public function deleteCache( $title, $namespace, $interwiki, $subobject ) { - if ( $namespace == SMW_NS_PROPERTY && $interwiki === '' && $subobject === '' ) { - unset( $this->regular_ids[$title] ); - unset( $this->regular_sortkeys[$title] ); - } else { - $hashKey = self::getRegularHashKey( $title, $namespace, $interwiki, $subobject ); - unset( $this->regular_ids[$hashKey] ); - unset( $this->regular_sortkeys[$hashKey] ); - } - } - - /** - * Move all cached information about subobjects. - * - * @todo This method is neither efficient nor very convincing - * architecturally; it should be redesigned. - * - * @since 1.8 - * @param string $oldtitle - * @param integer $oldnamespace - * @param string $newtitle - * @param integer $newnamespace - */ - public function moveSubobjects( $oldtitle, $oldnamespace, $newtitle, $newnamespace ) { - // Currently we have no way to change title and namespace across all entries. - // Best we can do is clear the cache to avoid wrong hits: - if ( $oldnamespace == SMW_NS_PROPERTY || $newnamespace == SMW_NS_PROPERTY ) { - $this->prop_ids = array(); - $this->prop_sortkeys = array(); - } - if ( $oldnamespace != SMW_NS_PROPERTY || $newnamespace != SMW_NS_PROPERTY ) { - $this->regular_ids = array(); - $this->regular_sortkeys = array(); - } - } - - /** - * Delete all cached information. - * - * @since 1.8 - */ - public function clearCaches() { - $this->prop_ids = array(); - $this->prop_sortkeys = array(); - $this->regular_ids = array(); - $this->regular_sortkeys = array(); - } - - /** - * Ensure that the property ID and sortkey caches have space to insert - * at least one more element. If not, some other entries will be unset. - * - * @since 1.8 - */ - protected function checkPropertySizeLimit() { - if ( count( $this->prop_ids ) >= self::$PROP_CACHE_MAX_SIZE ) { - $keys = array_rand( $this->prop_ids, 10 ); - foreach ( $keys as $key ) { - unset( $this->prop_ids[$key] ); - unset( $this->prop_sortkeys[$key] ); - } - } - } - - /** - * Ensure that the non-property ID and sortkey caches have space to - * insert at least one more element. If not, some other entries will be - * unset. - * - * @since 1.8 - */ - protected function checkRegularSizeLimit() { - if ( count( $this->regular_ids ) >= self::$PAGE_CACHE_MAX_SIZE ) { - $keys = array_rand( $this->regular_ids, 10 ); - foreach ( $keys as $key ) { - unset( $this->regular_ids[$key] ); - unset( $this->regular_sortkeys[$key] ); - } - } - } - - /** - * Get the hash key for regular (non-property) pages. - * - * @since 1.8 - * @param string $title - * @param integer $namespace - * @param string $interwiki - * @param string $subobject - * @return string - */ - protected static function getRegularHashKey( $title, $namespace, $interwiki, $subobject ) { - return "$title#$namespace#$interwiki#$subobject"; - } - - /** - * Return an array of hashes with table names as keys. These - * hashes are used to compare new data with old data for each - * property-value table when updating data - * - * @since 1.8 - * - * @param integer $subjectId ID of the page as stored in the SMW IDs table - * - * @return array - */ - public function getPropertyTableHashes( $subjectId ) { - $hash = null; - $db = $this->store->getDatabase(); - - if ( $this->hashCacheId == $subjectId ) { - $hash = $this->hashCacheContents; - } elseif ( $subjectId !== 0 ) { - - $row = $db->selectRow( - self::tableName, - array( 'smw_proptable_hash' ), - 'smw_id=' . $subjectId , - __METHOD__ - ); - - if ( $row !== false ) { - $hash = $row->smw_proptable_hash; - } - } - - if ( $hash !== null && $GLOBALS['wgDBtype'] == 'postgres' ) { - $hash = pg_unescape_bytea( $hash ); - } - - return is_null( $hash ) ? array() : unserialize( $hash ); - } - - /** - * Update the proptable_hash for a given page. - * - * @since 1.8 - * @param integer $sid ID of the page as stored in SMW IDs table - * @param string[] of hash values with table names as keys - */ - public function setPropertyTableHashes( $sid, array $newTableHashes ) { - $db = $this->store->getDatabase(); - $propertyTableHash = serialize( $newTableHashes ); - - $db->update( - self::tableName, - array( 'smw_proptable_hash' => $propertyTableHash ), - array( 'smw_id' => $sid ), - __METHOD__ - ); - - if ( $sid == $this->hashCacheId ) { - $this->setPropertyTableHashesCache( $sid, $propertyTableHash ); - } - } - - /** - * Temporarily cache a property tablehash that has been retrieved for - * the given SMW ID. - * - * @since 1.8 - * @param $id integer - * @param $propertyTableHash string - */ - protected function setPropertyTableHashesCache( $id, $propertyTableHash ) { - if ( $id == 0 ) return; // never cache 0 - //print "Cache set for $id.\n"; - $this->hashCacheId = $id; - $this->hashCacheContents = $propertyTableHash; - } - - /** - * Simple helper method for debugging cache performance. Prints - * statistics about the SMWSql3SmwIds object created last. - * The following code can be used in LocalSettings.php to enable - * this in a wiki: - * - * $wgHooks['SkinAfterContent'][] = 'showCacheStats'; - * function showCacheStats() { - * self::debugDumpCacheStats(); - * return true; - * } - * - * @note This is a debugging/profiling method that no published code - * should rely on. - * - * @since 1.8 - */ - public static function debugDumpCacheStats() { - $that = self::$singleton_debug; - if ( is_null( $that ) ) return; - - $debugString = - "Statistics for SMWSql3SmwIds:\n" . - "- Executed {$that->selectrow_sort_debug} selects for sortkeys.\n" . - "- Executed {$that->selectrow_redi_debug} selects for redirects.\n" . - "- Regular cache hits: {$that->reghit_debug} misses: {$that->regmiss_debug}"; - if ( $that->regmiss_debug + $that->reghit_debug > 0 ) { - $debugString .= " rate: " . round( $that->reghit_debug/( $that->regmiss_debug + $that->reghit_debug ), 3 ); - } - $debugString .= " cache size: " . count( $that->regular_ids ) . "\n" ; - $debugString .= "- Property cache hits: {$that->prophit_debug} misses: {$that->propmiss_debug}"; - if ( $that->propmiss_debug + $that->prophit_debug > 0 ) { - $debugString .= " rate: " . round( $that->prophit_debug/( $that->propmiss_debug + $that->prophit_debug ), 3 ); - } - $debugString .= " cache size: " . count( $that->prop_ids ) . "\n"; - wfDebug( $debugString ); - } - - /** - * Returns store Id table name - * - * @return string - */ - public function getIdTable() { - return self::tableName; - } - -}
\ No newline at end of file diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SMW_Sql3StubSemanticData.php b/SemanticMediaWiki/includes/storage/SQLStore/SMW_Sql3StubSemanticData.php deleted file mode 100644 index 3e79d08d..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SMW_Sql3StubSemanticData.php +++ /dev/null @@ -1,325 +0,0 @@ -<?php - -use SMW\DataTypeRegistry; -use SMW\DIProperty; -use SMW\DIWikiPage; - -/** - * This class provides a subclass of SMWSemanticData that can store - * prefetched values from SMW's SQL stores, and unstub this data on demand when - * it is accessed. - * - * @since 1.8 - * @author Markus Krötzsch - * - * @ingroup SMWStore - */ -class SMWSql3StubSemanticData extends SMWSemanticData { - - /** - * The store object. - * - * @since 1.8 - * - * @var SMWSQLStore3 - */ - protected $store; - - /** - * Stub property data that is not part of $mPropVals and $mProperties - * yet. Entries use property keys as keys. The value is an array of - * DBkey-arrays that define individual datavalues. The stubs will be - * set up when first accessed. - * - * @since 1.8 - * - * @var array - */ - protected $mStubPropVals = array(); - - /** - * SMWDIWikiPage object that is the subject of this container. - * Subjects that are null are used to represent "internal objects" - * only. - * - * @since 1.8 - * - * @var SMWDIWikiPage - */ - protected $mSubject; - - /** - * Whether SubSemanticData have been requested and added - * - * @var boolean - */ - private $subSemanticDataInitialized = false; - - /** - * Constructor. - * - * @since 1.8 - * - * @param SMWDIWikiPage $subject to which this data refers - * @param SMWSQLStore3 $store (the parent store) - * @param boolean $noDuplicates stating if duplicate data should be avoided - */ - public function __construct( SMWDIWikiPage $subject, SMWSQLStore3 $store, $noDuplicates = true ) { - $this->store = $store; - parent::__construct( $subject, $noDuplicates ); - } - - /** - * Create a new SMWSql3StubSemanticData object that holds the data of a - * given SMWSemanticData object. Array assignments create copies in PHP - * so the arrays are distinct in input and output object. The object - * references are copied as references in a shallow way. This is - * sufficient as the data items used there are immutable. - * - * @since 1.8 - * - * @param $semanticData SMWSemanticData - * @param SMWSQLStore3 $store - * - * @return SMWSql3StubSemanticData - */ - public static function newFromSemanticData( SMWSemanticData $semanticData, SMWSQLStore3 $store ) { - $result = new SMWSql3StubSemanticData( $semanticData->getSubject(), $store ); - $result->mPropVals = $semanticData->mPropVals; - $result->mProperties = $semanticData->mProperties; - $result->mHasVisibleProps = $semanticData->mHasVisibleProps; - $result->mHasVisibleSpecs = $semanticData->mHasVisibleSpecs; - $result->stubObject = $semanticData->stubObject; - return $result; - } - - /** - * Get the array of all properties that have stored values. - * - * @since 1.8 - * - * @return array of SMWDIProperty objects - */ - public function getProperties() { - $this->unstubProperties(); - return parent::getProperties(); - } - - /** - * Get the array of all stored values for some property. - * - * @since 1.8 - * - * @param DIProperty $property - * - * @return array of SMWDataItem - */ - public function getPropertyValues( DIProperty $property ) { - if ( $property->isInverse() ) { // we never have any data for inverses - return array(); - } - - if ( array_key_exists( $property->getKey(), $this->mStubPropVals ) ) { - // Not catching exception here; the - $this->unstubProperty( $property->getKey(), $property ); - $propertyTypeId = $property->findPropertyTypeID(); - $propertyDiId = DataTypeRegistry::getInstance()->getDataItemId( $propertyTypeId ); - - foreach ( $this->mStubPropVals[$property->getKey()] as $dbkeys ) { - try { - $diHandler = $this->store->getDataItemHandlerForDIType( $propertyDiId ); - $di = $diHandler->dataItemFromDBKeys( $dbkeys ); - - if ( $this->mNoDuplicates ) { - $this->mPropVals[$property->getKey()][$di->getHash()] = $di; - } else { - $this->mPropVals[$property->getKey()][] = $di; - } - } catch ( SMWDataItemException $e ) { - // ignore data - } - } - - unset( $this->mStubPropVals[$property->getKey()] ); - } - - return parent::getPropertyValues( $property ); - } - - /** - * @see SemanticData::getSubSemanticData - * - * @note SubSemanticData are added only on request to avoid unnecessary DB - * transactions - * - * @since 2.0 - */ - public function getSubSemanticData() { - - if ( $this->subSemanticDataInitialized ) { - return parent::getSubSemanticData(); - } - - $this->subSemanticDataInitialized = true; - - foreach ( $this->getProperties() as $property ) { - - if ( $property->findPropertyTypeID() !== '__sob' ) { - continue; - } - - $this->addSubSemanticDataToInternalCache( $property ); - } - - return parent::getSubSemanticData(); - } - - /** - * @see SemanticData::hasSubSemanticData - * - * @note This method will initialize SubSemanticData first if it wasn't done - * yet to ensure data consistency - * - * @since 2.0 - */ - public function hasSubSemanticData( $subobjectName = null ) { - - if ( !$this->subSemanticDataInitialized ) { - $this->getSubSemanticData(); - } - - return parent::hasSubSemanticData( $subobjectName ); - } - - /** - * Remove a value for a property identified by its SMWDataItem object. - * This method removes a property-value specified by the property and - * dataitem. If there are no more property-values for this property it - * also removes the property from the mProperties. - * - * @note There is no check whether the type of the given data item - * agrees with the type of the property. Since property types can - * change, all parts of SMW are prepared to handle mismatched data item - * types anyway. - * - * @param $property SMWDIProperty - * @param $dataItem SMWDataItem - * - * @since 1.8 - */ - public function removePropertyObjectValue( DIProperty $property, SMWDataItem $dataItem ) { - $this->unstubProperties(); - $this->getPropertyValues( $property ); - parent::removePropertyObjectValue($property, $dataItem); - } - - /** - * Return true if there are any visible properties. - * - * @since 1.8 - * - * @return boolean - */ - public function hasVisibleProperties() { - $this->unstubProperties(); - return parent::hasVisibleProperties(); - } - - /** - * Return true if there are any special properties that can - * be displayed. - * - * @since 1.8 - * - * @return boolean - */ - public function hasVisibleSpecialProperties() { - $this->unstubProperties(); - return parent::hasVisibleSpecialProperties(); - } - - /** - * Add data in abbreviated form so that it is only expanded if needed. - * The property key is the DB key (string) of a property value, whereas - * valuekeys is an array of DBkeys for the added value that will be - * used to initialize the value if needed at some point. If there is - * only one valuekey, a single string can be used. - * - * @since 1.8 - * @param string $propertyKey - * @param array|string $valueKeys - */ - public function addPropertyStubValue( $propertyKey, $valueKeys ) { - $this->mStubPropVals[$propertyKey][] = $valueKeys; - } - - /** - * Delete all data other than the subject. - * - * @since 1.8 - */ - public function clear() { - $this->mStubPropVals = array(); - parent::clear(); - } - - /** - * Process all mProperties that have been added as stubs. - * Associated data may remain in stub form. - * - * @since 1.8 - */ - protected function unstubProperties() { - foreach ( $this->mStubPropVals as $pkey => $values ) { // unstub property values only, the value lists are still kept as stubs - try { - $this->unstubProperty( $pkey ); - } catch ( SMWDataItemException $e ) { - // Likely cause: a property name from the DB is no longer valid. - // Do nothing; we could unset the data, but it will never be - // unstubbed anyway if there is no valid property DI for it. - } - } - } - - /** - * Unstub a single property from the stub data array. If available, an - * existing object for that property might be provided, so we do not - * need to make a new one. It is not checked if the object matches the - * property name. - * - * @since 1.8 - * - * @param string $propertyKey - * @param SMWDIProperty $diProperty if available - * @throws SMWDataItemException if property key is not valid - * and $diProperty is null - */ - protected function unstubProperty( $propertyKey, $diProperty = null ) { - if ( !array_key_exists( $propertyKey, $this->mProperties ) ) { - if ( is_null( $diProperty ) ) { - $diProperty = new DIProperty( $propertyKey, false ); - } - - $this->mProperties[$propertyKey] = $diProperty; - - if ( !$diProperty->isUserDefined() ) { - if ( $diProperty->isShown() ) { - $this->mHasVisibleSpecs = true; - $this->mHasVisibleProps = true; - } - } else { - $this->mHasVisibleProps = true; - } - } - } - - private function addSubSemanticDataToInternalCache( DIProperty $property ) { - - foreach ( $this->getPropertyValues( $property ) as $value ) { - if ( $value instanceOf DIWikiPage && !$this->hasSubSemanticData( $value->getSubobjectName() ) ) { - $this->addSubSemanticData( $this->store->getSemanticData( $value ) ); - } - } - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/SimplePropertyStatisticsRebuilder.php b/SemanticMediaWiki/includes/storage/SQLStore/SimplePropertyStatisticsRebuilder.php deleted file mode 100644 index 91919dde..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/SimplePropertyStatisticsRebuilder.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -namespace SMW\SQLStore; - -use SMW\Store\PropertyStatisticsStore; -use SMW\Reporter\MessageReporter; -use SMW\Reporter\NullMessageReporter; - -use SMW\Store; - -use MWException; - -/** - * Simple implementation of PropertyStatisticsRebuilder. - * - * @since 1.9 - * - * @ingroup SMWStore - * - * @license GNU GPL v2 or later - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - * @author Nischay Nahata - */ -class SimplePropertyStatisticsRebuilder implements \SMW\Store\PropertyStatisticsRebuilder { - - /** @var Store */ - protected $store = null; - - /** - * @since 1.9 - * - * @var MessageReporter - */ - protected $reporter; - - /** - * @since 1.9 - * - * @param Store $store - * @param MessageReporter|null $reporter - */ - public function __construct( Store $store, MessageReporter $reporter = null ) { - $this->store = $store; - $this->reporter = $reporter; - - if ( $this->reporter === null ) { - $this->reporter = new NullMessageReporter(); - } - } - - /** - * @see PropertyStatisticsRebuilder::rebuild - * - * @since 1.9 - * - * @param PropertyStatisticsStore $propStatsStore - */ - public function rebuild( PropertyStatisticsStore $propStatsStore ) { - $this->reportMessage( "Updating property statistics. This may take a while.\n" ); - - $propStatsStore->deleteAll(); - - $res = $this->store->getDatabase()->select( - \SMWSql3SmwIds::tableName, - array( 'smw_id', 'smw_title' ), - array( 'smw_namespace' => SMW_NS_PROPERTY ), - __METHOD__ - ); - - foreach ( $res as $row ) { - $this->reportMessage( '.' ); - - $usageCount = 0; - foreach ( $this->store->getPropertyTables() as $propertyTable ) { - - if ( $propertyTable->isFixedPropertyTable() && $propertyTable->getFixedProperty() !== $row->smw_title ) { - // This table cannot store values for this property - continue; - } - - $usageCount += $this->getPropertyTableRowCount( $propertyTable, $row->smw_id ); - } - - $propStatsStore->insertUsageCount( (int)$row->smw_id, $usageCount ); - } - - $propCount = $res->numRows(); - $this->store->getDatabase()->freeResult( $res ); - $this->reportMessage( "\nUpdated statistics for $propCount Properties.\n" ); - } - - protected function getPropertyTableRowCount( $propertyTable, $id ) { - - $condition = $propertyTable->isFixedPropertyTable() ? array() : array( 'p_id' => $id ); - - $row = $this->store->getDatabase()->selectRow( - $propertyTable->getName(), - 'Count(*) as count', - $condition, - __METHOD__ - ); - - return $row->count; - } - - protected function reportMessage( $message ) { - $this->reporter->reportMessage( $message ); - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/StatisticsCollector.php b/SemanticMediaWiki/includes/storage/SQLStore/StatisticsCollector.php deleted file mode 100644 index 7ee2293c..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/StatisticsCollector.php +++ /dev/null @@ -1,266 +0,0 @@ -<?php - -namespace SMW\SQLStore; - -use SMW\Store\CacheableResultCollector; - -use SMW\SimpleDictionary; -use SMW\DIProperty; -use SMW\Settings; -use SMW\Store; - -use DatabaseBase; - -/** - * Collects statistical information provided by the store - * - * @ingroup SQLStore - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - * @author Nischay Nahata - */ -class StatisticsCollector extends CacheableResultCollector { - - /** @var Store */ - protected $store; - - /** @var Settings */ - protected $settings; - - /** @var DatabaseBase */ - protected $dbConnection; - - /** - * @since 1.9 - * - * @param Store $store - * @param DatabaseBase $dbw - * @param Settings $settings - */ - public function __construct( Store $store, DatabaseBase $dbw, Settings $settings ) { - $this->store = $store; - $this->dbConnection = $dbw; - $this->settings = $settings; - } - - /** - * Collects statistical information as an associative array - * with the following keys: - * - * - 'PROPUSES': Number of property instances (value assignments) in the dbConnection - * - 'USEDPROPS': Number of properties that are used with at least one value - * - 'DECLPROPS': Number of properties that have been declared (i.e. assigned a type) - * - 'OWNPAGE': Number of properties with their own page - * - 'QUERY': Number of inline queries - * - 'QUERYSIZE': Represents collective query size - * - 'CONCEPTS': Number of declared concepts - * - 'SUBOBJECTS': Number of declared subobjects - * - 'QUERYFORMATS': Array of used formats and its usage count - * - * @since 1.9 - * - * @return DIProperty[] - */ - public function runCollector() { - - return array( - 'OWNPAGE' => $this->getPropertyPageCount(), - 'QUERY' => $this->getQueryCount(), - 'QUERYSIZE' => $this->getQuerySize(), - 'QUERYFORMATS' => $this->getQueryFormatsCount(), - 'CONCEPTS' => $this->getConceptCount(), - 'SUBOBJECTS' => $this->getSubobjectCount(), - 'DECLPROPS' => $this->getDeclaredPropertiesCount(), - 'PROPUSES' => $this->getPropertyUsageCount(), - 'USEDPROPS' => $this->getUsedPropertiesCount() - ); - } - - /** - * @since 1.9 - * - * @return number - */ - public function getQueryCount() { - return $this->count( '_ASK' ); - } - - /** - * @since 1.9 - * - * @return number - */ - public function getQuerySize() { - return $this->count( '_ASKSI' ); - } - - /** - * @since 1.9 - * - * @return number - */ - public function getConceptCount() { - return $this->count( '_CONC' ); - } - - /** - * @since 1.9 - * - * @return number - */ - public function getSubobjectCount() { - return $this->count( DIProperty::TYPE_SUBOBJECT ); - } - - /** - * @since 1.9 - * - * @return number - */ - public function getDeclaredPropertiesCount() { - return $this->count( DIProperty::TYPE_HAS_TYPE ); - } - - /** - * @since 1.9 - * - * @return array - */ - public function getQueryFormatsCount() { - wfProfileIn( __METHOD__ ); - - $count = array(); - $res = $this->dbConnection->select( - $this->findPropertyTableByType( '_ASKFO' )->getName(), - 'o_hash, COUNT(s_id) AS count', - array(), - __METHOD__, - array( - 'ORDER BY' => 'count DESC', - 'GROUP BY' => 'o_hash' - ) - ); - - foreach ( $res as $row ) { - $count[$row->o_hash] = (int)$row->count; - } - - wfProfileOut( __METHOD__ ); - return $count; - } - - /** - * @since 1.9 - * - * @return number - */ - public function getPropertyPageCount() { - wfProfileIn( __METHOD__ ); - - $count = 0; - $count = $this->dbConnection->estimateRowCount( - 'page', - '*', - array( 'page_namespace' => SMW_NS_PROPERTY ) - ); - - wfProfileOut( __METHOD__ ); - return (int)$count; - } - - /** - * Count property uses by summing up property statistics table - * - * @note subproperties that are part of container values are counted - * individually and it does not seem to be important to filter them by - * adding more conditions. - * - * @since 1.9 - * - * @return number - */ - public function getPropertyUsageCount() { - wfProfileIn( __METHOD__ ); - - $count = 0; - $row = $this->dbConnection->selectRow( - array( $this->store->getStatisticsTable() ), - 'SUM( usage_count ) AS count', - array(), - __METHOD__ - ); - - $count = $row ? $row->count : $count; - - wfProfileOut( __METHOD__ ); - return (int)$count; - } - - /** - * @since 1.9 - * - * @return number - */ - public function getUsedPropertiesCount() { - wfProfileIn( __METHOD__ ); - - $count = 0; - $row = $this->dbConnection->selectRow( - array( $this->store->getStatisticsTable() ), - 'Count( * ) AS count', - array( 'usage_count > 0' ), - __METHOD__ - ); - - $count = $row ? $row->count : $count; - - wfProfileOut( __METHOD__ ); - return (int)$count; - } - - /** - * Convenience method to count on a single table for a given type - * - * @since 1.9 - * - * @param string $type - * - * @return number - */ - protected function count( $type ) { - $caller = wfGetCaller(); - wfProfileIn( $caller ); - - $count = 0; - $res = $this->dbConnection->select( - $this->findPropertyTableByType( $type )->getName(), - 'COUNT(s_id) AS count', - array(), - __METHOD__ - ); - $row = $this->dbConnection->fetchObject( $res ); - - wfProfileOut( $caller ); - return (int)$row->count; - } - - /** - * @see CacheableObjectCollector::cacheSetup - * - * @since 1.9 - * - * @return ObjectDictionary - */ - protected function cacheSetup() { - return new SimpleDictionary( array( - 'id' => array( 'smwgStatisticsCache', $this->requestOptions ), - 'type' => $this->settings->get( 'smwgCacheType' ), - 'enabled' => $this->settings->get( 'smwgStatisticsCache' ), - 'expiry' => $this->settings->get( 'smwgStatisticsCacheExpiry' ) - ) ); - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/TableDefinition.php b/SemanticMediaWiki/includes/storage/SQLStore/TableDefinition.php deleted file mode 100644 index 8dc581b5..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/TableDefinition.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php - -namespace SMW\SQLStore; - -use OutOfBoundsException; - -/** - * Simple data container for storing information about property tables. A - * property table is a DB table that is used to store subject-property-value - * records about data in SMW. Tables mostly differ in the composition of the - * value, but also in whether the property is explicitly named (or fixed), - * and in the way subject pages are referred to. - * - * @since 1.8 - * - * @ingroup SMWStore - * - * @licence GNU GPL v2+ - * @author Nischay Nahata - * @author Markus Krötzsch - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class TableDefinition { - - /** - * Name of the table in the DB. - * - * @since 1.8 - * @var string - */ - protected $name; - - /** - * DIType of this table. - * - * @since 1.8 - * @var integer - */ - protected $diType; - - /** - * If the table is only for one property, this field holds its key. - * Empty otherwise. Tables without a fixed property have a column "p_id" - * for storing the SMW page id of the property. - * - * @note It is important that this is the DB key form or special - * property key, not the label. This is not checked eagerly in SMW but - * can lead to spurious errors when properties are compared to each - * other or to the contents of the store. - * - * @since 1.8 - * @var string|boolean false - */ - protected $fixedProperty; - - /** - * Boolean that states how subjects are stored. If true, a column "s_id" - * with an SMW page id is used. If false, two columns "s_title" and - * "s_namespace" are used. The latter de-normalized form cannot store - * sortkeys and interwiki prefixes, and is used only for the redirect - * table. New tables should really keep the default "true" here. - * - * @since 1.8 - * @var boolean - */ - protected $idSubject = true; - - /** - * Factory method to create an instance for a given - * DI type and the given table name. - * - * @since 1.8 - * - * @param integer $DIType constant - * @param string $tableName logocal table name (not the DB version) - * @param string|false $fixedProperty property key if any - */ - public function __construct( $DIType, $tableName, $fixedProperty = false ) { - $this->name = $tableName; - $this->fixedProperty = $fixedProperty; - $this->diType = $DIType; - } - - /** - * Method to return the fields for this table - * - * @since 1.8 - * - * @param SMWSQLStore3 $store - * - * @return array - */ - public function getFields( \SMWSQLStore3 $store ) { - $diHandler = $store->getDataItemHandlerForDIType( $this->diType ); - return $diHandler->getTableFields(); - } - - /** - * @see $idSubject - * - * @since 1.8 - * - * @return boolean - */ - public function usesIdSubject() { - return $this->idSubject; - } - - /** - * @see $idSubject - * - * @param $usesIdSubject - * - * @since 1.8 - */ - public function setUsesIdSubject( $usesIdSubject ) { - $this->idSubject = $usesIdSubject; - } - - /** - * Returns the name of the fixed property which this table is for. - * Throws an exception when called on a table not for any fixed - * property, so call @see isFixedPropertyTable first when appropriate. - * - * @see $fixedProperty - * - * @since 1.8 - * - * @return string - * @throws OutOfBoundsException - */ - public function getFixedProperty() { - - if ( $this->fixedProperty === false ) { - throw new OutOfBoundsException( 'Attempt to get the fixed property from a table that does not hold one' ); - } - - return $this->fixedProperty; - } - - /** - * Returns if the table holds a fixed property or is a general table. - * - * @see $fixedProperty - * - * @since 1.8 - * - * @return boolean - */ - public function isFixedPropertyTable() { - return $this->fixedProperty !== false; - } - - /** - * Returns the name of the table in the database. - * - * @since 1.8 - * - * @return string - */ - public function getName() { - return $this->name; - } - - /** - * Returns @see $diType - * - * @since 1.8 - * - * @return integer - */ - public function getDiType() { - return $this->diType; - } -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/UnusedPropertiesCollector.php b/SemanticMediaWiki/includes/storage/SQLStore/UnusedPropertiesCollector.php deleted file mode 100644 index 1fa94703..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/UnusedPropertiesCollector.php +++ /dev/null @@ -1,144 +0,0 @@ -<?php - -namespace SMW\SQLStore; - -use SMW\Store\CacheableResultCollector; - -use SMW\InvalidPropertyException; -use SMW\SimpleDictionary; -use SMW\DIProperty; -use SMW\Settings; -use SMW\Profiler; -use SMW\Store; - -use SMWDIError; - -use Message; -use DatabaseBase; - -/** - * Collects unused properties from a store entity - * - * @ingroup SQLStore - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - * @author Nischay Nahata - */ -class UnusedPropertiesCollector extends CacheableResultCollector { - - /** @var Store */ - protected $store; - - /** @var Settings */ - protected $settings; - - /** @var DatabaseBase */ - protected $dbConnection; - - /** - * @since 1.9 - * - * @param Store $store - * @param DatabaseBase $dbw - * @param Settings $settings - */ - public function __construct( Store $store, DatabaseBase $dbw, Settings $settings ) { - $this->store = $store; - $this->dbConnection = $dbw; - $this->settings = $settings; - } - - /** - * Returns unused properties - * - * @since 1.9 - * - * @return DIProperty[] - */ - public function runCollector() { - return $this->getProperties( $this->doQuery() ); - } - - /** - * @see CacheableObjectCollector::cacheSetup - * - * @since 1.9 - * - * @return ObjectDictionary - */ - protected function cacheSetup() { - return new SimpleDictionary( array( - 'id' => array( 'smwgUnusedPropertiesCache', $this->requestOptions ), - 'type' => $this->settings->get( 'smwgCacheType' ), - 'enabled' => $this->settings->get( 'smwgUnusedPropertiesCache' ), - 'expiry' => $this->settings->get( 'smwgUnusedPropertiesCacheExpiry' ) - ) ); - } - - /** - * @since 1.9 - * - * @return array - */ - protected function doQuery() { - Profiler::In( __METHOD__ ); - - // the query needs to do the filtering of internal properties, else LIMIT is wrong - $options = array( 'ORDER BY' => 'smw_sortkey' ); - - if ( $this->requestOptions !== null ) { - if ( $this->requestOptions->limit > 0 ) { - $options['LIMIT'] = $this->requestOptions->limit; - $options['OFFSET'] = max( $this->requestOptions->offset, 0 ); - } - } - - $conditions = array( - 'smw_namespace' => SMW_NS_PROPERTY, - 'smw_iw' => '' - ); - - $conditions['usage_count'] = 0; - - $res = $this->dbConnection->select( - array( $this->store->getObjectIds()->getIdTable(), $this->store->getStatisticsTable() ), - array( 'smw_title', 'usage_count' ), - $conditions, - __METHOD__, - $options, - array( $this->store->getObjectIds()->getIdTable() => array( 'INNER JOIN', array( 'smw_id=p_id' ) ) ) - ); - - Profiler::Out( __METHOD__ ); - return $res; - } - - /** - * @since 1.9 - * - * @return DIProperty[] - */ - protected function getProperties( $res ) { - Profiler::In( __METHOD__ ); - - $result = array(); - - foreach ( $res as $row ) { - - try { - $property = new DIProperty( $row->smw_title ); - } catch ( InvalidPropertyException $e ) { - $property = new SMWDIError( new Message( 'smw_noproperty', array( $row->smw_title ) ) ); - } - - $result[] = $property; - } - - Profiler::Out( __METHOD__ ); - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/storage/SQLStore/WantedPropertiesCollector.php b/SemanticMediaWiki/includes/storage/SQLStore/WantedPropertiesCollector.php deleted file mode 100644 index ea893ea5..00000000 --- a/SemanticMediaWiki/includes/storage/SQLStore/WantedPropertiesCollector.php +++ /dev/null @@ -1,144 +0,0 @@ -<?php - -namespace SMW\SQLStore; - -use SMW\Store\CacheableResultCollector; - -use SMW\InvalidPropertyException; -use SMW\SimpleDictionary; -use SMW\DIProperty; -use SMW\Profiler; -use SMW\Settings; -use SMW\Store; - -use SMWDIError; - -use DatabaseBase; -use Message; -/** - * Collects wanted properties from a store entity - * - * @ingroup SQLStore - * - * @licence GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - * @author Nischay Nahata - */ -class WantedPropertiesCollector extends CacheableResultCollector { - - /** @var Store */ - protected $store; - - /** @var Settings */ - protected $settings; - - /** @var DatabaseBase */ - protected $dbConnection; - - /** - * @since 1.9 - * - * @param Store $store - * @param DatabaseBase $dbw - * @param Settings $settings - */ - public function __construct( Store $store, DatabaseBase $dbw, Settings $settings ) { - $this->store = $store; - $this->dbConnection = $dbw; - $this->settings = $settings; - } - - /** - * @since 1.9 - * - * @return DIProperty[] - */ - public function runCollector() { - - // Wanted Properties must have the default type - $this->propertyTable = $this->findPropertyTableByType( $this->settings->get( 'smwgPDefaultType' ), true ); - - // anything else would be crazy, but let's fail gracefully even if the whole world is crazy - if ( $this->propertyTable->isFixedPropertyTable() ) { - return array(); - } - - return $this->getProperties( $this->doQuery() ); - } - - /** - * @see CacheableObjectCollector::cacheSetup - * - * @since 1.9 - * - * @return ObjectDictionary - */ - protected function cacheSetup() { - return new SimpleDictionary( array( - 'id' => array( 'smwgWantedPropertiesCache', $this->settings->get( 'smwgPDefaultType' ), $this->requestOptions ), - 'type' => $this->settings->get( 'smwgCacheType' ), - 'enabled' => $this->settings->get( 'smwgWantedPropertiesCache' ), - 'expiry' => $this->settings->get( 'smwgWantedPropertiesCacheExpiry' ) - ) ); - } - - /** - * Returns wanted properties - * - * @note This function is very resource intensive and needs to be cached on - * medium/large wikis. - * - * @since 1.9 - * - * @return DIProperty[] - */ - protected function doQuery() { - Profiler::In( __METHOD__ ); - - $options = $this->store->getSQLOptions( $this->requestOptions, 'title' ); - $options['ORDER BY'] = 'count DESC'; - - // TODO: this is not how JOINS should be specified in the select function - $res = $this->dbConnection->select( - $this->dbConnection->tableName( $this->propertyTable->getName() ) . ' INNER JOIN ' . - $this->dbConnection->tableName( $this->store->getObjectIds()->getIdTable() ) . ' ON p_id=smw_id LEFT JOIN ' . - $this->dbConnection->tableName( 'page' ) . ' ON (page_namespace=' . - $this->dbConnection->addQuotes( SMW_NS_PROPERTY ) . ' AND page_title=smw_title)', - 'smw_title, COUNT(*) as count', - 'smw_id > 50 AND page_id IS NULL GROUP BY smw_title', - __METHOD__, - $options - ); - - Profiler::Out( __METHOD__ ); - return $res; - } - - /** - * @since 1.9 - * - * @return DIProperty[] - */ - protected function getProperties( $res ) { - Profiler::In( __METHOD__ ); - - $result = array(); - - foreach ( $res as $row ) { - - try { - $property = new DIProperty( $row->smw_title ); - } catch ( InvalidPropertyException $e ) { - $property = new SMWDIError( new Message( 'smw_noproperty', array( $row->smw_title ) ) ); - } - - $result[] = array( $property, $row->count ); - } - - Profiler::Out( __METHOD__ ); - return $result; - } - -} diff --git a/SemanticMediaWiki/includes/storage/StoreFactory.php b/SemanticMediaWiki/includes/storage/StoreFactory.php deleted file mode 100644 index 7353b777..00000000 --- a/SemanticMediaWiki/includes/storage/StoreFactory.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -namespace SMW; - -use RuntimeException; - -/** - * Factory method that returns an instance of the default store, or an - * alternative store - * - * @ingroup Factory - * @ingroup Store - * - * @license GNU GPL v2+ - * @since 1.9 - * - * @author mwjames - */ -class StoreFactory { - - /** @var Store[] */ - private static $instance = array(); - - /** @var string */ - private static $defaultStore = null; - - /** - * @since 1.9 - * - * @param string|null $store - * - * @return Store - * @throws RuntimeException - * @throws InvalidStoreException - */ - public static function getStore( $store = null ) { - - if ( self::$defaultStore === null ) { - self::$defaultStore = self::getConfiguration()->get( 'smwgDefaultStore' ); - } - - if ( $store === null ) { - $store = self::$defaultStore; - } - - if ( !isset( self::$instance[ $store ] ) ) { - self::$instance[ $store ] = self::newInstance( $store ); - self::$instance[ $store ]->setConfiguration( self::getConfiguration() ); - } - - return self::$instance[ $store ]; - } - - /** - * @note This method should not be used in production code and is mostly - * provided to inject instances during unit testing - * - * @since 2.0 - * - * @param Store $instance - */ - public static function setDefaultStoreForUnitTest( Store $instance ) { - - if ( self::$defaultStore === null ) { - self::$defaultStore = self::getConfiguration()->get( 'smwgDefaultStore' ); - } - - self::$instance[ self::$defaultStore ] = $instance; - } - - /** - * @since 1.9 - */ - public static function clear() { - self::$instance = array(); - self::$defaultStore = null; - } - - private static function getConfiguration() { - return Settings::newFromGlobals(); - } - - private static function newInstance( $store ) { - - if ( !class_exists( $store ) ) { - throw new RuntimeException( "Expected a {$store} class" ); - } - - $instance = new $store; - - if ( !( $instance instanceof Store ) ) { - throw new InvalidStoreException( "{$store} can not be used as a store instance" ); - } - - return $instance; - } - -} diff --git a/SemanticMediaWiki/includes/storage/StringCondition.php b/SemanticMediaWiki/includes/storage/StringCondition.php deleted file mode 100644 index 378fbc18..00000000 --- a/SemanticMediaWiki/includes/storage/StringCondition.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/** - * Small data container class for describing filtering conditions on the string - * label of some entity. States that a given string should either be prefix, - * postfix, or some arbitrary part of labels. - * - * @ingroup SMWStore - * - * @author Markus Krötzsch - */ -class SMWStringCondition { - - const STRCOND_PRE = 0; - const STRCOND_POST = 1; - const STRCOND_MID = 2; - - /** - * String to match. - */ - public $string; - - /** - * Condition. One of STRCOND_PRE (string matches prefix), - * STRCOND_POST (string matches postfix), STRCOND_MID - * (string matches to some inner part). - */ - public $condition; - - public function __construct( $string, $condition ) { - $this->string = $string; - $this->condition = $condition; - } - -}
\ No newline at end of file |