/** * Adds a SMWDataItem representing a deletion to the set for the specified SMWDIProperty. * * @since 0.1 * * @param SMWDIProperty $property * @param SMWDataItem $dataItem */ public function addDeletion(SMWDIProperty $property, SMWDataItem $dataItem) { $this->deletions->addPropertyObjectValue($property, $dataItem); }
/** * 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 = smwfGetStore()->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 = smwfGetStore()->getPropertySubjects( $property, $this->subject->getDataItem(), $valoptions ); foreach ( $values as $value ) { $indata->addPropertyObjectValue( $property, $value ); } } return array( $indata, $more ); }
/** * 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) { // Issue 619 // Resolve the redirect target and return a container with information // about the redirect if ($diWikiPage->getTitle() !== null && $diWikiPage->getTitle()->isRedirect()) { try { $redirectTarget = $this->getDeepRedirectTargetResolver()->findRedirectTargetFor($diWikiPage->getTitle()); } catch (\Exception $e) { $redirectTarget = null; } // Couldn't resolve the redirect which is most likely caused by a // circular redirect therefore we give up if ($redirectTarget === null) { return null; } $semData = new SemanticData($diWikiPage); $semData->addPropertyObjectValue(new DIProperty('_REDI'), DIWikiPage::newFromTitle($redirectTarget)); return $semData; } $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 SMW\DIProperty($propid); $values = $semdata->getPropertyValues($prop); foreach ($values as $dv) { $result->addPropertyObjectValue($prop, $dv); } } } else { $result = clone $semdata; } return $result; }
/** * Create exportable data from a given semantic data record. * * @param $semdata SMWSemanticData * @return SMWExpData */ public static function makeExportData(SMWSemanticData $semdata) { self::initBaseURIs(); $subject = $semdata->getSubject(); // #649 Alwways make sure to have a least one valid sortkey if (!$semdata->getPropertyValues(new DIProperty('_SKEY')) && $subject->getSortKey() !== '') { $semdata->addPropertyObjectValue(new DIProperty('_SKEY'), new SMWDIBlob($subject->getSortKey())); } $result = self::makeExportDataForSubject($subject); foreach ($semdata->getProperties() as $property) { self::addPropertyValues($property, $semdata->getPropertyValues($property), $result, $subject); } return $result; }
/** * Get derived properties. * @param SMWSemanticData $semData * Annotated facts of an article * @return SMWSemanticData * Derived facts of the article */ public static function getDerivedProperties(SMWSemanticData $semData) { global $smwgIP, $smwgHaloIP, $smwgTripleStoreGraph; require_once $smwgIP . '/includes/SMW_QueryProcessor.php'; require_once $smwgHaloIP . '/includes/storage/SMW_TripleStore.php'; $derivedProperties = new SMWSemanticData($semData->getSubject()); $subject = $semData->getSubject()->getDBkey(); global $wgContLang; $subject = $semData->getSubject(); $ns = strtolower($wgContLang->getNSText($subject->getNamespace())); if (empty($ns)) { $ns = 'a'; } $localName = $subject->getDBkey(); $inst = $smwgTripleStoreGraph . TSNamespaces::$INST_NS_SUFFIX; // $queryText = "PREFIX a:<$inst> SELECT ?pred ?obj WHERE { a:$subject ?pred ?obj . }"; // $queryText = "SELECT ?pred ?obj WHERE { a:$subject ?pred ?obj . }"; $queryText = "SELECT ?pred ?obj WHERE { <" . $smwgTripleStoreGraph . "/{$ns}#{$localName}> ?pred ?obj . }"; // echo $queryText; wfRunHooks('BeforeDerivedPropertyQuery', array(&$queryText)); // Ask for all properties of the subject (derived and ground facts) $q = SMWSPARQLQueryProcessor::createQuery($queryText, array()); $res = smwfGetStore()->getQueryResult($q); // SMWQueryResult wfRunHooks('AfterDerivedPropertyQuery', array()); wfRunHooks('FilterQueryResults', array(&$res, array('pred'))); $propVal = array(); while ($row = $res->getNext()) { //$row: SMWResultArray[] $i = 0; $valuesForProperty = array(); $key = false; if (count($row) == 2) { $properties = array(); $values = array(); // There may be several properties with the same values $p = $row[0]; while (($object = $p->getNextObject()) !== false) { if ($object instanceof SMWURIValue) { $keys = $object->getDBkeys(); $properties[] = $keys[0]; } else { $properties[] = $object->getDBkey(); } } // Retrieve the values of the properties $v = $row[1]; while (($object = $v->getNextObject()) !== false) { $values[] = $object; } } foreach ($properties as $p) { if (array_key_exists($p, $propVal)) { // The same property may appear several times $propVal[$p] = array_merge($values, $propVal[$p]); } else { $propVal[$p] = $values; } } } // Check is a property is derived or directly annotated foreach ($propVal as $propName => $derivedValues) { // does the property already exist? $prop = SMWPropertyValue::makeUserProperty($propName); $values = $semData->getPropertyValues($prop); foreach ($derivedValues as $dv) { $isDerived = true; $val = null; foreach ($values as $v) { if ($dv->getTypeID() == '_wpg' && $v->getTypeID() == '_wpg') { $vt1 = $dv->getTitle(); $vt2 = $v->getTitle(); if (isset($vt1) && isset($vt2) && $vt1->getText() == $vt2->getText()) { $isDerived = false; break; } } else { if ($dv->getTypeID() == '_wpg' && $v->getTypeID() != '_wpg') { // how can this happen? $isDerived = false; break; } else { if ($dv->isNumeric()) { if ($dv->getWikiValue() == $v->getWikiValue()) { $isDerived = false; break; } } else { if (array_shift($dv->getDBkeys()) == array_shift($v->getDBkeys())) { $isDerived = false; break; } } } } } if ($isDerived) { $property = SMWPropertyValue::makeUserProperty($propName); $derivedProperties->addPropertyObjectValue($property, $dv); } } } return $derivedProperties; }
/** * 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 = smwfGetStore()->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; }
/** * This function takes care of storing the collected semantic data and takes * care of clearing out any outdated entries for the processed page. It assume that * parsing has happened and that all relevant data is contained in the provided parser * output. * * Optionally, this function also takes care of triggering indirect updates that might be * needed for 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 SMWUpdateJobs for the relevant articles, * which then asynchronously update the semantic data in the database. * * @param $parseroutput ParserOutput object that contains the results of parsing which will * be stored. * @param $title Title object specifying the page that should be saved. * @param $makejobs Bool stating whether jobs should be created to trigger further updates if * this appears to be necessary after this update. * * @todo FIXME: Some job generations here might create too many jobs at once on a large wiki. Use incremental jobs instead. */ public static function storeData($parseroutput, Title $title, $makejobs = true) { global $smwgEnableUpdateJobs, $smwgDeclarationProperties, $smwgPageSpecialProperties; $semdata = $parseroutput->mSMWData; $namespace = $title->getNamespace(); $processSemantics = smwfIsSemanticsProcessed($namespace); if (!isset($semdata)) { // no data at all? $semdata = new SMWSemanticData(SMWDIWikiPage::newFromTitle($title)); } if ($processSemantics) { $props = array(); foreach ($smwgPageSpecialProperties as $propId) { // Do not calculate the same property again. if (array_key_exists($propId, $props)) { continue; } // Remember the property is processed. $props[$propId] = true; $prop = new SMWDIProperty($propId); if (count($semdata->getPropertyValues($prop)) > 0) { continue; } // Calculate property value. $value = null; switch ($propId) { case '_MDAT': $timestamp = Revision::getTimeStampFromID($title, $title->getLatestRevID()); $value = self::getDataItemFromMWTimestamp($timestamp); break; case '_CDAT': $timestamp = $title->getFirstRevision()->getTimestamp(); $value = self::getDataItemFromMWTimestamp($timestamp); break; case '_NEWP': $value = new SMWDIBoolean($title->isNewPage()); break; case '_LEDT': $revision = Revision::newFromId($title->getLatestRevID()); $user = User::newFromId($revision->getUser()); $value = SMWDIWikiPage::newFromTitle($user->getUserPage()); break; } if (!is_null($value)) { $semdata->addPropertyObjectValue($prop, $value); } // Issue error or warning? } // foreach } else { // data found, but do all operations as if it was empty $semdata = new SMWSemanticData($semdata->getSubject()); } // Check if the semantic data has been changed. // Sets the updateflag to true if so. // Careful: storage access must happen *before* the storage update; // even finding uses of a property fails after its type was changed. $updatejobflag = false; $jobs = array(); if ($makejobs && $smwgEnableUpdateJobs && $namespace == SMW_NS_PROPERTY) { // If it is a property, then we need to check if the type or the allowed values have been changed. $ptype = new SMWDIProperty('_TYPE'); $oldtype = smwfGetStore()->getPropertyValues($semdata->getSubject(), $ptype); $newtype = $semdata->getPropertyValues($ptype); if (!self::equalDatavalues($oldtype, $newtype)) { $updatejobflag = true; } else { foreach ($smwgDeclarationProperties as $prop) { $pv = new SMWDIProperty($prop); $oldvalues = smwfGetStore()->getPropertyValues($semdata->getSubject(), $pv); $newvalues = $semdata->getPropertyValues($pv); $updatejobflag = !self::equalDatavalues($oldvalues, $newvalues); } } if ($updatejobflag) { $prop = new SMWDIProperty($title->getDBkey()); $subjects = smwfGetStore()->getAllPropertySubjects($prop); foreach ($subjects as $subject) { $subjectTitle = $subject->getTitle(); if (!is_null($subjectTitle)) { // wikia change start - jobqueue migration $task = new \Wikia\Tasks\Tasks\JobWrapperTask(); $task->call('SMWUpdateJob', $subjectTitle); $jobs[] = $task; // wikia change end } } wfRunHooks('smwUpdatePropertySubjects', array(&$jobs)); $subjects = smwfGetStore()->getPropertySubjects(new SMWDIProperty('_ERRP'), $semdata->getSubject()); foreach ($subjects as $subject) { $subjectTitle = $subject->getTitle(); if (!is_null($subjectTitle)) { // wikia change start - jobqueue migration $task = new \Wikia\Tasks\Tasks\JobWrapperTask(); $task->call('SMWUpdateJob', $subjectTitle); $jobs[] = $task; // wikia change end } } } } elseif ($makejobs && $smwgEnableUpdateJobs && $namespace == SMW_NS_TYPE) { // if it is a type we need to check if the conversion factors have been changed $pconv = new SMWDIProperty('_CONV'); $ptype = new SMWDIProperty('_TYPE'); $oldfactors = smwfGetStore()->getPropertyValues($semdata->getSubject(), $pconv); $newfactors = $semdata->getPropertyValues($pconv); $updatejobflag = !self::equalDatavalues($oldfactors, $newfactors); if ($updatejobflag) { $store = smwfGetStore(); /// FIXME: this will kill large wikis! Use incremental updates! $dv = SMWDataValueFactory::newTypeIdValue('__typ', $title->getDBkey()); $proppages = $store->getPropertySubjects($ptype, $dv); foreach ($proppages as $proppage) { $propertyTitle = $proppage->getTitle(); if (!is_null($propertyTitle)) { // wikia change start - jobqueue migration $task = new \Wikia\Tasks\Tasks\JobWrapperTask(); $task->call('SMWUpdateJob', $propertyTitle); $jobs[] = $task; // wikia change end } $prop = new SMWDIProperty($proppage->getDBkey()); $subjects = $store->getAllPropertySubjects($prop); foreach ($subjects as $subject) { $subjectTitle = $subject->getTitle(); if (!is_null($subjectTitle)) { // wikia change start - jobqueue migration $task = new \Wikia\Tasks\Tasks\JobWrapperTask(); $task->call('SMWUpdateJob', $subjectTitle); $jobs[] = $task; // wikia change end } } $subjects = smwfGetStore()->getPropertySubjects(new SMWDIProperty('_ERRP'), $prop->getWikiPageValue()); foreach ($subjects as $subject) { $subjectTitle = $subject->getTitle(); if (!is_null($subjectTitle)) { // wikia change start - jobqueue migration $task = new \Wikia\Tasks\Tasks\JobWrapperTask(); $task->call('SMWUpdateJob', $subjectTitle); $jobs[] = $task; // wikia change end } } } } } // Actually store semantic data, or at least clear it if needed if ($processSemantics) { smwfGetStore()->updateData($semdata); } else { smwfGetStore()->clearData($semdata->getSubject()); } // Finally trigger relevant Updatejobs if necessary if ($updatejobflag) { // wikia change start - jobqueue migration \Wikia\Tasks\Tasks\BaseTask::batch($jobs); // wikia change end } return true; }
/** * 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 = self::$incomingpropertiescount; if ($this->offset > 0) { $options->offset = $this->offset; } $store = \SMW\StoreFactory::getStore(); $inproperties = $store->getInProperties($this->subject->getDataItem(), $options); if (count($inproperties) == self::$incomingpropertiescount) { $more = true; array_pop($inproperties); // drop the last one } else { $more = false; } $valoptions = new SMWRequestOptions(); $valoptions->sort = true; $valoptions->limit = self::$incomingvaluescount; foreach ($inproperties as $property) { $values = $store->getPropertySubjects($property, $this->subject->getDataItem(), $valoptions); foreach ($values as $value) { $indata->addPropertyObjectValue($property, $value); } } // Added in 2.3 wfRunHooks('SMW::Browse::AfterIncomingPropertiesLookupComplete', array($store, $indata, $valoptions)); return array($indata, $more); }
/** * Reads the paramstring for remove and add and turns it into * SMWSemanticData object that can be used with the SMWWriter API * * @param Title $title Title of the page to be modified * @param string $text The param value * @return SMWSemanticData Object with the interpreted data from the param value */ private function readData( Title $title, /* string */ $text ) { if ( empty( $text ) ) return new SMWSemanticData( SMWWikiPageValue::makePage( false, 0 ) ); if ( $text == '*' ) return new SMWSemanticData( SMWWikiPageValue::makePage( $title, 0 ) ); $result = new SMWSemanticData( SMWWikiPageValue::makePageFromTitle( $title ) ); $matches = array(); preg_match_all( "/\[\[([^\[\]]*)\]\]/", $text, $matches, PREG_PATTERN_ORDER ); foreach ( $matches[1] as $match ) { $parts = explode( "::", $match ); if ( count( $parts ) != 2 ) continue; $property = SMWPropertyValue::makeUserProperty( trim( $parts[0] ) ); if ( trim( $parts[1] ) == '*' ) $value = SMWDataValueFactory::newPropertyObjectValue( $property, false ); else $value = SMWDataValueFactory::newPropertyObjectValue( $property, trim( $parts[1] ) ); $result->addPropertyObjectValue( $property, $value ); } return $result; }
/** * @since 2.5 * * @param string $sortKey */ public function addCompositeSortKey($sortKey) { $this->m_semanticData->addPropertyObjectValue(new DIProperty('_SKEY'), new DIBlob($this->m_semanticData->getSubject()->getSortKey() . '#' . $sortKey)); }
/** * Create exportable data from a given semantic data record. * * @param $semdata SMWSemanticData * @return SMWExpData */ public static function makeExportData(SMWSemanticData $semdata) { self::initBaseURIs(); $subject = $semdata->getSubject(); // Make sure to use the canonical form, a localized representation // should not carry a reference to a subject (e.g invoked as incoming // property caused by a different user language) if ($subject->getNamespace() === SMW_NS_PROPERTY && $subject->getSubobjectName() === '') { $subject = DIProperty::newFromUserLabel($subject->getDBKey())->getCanonicalDiWikiPage(); } // #1690 Couldn't match a CanonicalDiWikiPage which is most likely caused // by an outdated pre-defined property therefore use the original subject if ($subject->getDBKey() === '') { $subject = $semdata->getSubject(); } // #649 Alwways make sure to have a least one valid sortkey if (!$semdata->getPropertyValues(new DIProperty('_SKEY')) && $subject->getSortKey() !== '') { $semdata->addPropertyObjectValue(new DIProperty('_SKEY'), new SMWDIBlob($subject->getSortKey())); } $result = self::makeExportDataForSubject($subject); foreach ($semdata->getProperties() as $property) { self::addPropertyValues($property, $semdata->getPropertyValues($property), $result, $subject); } return $result; }
/** * Formats the content of this object into a SMWSemanticData object * * @param Title $title Title of the page this SMWWriterData refers to * @return SMWSemanticData The conent of this SMWWriterData object as a * SMWSemanticData object */ public function getSemanticData( Title $title ) { $result = new SMWSemanticData( SMWWikiPageValue::makePageFromTitle( $title ), 0 ); $propertynames = $this->getPropertynames(); foreach ( $propertynames as $propertyname ) { $property = SMWPropertyValue::makeUserProperty( $propertyname ); $values = $this->getPropertyValues( $propertyname ); foreach ( $values as $value ) { $result->addPropertyObjectValue( $property, $value ); } } return $result; }