/** * Get the array of all stored values for some property. * * @param $property SMWDIProperty * @return array of SMWDataItem */ public function getPropertyValues(SMWDIProperty $property) { if ($property->isInverse()) { // we never have any data for inverses return array(); } if (array_key_exists($property->getKey(), $this->mStubPropVals)) { $this->unstubProperty($property->getKey(), $property); $propertyTypeId = $property->findPropertyTypeID(); $propertyDiId = SMWDataValueFactory::getDataItemId($propertyTypeId); foreach ($this->mStubPropVals[$property->getKey()] as $dbkeys) { try { if ($propertyDiId == SMWDataItem::TYPE_CONTAINER) { $diSubWikiPage = SMWCompatibilityHelpers::dataItemFromDBKeys('_wpg', $dbkeys); $semanticData = new SMWContainerSemanticData($diSubWikiPage); $semanticData->copyDataFrom(smwfGetStore()->getSemanticData($diSubWikiPage)); $di = new SMWDIContainer($semanticData); } else { $di = SMWCompatibilityHelpers::dataItemFromDBKeys($propertyTypeId, $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); }
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); }
/** * This function does the same as makeSMWPageID() but takes into account * that properties might be predefined. */ protected function makeSMWPropertyID(SMWDIProperty $property) { if (!$property->isUserDefined() && array_key_exists($property->getKey(), self::$special_ids)) { return self::$special_ids[$property->getKey()]; // very important property with fixed id } else { return $this->makeSMWPageID($property->getKey(), SMW_NS_PROPERTY, $this->getPropertyInterwiki($property), '', true); } }
/** * Retrieve the id of the property table that is to be used for storing * values for the given property object. * * @since 1.8 * @param SMWDIProperty $diProperty * @return string */ public static function findPropertyTableID(SMWDIProperty $diProperty) { $propertyKey = $diProperty->getKey(); // This is needed to initialize the $fixedPropertyTableIds field self::getPropertyTables(); if (array_key_exists($propertyKey, self::$fixedPropertyTableIds)) { return self::$fixedPropertyTableIds[$propertyKey]; } else { return self::findTypeTableId($diProperty->findPropertyTypeID()); } }
/** * @see SMWStore::getPropertySubjects * * @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 = SMWSQLStore3::findPropertyTableID($property); if ($pid == 0 || $tableid === '') { wfProfileOut("SMWSQLStoreLight::getPropertySubjects (SMW)"); return array(); } $proptables = SMWSQLStore3::getPropertyTables(); $proptable = $proptables[$tableid]; $db = wfGetDB(DB_SLAVE); if ($proptable->idsubject) { // join in smw_ids to get title data $from = $db->tableName('smw_ids') . " INNER JOIN " . $db->tableName($proptable->name) . " AS t1 ON t1.s_id=smw_id"; $select = 'smw_title, smw_namespace, smw_sortkey, smw_iw, smw_subobject'; } else { // no join needed, title+namespace as given in proptable $from = $db->tableName($proptable->name) . " AS t1"; $select = 's_title AS smw_title, s_namespace AS smw_namespace, s_title AS smw_sortkey, \'\' AS smw_iw, \'\' AS smw_subobject'; } if ($proptable->fixedproperty == false) { $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 !== ''), 'SMW::getPropertySubjects', $this->store->getSQLOptions($requestoptions, 'smw_sortkey')); foreach ($res as $row) { try { if ($row->smw_iw === '' || $row->smw_iw[0] != ':') { // filter special objects $result[] = new SMWDIWikiPage($row->smw_title, $row->smw_namespace, $row->smw_iw, $row->smw_subobject); } } 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; }
/** * @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 SMWDataItem|null $value * @param SMWRequestOptions|null $requestOptions * * @return array of DIWikiPage */ public function getPropertySubjects(SMWDIProperty $property, SMWDataItem $value = null, SMWRequestOptions $requestOptions = null) { /// TODO: should we share code with #ask query computation here? Just use queries? if ($property->isInverse()) { // inverses are working differently $noninverse = new SMW\DIProperty($property->getKey(), false); $result = $this->getPropertyValues($value, $noninverse, $requestOptions); return $result; } // #1222, Filter those where types don't match (e.g property = _txt // and value = _wpg) if ($value !== null && DataTypeRegistry::getInstance()->getDataItemId($property->findPropertyTypeID()) !== $value->getDIType()) { return array(); } // 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 === '') { return array(); } $proptables = $this->store->getPropertyTables(); $proptable = $proptables[$tableid]; $db = $this->store->getConnection(); if ($proptable->usesIdSubject()) { // join with ID table to get title data $from = $db->tableName(SMWSql3SmwIds::TABLE_NAME) . " 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(); if (!$proptable->isFixedPropertyTable()) { if ($where !== '' && strpos(SMW_SQL3_SMWIW_OUTDATED, $where) === false) { $where .= " AND smw_iw!=" . $db->addQuotes(SMW_SQL3_SMWIW_OUTDATED) . " AND smw_iw!=" . $db->addQuotes(SMW_SQL3_SMWDELETEIW); } else { $where .= " smw_iw!=" . $db->addQuotes(SMW_SQL3_SMWIW_OUTDATED) . " AND smw_iw!=" . $db->addQuotes(SMW_SQL3_SMWDELETEIW); } } $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 (DataItemHandlerException $e) { // silently drop data, should be extremely rare and will usually fix itself at next edit } } $db->freeResult($res); return $result; }
/** * 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 { $sortkey = ''; return $this->makeDatabaseId($property->getKey(), SMW_NS_PROPERTY, $this->getPropertyInterwiki($property), '', true, $property->getLabel(), false); } }
/** * 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(SMWDIProperty $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()]); } }
/** * 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(SMWSQLStore3::ID_TABLE, 'smw_iw', 'smw_id=' . $db->addQuotes(\SMWSql3SmwIds::FXD_PROP_BORDER_ID)); if ($borderiw != SMW_SQL3_SMWBORDERIW) { $this->reportProgress(" ... allocating space for internal properties ...\n", $verbose); $this->store->smwIds->moveSMWPageID(\SMWSql3SmwIds::FXD_PROP_BORDER_ID); // make sure position 50 is empty $db->insert(SMWSQLStore3::ID_TABLE, array('smw_id' => \SMWSql3SmwIds::FXD_PROP_BORDER_ID, '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 < \SMWSql3SmwIds::FXD_PROP_BORDER_ID; $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(SMWSQLStore3::ID_TABLE, 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 = SMWSQLStore3::ID_TABLE . '_smw_id_seq'; $this->reportProgress(" ... updating {$sequenceIndex} sequence accordingly.\n", $verbose); $max = $db->selectField(SMWSQLStore3::ID_TABLE, 'max(smw_id)', array(), __METHOD__); $max += 1; $db->query("ALTER SEQUENCE {$sequenceIndex} RESTART WITH {$max}", __METHOD__); } $this->reportProgress("Internal properties initialized successfully.\n", $verbose); }
/** * 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 SMWDIProperty * @param $dataItem SMWDataItem */ public function addPropertyObjectValue(SMWDIProperty $property, SMWDataItem $dataItem) { 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; } }
/** * Removes all changes for a certian property. * * @param SMWDIProperty $property */ public function removeChangesForProperty(SMWDIProperty $property) { if (array_key_exists($property->getKey(), $this->changes)) { unset($this->changes[$property->getKey()]); unset($this->properties[$property->getKey()]); } }
/** * Get the array of all stored values for some property. * * @since 1.8 * * @param $property SMWDIProperty * * @return array of SMWDataItem */ public function getPropertyValues(SMWDIProperty $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 = SMWDataValueFactory::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); }