/**
     * Handle the onDataChanged hook of SMW >1.6, which gets called
     * every time the value of a propery changes somewhere.
     *
     * @since 0.1
     *
     * @param SMWStore $store
     * @param SMWChangeSet $changes
     * 
     * @return true
     */
	public static function onDataUpdate( SMWStore $store, SMWSemanticData $newData ) {
		$subject = $newData->getSubject();
		$oldData = $store->getSemanticData( $subject );
		$title = Title::makeTitle( $subject->getNamespace(), $subject->getDBkey() );
		
		$groups = SWLGroups::getMatchingWatchGroups( $title );
		
		$edit = false;
		
		foreach ( $groups as /* SWLGroup */ $group ) {
			$changeSet = SWLChangeSet::newFromSemanticData( $oldData, $newData, $group->getProperties() );
			
			if ( $changeSet->hasUserDefinedProperties() ) {
				if ( $edit === false ) {
					$edit = new SWLEdit(
						$title->getArticleID(), 
						$GLOBALS['wgUser']->getName(),
						wfTimestampNow()
					);
					
					$edit->writeToDB();
				}
				
				$changeSet->setEdit( $edit );
				$setId = $changeSet->writeToStore( $groups, $edit->getId() );
				
				if ( $setId != 0 ) {
					$group->notifyWatchingUsers( $changeSet );
				}	
			}
		}
		
		return true;
	}
예제 #2
0
 /**
  * Create a new SMWSqlStubSemanticData 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.
  *
  * @param $semanticData SMWSemanticData
  * @return SMWSqlStubSemanticData
  */
 public static function newFromSemanticData(SMWSemanticData $semanticData)
 {
     $result = new SMWSqlStubSemanticData($semanticData->getSubject());
     $result->mPropVals = $semanticData->mPropVals;
     $result->mProperties = $semanticData->mProperties;
     $result->mHasVisibleProps = $semanticData->mHasVisibleProps;
     $result->mHasVisibleSpecs = $semanticData->mHasVisibleSpecs;
     $result->stubObject = $semanticData->stubObject;
     return $result;
 }
예제 #3
0
	/**
	 * 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;
	}
예제 #4
0
 /**
  * Update the semantic data stored for some individual. The data is
  * given as a SMWSemanticData object, which contains all semantic data
  * for one particular subject.
  *
  * @param $data SMWSemanticData
  */
 public function updateData(SMWSemanticData $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));
 }
예제 #5
0
 /**
  * This function creates wiki text suitable for rendering a Factbox for a given
  * SMWSemanticData object that holds all relevant data. It also checks whether the
  * given setting of $showfactbox requires displaying the given data at all.
  * 
  * @param SMWSemanticData $semdata
  * @param boolean $showfactbox
  * 
  * @return string
  */
 public static function getFactboxText(SMWSemanticData $semdata, $showfactbox = SMW_FACTBOX_NONEMPTY)
 {
     global $wgContLang;
     wfProfileIn('SMWFactbox::printFactbox (SMW)');
     switch ($showfactbox) {
         case SMW_FACTBOX_HIDDEN:
             // never show
             wfProfileOut('SMWFactbox::printFactbox (SMW)');
             return '';
         case SMW_FACTBOX_SPECIAL:
             // show only if there are special properties
             if (!$semdata->hasVisibleSpecialProperties()) {
                 wfProfileOut('SMWFactbox::printFactbox (SMW)');
                 return '';
             }
             break;
         case SMW_FACTBOX_NONEMPTY:
             // show only if non-empty
             if (!$semdata->hasVisibleProperties()) {
                 wfProfileOut('SMWFactbox::printFactbox (SMW)');
                 return '';
             }
             break;
             // case SMW_FACTBOX_SHOWN: // just show ...
     }
     // actually build the Factbox text:
     $text = '';
     if (wfRunHooks('smwShowFactbox', array(&$text, $semdata))) {
         $subjectDv = SMWDataValueFactory::newDataItemValue($semdata->getSubject(), null);
         SMWOutputs::requireResource('ext.smw.style');
         $rdflink = SMWInfolink::newInternalLink(wfMessage('smw_viewasrdf')->inContentLanguage()->text(), $wgContLang->getNsText(NS_SPECIAL) . ':ExportRDF/' . $subjectDv->getWikiValue(), 'rdflink');
         $browselink = SMWInfolink::newBrowsingLink($subjectDv->getText(), $subjectDv->getWikiValue(), 'swmfactboxheadbrowse');
         $text .= '<div class="smwfact">' . '<span class="smwfactboxhead">' . wfMessage('smw_factbox_head', $browselink->getWikiText())->inContentLanguage()->text() . '</span>' . '<span class="smwrdflink">' . $rdflink->getWikiText() . '</span>' . '<table class="smwfacttable">' . "\n";
         foreach ($semdata->getProperties() as $propertyDi) {
             $propertyDv = SMWDataValueFactory::newDataItemValue($propertyDi, null);
             if (!$propertyDi->isShown()) {
                 // showing this is not desired, hide
                 continue;
             } elseif ($propertyDi->isUserDefined()) {
                 // user defined property
                 $propertyDv->setCaption(preg_replace('/[ ]/u', '&#160;', $propertyDv->getWikiValue(), 2));
                 /// NOTE: the preg_replace is a slight hack to ensure that the left column does not get too narrow
                 $text .= '<tr><td class="smwpropname">' . $propertyDv->getShortWikiText(true) . '</td><td class="smwprops">';
             } elseif ($propertyDv->isVisible()) {
                 // predefined property
                 $text .= '<tr><td class="smwspecname">' . $propertyDv->getShortWikiText(true) . '</td><td class="smwspecs">';
             } else {
                 // predefined, internal property
                 continue;
             }
             $propvalues = $semdata->getPropertyValues($propertyDi);
             $valuesHtml = array();
             foreach ($propvalues as $dataItem) {
                 $dataValue = SMWDataValueFactory::newDataItemValue($dataItem, $propertyDi);
                 if ($dataValue->isValid()) {
                     $valuesHtml[] = $dataValue->getLongWikiText(true) . $dataValue->getInfolinkText(SMW_OUTPUT_WIKI);
                 }
             }
             $text .= $GLOBALS['wgLang']->listToText($valuesHtml);
             $text .= '</td></tr>';
         }
         $text .= '</table></div>';
     }
     wfProfileOut('SMWFactbox::printFactbox (SMW)');
     return $text;
 }
예제 #6
0
 /**
  * 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(SMWSemanticData $semanticData)
 {
     if ($semanticData->getSubject()->getDBkey() !== $this->getSubject()->getDBkey()) {
         return;
     }
     $subobjectName = $container->getSubject()->getSubobjectName();
     if (array_key_exists($subobjectName, $this->subSemanticData)) {
         $this->subSemanticData[$subobjectName]->removeDataFrom($semanticData);
         if ($this->subSemanticData[$subobjectName]->isEmpty()) {
             unset($this->subSemanticData[$subobjectName]);
         }
     }
 }
 /**
  * @see SMWStore::doDataUpdate
  * 
  * @param SMWSemanticData $data
  */
 public function doDataUpdate(SMWSemanticData $data)
 {
     wfProfileIn("SMWSQLStore2::updateData (SMW)");
     wfRunHooks('SMWSQLStore2::updateDataBefore', array($this, $data));
     $subject = $data->getSubject();
     $this->deleteSemanticData($subject);
     $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());
         wfProfileOut("SMWSQLStore2::updateData (SMW)");
         return;
         // Stop here -- no support for annotations on redirect pages!
     } else {
         $this->updateRedirects($subject->getDBkey(), $subject->getNamespace());
     }
     $sortkeyDataItems = $data->getPropertyValues(new SMWDIProperty('_SKEY'));
     $sortkeyDataItem = end($sortkeyDataItems);
     if ($sortkeyDataItem instanceof SMWDIString) {
         $sortkey = $sortkeyDataItem->getString();
     } else {
         // default sortkey
         $sortkey = str_replace('_', ' ', $subject->getDBkey());
     }
     // Always make an ID (pages without ID cannot be in query results, not even in fixed value queries!):
     $sid = $this->makeSMWPageID($subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName(), true, $sortkey);
     $updates = array();
     // collect data for bulk updates; format: tableid => updatearray
     $this->prepareDBUpdates($updates, $data, $sid, $subject);
     $db = wfGetDB(DB_MASTER);
     foreach ($updates as $tablename => $uvals) {
         if ($tablename != 'smw_conc2') {
             $db->insert($tablename, $uvals, "SMW::updateData{$tablename}");
         }
     }
     // Concepts are not just written but carefully updated,
     // preserving existing metadata (cache ...) for a concept:
     if ($subject->getNamespace() == SMW_NS_CONCEPT) {
         if (array_key_exists('smw_conc2', $updates) && count($updates['smw_conc2']) != 0) {
             $up_conc2 = end($updates['smw_conc2']);
             unset($up_conc2['cache_date']);
             unset($up_conc2['cache_count']);
         } else {
             $up_conc2 = array('concept_txt' => '', 'concept_docu' => '', 'concept_features' => 0, 'concept_size' => -1, 'concept_depth' => -1);
         }
         $row = $db->selectRow('smw_conc2', array('cache_date', 'cache_count'), array('s_id' => $sid), 'SMWSQLStore2Queries::updateConst2Data');
         if ($row === false && $up_conc2['concept_txt'] !== '') {
             // insert newly given data
             $up_conc2['s_id'] = $sid;
             $db->insert('smw_conc2', $up_conc2, 'SMW::updateConc2Data');
         } elseif ($row !== false) {
             // update data, preserve existing entries
             $db->update('smw_conc2', $up_conc2, array('s_id' => $sid), 'SMW::updateConc2Data');
         }
     }
     // Finally update caches (may be important if jobs are directly following this call)
     $this->m_semdata[$sid] = SMWSqlStubSemanticData::newFromSemanticData($data);
     // Everything that one can know.
     $this->m_sdstate[$sid] = array();
     foreach (self::getPropertyTables() as $tableId => $tableDeclaration) {
         $this->m_sdstate[$sid][$tableId] = true;
     }
     wfRunHooks('SMWSQLStore2::updateDataAfter', array($this, $data));
     wfProfileOut("SMWSQLStore2::updateData (SMW)");
 }
예제 #8
0
 /**
  * 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
  * @param DatabaseBase $dbr used for reading only
  * @return array
  */
 protected function preparePropertyTableInserts($sid, SMWSemanticData $data, DatabaseBase $dbr)
 {
     $updates = array();
     $subject = $data->getSubject();
     $propertyTables = SMWSQLStore3::getPropertyTables();
     foreach ($data->getProperties() as $property) {
         $tableId = SMWSQLStore3::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));
             $insertValueKey = self::makeDatabaseRowKey($insertValues);
             $updates[$propertyTable->getName()][$insertValueKey] = $insertValues;
         }
     }
     // Special handling of Concepts
     if ($subject->getNamespace() == SMW_NS_CONCEPT && $subject->getSubobjectName() == '') {
         $this->prepareConceptTableInserts($sid, $updates, $dbr);
     }
     return $updates;
 }
	private function process( SMWSemanticData $answer ) {
		$this->getResult()->addValue( array( 'smwwriteable' ), 'title', $answer->getSubject()->getWikiValue() );
		$properties = $answer->getProperties();
		foreach ( $properties as $property ) {
			$values = $answer->getPropertyValues( $property );
			$valuestrings = array();
			foreach ( $values as $value ) $valuestrings[] = $value->getWikiValue();
			$this->getResult()->setIndexedTagName( $valuestrings, 'value' );
			$this->getResult()->addValue( array( 'smwwriteable', 'properties' ), $property->getWikiValue(), $valuestrings );
		}
	}
	function smwAutoRefresh( SMWStore $store, SMWSemanticData $data ) {
		$data->getSubject()->getTitle()->invalidateCache();
		return true;
	}	
 /**
  * @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));
 }
예제 #12
0
 /**
  * This function is used for storing a SMWSemanticData Item in the Solr
  * Index
  *
  * @param SMWSemanticData $data
  */
 public function parseSemanticData(SMWSemanticData $data)
 {
     $solritem = new SolrDoc();
     $solritem->addField('pagetitle', $data->getSubject()->getTitle()->getText());
     $solritem->addField('namespace', $data->getSubject()->getNamespace());
     $solritem->addField('dbkey', $data->getSubject()->getDBkey());
     $solritem->addField('interwiki', $data->getSubject()->getInterwiki());
     $solritem->addField('subobjectname', $data->getSubject()->getSubobjectName());
     foreach ($data->getProperties() as $property) {
         if ($property->getKey() == '_SKEY' || $property->getKey() == '_REDI') {
             continue;
             // skip these here, we store them differently
         }
         $propertyName = $property->getLabel();
         foreach ($data->getPropertyValues($property) as $di) {
             if ($di instanceof SMWDIError) {
                 // error values, ignore
                 continue;
             }
             switch ($di->getDIType()) {
                 case 0:
                     //	  /// Data item ID that can be used to indicate that no data item class is appropriate
                     //	const TYPE_NOTYPE = 0;
                     break;
                 case 1:
                     //	/// Data item ID for SMWDINumber
                     //	const TYPE_NUMBER = 1;
                     $solritem->addField($propertyName . '_i', $di->getNumber());
                     $solritem->addSortField($propertyName . '_i', $di->getNumber());
                     break;
                 case 2:
                     //	/// Data item ID for SMWDIString
                     //	const TYPE_STRING = 2;
                     $solritem->addField($propertyName . '_t', $di->getString());
                     $solritem->addSortField($propertyName . '_t', $di->getString());
                     break;
                 case 3:
                     //	///  Data item ID for SMWDIBlob
                     //	const TYPE_BLOB = 3;
                     $solritem->addField($propertyName . '_t', $di->getString());
                     $solritem->addSortField($propertyName . '_t', $di->getString());
                     break;
                 case 4:
                     //	///  Data item ID for SMWDIBoolean
                     //	const TYPE_BOOLEAN = 4;
                     $solritem->addField($propertyName . '_b', $di->getBoolean());
                     $solritem->addSortField($propertyName . '_b', $di->getBoolean());
                     break;
                 case 5:
                     //	///  Data item ID for SMWDIUri
                     //	const TYPE_URI = 5;
                     $solritem->addField($propertyName . '_t', $di->getURI());
                     $solritem->addSortField($propertyName . '_t', $di->getURI());
                     break;
                 case 6:
                     //	///  Data item ID for SMWDITimePoint
                     //	const TYPE_TIME = 6;
                     $date = $di->getYear() . '-' . $di->getMonth() . '-' . $di->getDay() . 'T' . $di->getHour() . ':' . $di->getMinute() . ':' . $di->getSecond() . 'Z';
                     $solritem->addField($propertyName . '_dt', $date);
                     $solritem->addSortField($propertyName . '_dt', $date);
                     break;
                 case 7:
                     //	///  Data item ID for SMWDIGeoCoord
                     //	const TYPE_GEO = 7;
                     // TODO: Implement range Search in SOLR
                     $solritem->addField($propertyName . '_lat', $di->getLatitude());
                     $solritem->addField($propertyName . '_lng', $di->getLongitude());
                     break;
                 case 8:
                     //	///  Data item ID for SMWDIContainer
                     //	const TYPE_CONTAINER = 8
                     // TODO: What the hell is this used for?
                     $data->getSubject()->getTitle()->getText() . ' : ';
                     break;
                 case 9:
                     //	///  Data item ID for SMWDIWikiPage
                     //	const TYPE_WIKIPAGE = 9;
                     $ns = $di->getNamespace();
                     if ($ns == 0) {
                         $solritem->addField($propertyName . '_s', $di->getTitle());
                     } elseif ($ns == 14) {
                         $title = $di->getTitle();
                         $solritem->addField('category', substr($title, stripos($title, ':') + 1));
                     }
                     break;
                 case 10:
                     //	///  Data item ID for SMWDIConcept
                     //	const TYPE_CONCEPT = 10;
                     $data->getSubject()->getTitle()->getText() . ' : ';
                     break;
                 case 11:
                     //	///  Data item ID for SMWDIProperty
                     //	const TYPE_PROPERTY = 11;
                     $data->getSubject()->getTitle()->getText() . ' : ';
                     break;
                 case 12:
                     //	///  Data item ID for SMWDIError
                     //	const TYPE_ERROR = 12;
                     $data->getSubject()->getTitle()->getText() . ' : ';
                     break;
                 default:
                     break;
             }
         }
     }
     $this->addDoc($solritem);
 }
예제 #13
0
 /**
  * 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;
 }
예제 #14
0
	/**
	 * Replaces the data in remove with the data in add.
	 *
	 * @param SMWSemanticData $remove Facts to be removed. If $remove is on a
	 * null title, no data will be removed. If it is a SMWSemanticData object
	 * with only the subject set but no properties given, all data of the
	 * subject will be removed and replaced with the newly added facts. If the
	 * object has properties, but the properties have a null value, all
	 * properties with a null value will loose all their values before the data
	 * in add will be added.
	 * @param SMWSemanticData $add Facts to be added.
	 * @param String $editsummary Text to be saved for edit summary
	 * @param Integer bitfield $flags 0 means no special flags,
	 * @return String if empty, the system thinks that everything went well.
	 * Otherwise a String explaining what the system thinks just happened.
	 * If a non-empty string is returned, the state of the wiki was not changed.
	 */
	public function update( SMWSemanticData $remove, SMWSemanticData $add, $editsummary, $flags = 0 ) {
		if ( !empty( $this->error ) ) return;

		if ( empty( $editsummary ) ) $editsummary = "Changed by calling SMWWriter::Update"; // TODO make this more intelligent
		$this->editsummary = $editsummary;
		$this->flags = $flags;

		if ( !$this->checkSubject( $remove->getSubject()->getTitle(), $add->getSubject()->getTitle() ) ) {
			$this->addError( "Not fitting subjects in add or remove." ); return;
		}

		$this->normalizeRequest( $remove, $add );

		if ( empty( $this->error ) ) $this->doUpdate();
	}
예제 #15
0
 /**
  * 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;
 }
예제 #16
0
 /**
  * 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;
 }
 /**
  * @see SMWStore::doDataUpdate
  *
  * @param SMWSemanticData $data
  */
 public function doDataUpdate(SMWSemanticData $data)
 {
     wfProfileIn("SMWSQLStore3::updateData (SMW)");
     wfRunHooks('SMWSQLStore3::updateDataBefore', array($this->store, $data));
     $subject = $data->getSubject();
     $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());
         wfProfileOut("SMWSQLStore3::updateData (SMW)");
         return;
         // Stop here -- no support for annotations on redirect pages!
     } else {
         $this->updateRedirects($subject->getDBkey(), $subject->getNamespace());
     }
     $sortkeyDataItems = $data->getPropertyValues(new SMWDIProperty('_SKEY'));
     $sortkeyDataItem = end($sortkeyDataItems);
     if ($sortkeyDataItem instanceof SMWDIString) {
         $sortkey = $sortkeyDataItem->getString();
     } else {
         // default sortkey
         $sortkey = str_replace('_', ' ', $subject->getDBkey());
     }
     // Always make an ID (pages without ID cannot be in query results, not even in fixed value queries!):
     $sid = $this->store->smwIds->makeSMWPageID($subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName(), true, $sortkey, true);
     if ($subject->getSubobjectName() == '') {
         $this->updateSubSemanticData($data);
     }
     $updates = array();
     // collect data for bulk updates; format: tableid => updatearray
     $this->prepareDBUpdates($updates, $data, $sid, $subject);
     $db = wfGetDB(DB_MASTER);
     $oldHashes = $this->store->smwIds->getPropertyTableHashes($sid);
     $hashIsChanged = false;
     //old SemanticData container for this subject (This will only hold Semantic data that will be deleted)
     $oldData = new SMWSql3StubSemanticData($subject, $this->store, false);
     //new SemanticData container for this subject (This will only hold Semantic data that will be newly added)
     $newData = new SMWSql3StubSemanticData($subject, $this->store, false);
     //tables into which data has been changed or added (not considering the ones where data is only deleted)
     $modifiedTables = array();
     foreach (SMWSQLStore3::getPropertyTables() as $tableId => $tableDeclaration) {
         $tableName = $tableDeclaration->name;
         if ($tableName == 'smw_fpt_redi') {
             // TODO - handle these for updating property counts
             continue;
             //smw_fpt_redi are not considered here.
         }
         if (array_key_exists($tableName, $updates)) {
             $newHash = md5(serialize($updates[$tableName]));
             if (array_key_exists($tableName, $oldHashes) && $newHash == $oldHashes[$tableName]) {
                 //table was used before and value didn't change, nothing to do here
                 continue;
             } else {
                 //data didn't exist before or has changed
                 $this->store->getReader()->addTableSemanticData($sid, $oldData, $tableDeclaration);
                 // Add data for this table
                 // Concepts are not just written but carefully updated,
                 // preserving existing metadata (cache ...) for a concept:
                 if ($tableName == 'smw_fpt_conc') {
                     $row = $db->selectRow('smw_fpt_conc', array('cache_date', 'cache_count'), array('s_id' => $sid), 'SMWSQLStoreQueries::updateConcData');
                     if ($row === false && $updates['smw_fpt_conc']['concept_txt'] !== '') {
                         // insert newly given data
                         $db->insert('smw_fpt_conc', $updates['smw_fpt_conc'], 'SMW::updateConcData');
                     } elseif ($row !== false) {
                         // update data, preserve existing entries
                         $db->update('smw_fpt_conc', $updates['smw_fpt_conc'], array('s_id' => $sid), 'SMW::updateConcData');
                     }
                 } else {
                     $this->deleteTableSemanticData($sid, $tableDeclaration);
                     $db->insert($tableName, $updates[$tableName], "SMW::updateData{$tableName}");
                 }
                 $oldHashes[$tableName] = $newHash;
                 $hashIsChanged = true;
                 $modifiedTables[$tableId] = $tableDeclaration;
             }
         } elseif (array_key_exists($tableName, $oldHashes)) {
             //data existed before but not now (Concepts data is not deleted here)
             $this->store->getReader()->addTableSemanticData($sid, $oldData, $tableDeclaration);
             // Add data for this table
             $this->deleteTableSemanticData($sid, $tableDeclaration);
             unset($oldHashes[$tableName]);
             $hashIsChanged = true;
         }
     }
     if ($hashIsChanged) {
         $this->store->smwIds->setPropertyTableHashes($sid, $oldHashes);
     }
     // Finally update caches (may be important if jobs are directly following this call)
     $this->store->m_semdata[$sid] = SMWSql3StubSemanticData::newFromSemanticData($data, $this->store);
     // Everything that one can know.
     $this->store->m_sdstate[$sid] = array();
     foreach (SMWSQLStore3::getPropertyTables() as $tableId => $tableDeclaration) {
         $this->store->m_sdstate[$sid][$tableId] = true;
     }
     //Add newly added property-values to $newData
     //and remove property-values that hasn't been modified from $oldData
     foreach ($data->getProperties() as $propKey => $diProp) {
         $propTable = $this->store->findPropertyTableID($diProp);
         if (!array_key_exists($propTable, $modifiedTables)) {
             continue;
             //Properties in these table have been taken care of already
         }
         $dataPropVals = $data->getPropertyValues($diProp);
         //remove common property-values from $oldData and add new ones to $newData
         $oldPropVals = $oldData->getPropertyValues($diProp);
         foreach ($dataPropVals as $di) {
             if (in_array($di, $oldPropVals)) {
                 $oldData->removePropertyObjectValue($diProp, $di);
             } else {
                 $newData->addPropertyObjectValue($diProp, $di);
             }
         }
     }
     $this->doDiffandUpdateCount($oldData, $newData);
     wfRunHooks('SMWSQLStore3::updateDataAfter', array($this->store, $data));
     wfProfileOut("SMWSQLStore3::updateData (SMW)");
 }
 /**
  * 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;
 }
 /**
  * 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();
     if ($this->store->canUseUpdateFeature(SMW_TRX_UPDATE)) {
         $this->store->getConnection()->beginTransaction(__METHOD__);
     }
     // 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
         $this->store->getConnection()->commitTransaction(__METHOD__);
         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 = $subject->getSortKey();
     }
     // #649 Be consistent about how sortkeys are stored therefore always
     // normalize even for usages like {{DEFAULTSORT: Foo_bar }}
     $sortkey = str_replace('_', ' ', $sortkey);
     // 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->propertyTableRowDiffer->computeTableRowDiffFor($sid, $data);
     $this->writePropertyTableUpdates($sid, $deleteRows, $insertRows, $newHashes);
     if ($redirects === array() && $subject->getSubobjectName() === '') {
         $dataItemFromId = $this->store->getObjectIds()->getDataItemForId($sid);
         // If for some reason the internal redirect marker is still set but no
         // redirect annotations are known then do update the interwiki field
         if ($dataItemFromId !== null && $dataItemFromId->getInterwiki() === SMW_SQL3_SMWREDIIW) {
             $this->store->getObjectIds()->updateInterwikiField($sid, $subject);
         }
     }
     // Update caches (may be important if jobs are directly following this call)
     $this->setSemanticDataCache($sid, $data);
     $this->store->getConnection()->commitTransaction(__METHOD__);
     // 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).
 }
예제 #20
0
 /**
  * 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;
 }
예제 #21
0
 public function doDataUpdate(SMWSemanticData $data)
 {
     wfProfileIn("SMWSQLStoreLight::updateData (SMW)");
     wfRunHooks('SMWSQLStoreLight::updateDataBefore', array($this, $data));
     $subject = $data->getSubject();
     $this->deleteSemanticData($subject);
     $sid = $subject->getTitle()->getArticleID();
     $updates = array();
     // collect data for bulk updates; format: tableid => updatearray
     foreach ($data->getProperties() as $property) {
         $tablename = SMWSQLStoreLight::findPropertyTableName($property);
         if ($tablename === '') {
             continue;
         }
         foreach ($data->getPropertyValues($property) as $dv) {
             if (!$dv->isValid()) {
                 continue;
             }
             if ($dv instanceof SMWContainerValue) {
                 continue;
                 // subobjects not supported in this store right now; maybe could simply be PHP serialized
             } else {
                 $uvals = array('pageid' => $sid, 'propname' => $property->getDBkey(), 'value' => $tablename == 'smwsimple_special' ? reset($dv->getDBkeys()) : serialize($dv->getDBkeys()));
             }
             if (!array_key_exists($tablename, $updates)) {
                 $updates[$tablename] = array();
             }
             $updates[$tablename][] = $uvals;
         }
     }
     $db = wfGetDB(DB_MASTER);
     foreach ($updates as $tablename => $uvals) {
         $db->insert($tablename, $uvals, "SMW::updateData{$tablename}");
     }
     // Finally update caches (may be important if jobs are directly following this call)
     $this->m_semdata[$sid] = clone $data;
     $this->m_sdstate[$sid] = array('smwsimple_data' => true, 'smwsimple_special' => true);
     // everything that one can know
     wfRunHooks('SMWSQLStoreLight::updateDataAfter', array($this, $data));
     wfProfileOut("SMWSQLStoreLight::updateData (SMW)");
 }
 /**
  * Creates and returns a new SMWChangeSet from 2 SMWSemanticData objects.
  * 
  * @param SMWSemanticData $old
  * @param SMWSemanticData $new
  * @param array $filterProperties Optional list of properties (string serializations) to filter on. Null for no filtering.
  * 
  * @return SMWChangeSet
  */
 public static function newFromSemanticData(SMWSemanticData $old, SMWSemanticData $new, array $filterProperties = null)
 {
     $subject = $old->getSubject();
     if ($subject != $new->getSubject()) {
         return new self($subject);
     }
     $changes = new SWLPropertyChanges();
     $insertions = new SMWSemanticData($subject);
     $deletions = new SMWSemanticData($subject);
     $oldProperties = array();
     $newProperties = array();
     foreach ($old->getProperties() as $property) {
         if (is_null($filterProperties) || in_array($property->getLabel(), $filterProperties)) {
             $oldProperties[] = $property;
         }
     }
     foreach ($new->getProperties() as $property) {
         if (is_null($filterProperties) || in_array($property->getLabel(), $filterProperties)) {
             $newProperties[] = $property;
         }
     }
     // Find the deletions.
     self::findSingleDirectionChanges($deletions, $oldProperties, $old, $newProperties, $filterProperties);
     // Find the insertions.
     self::findSingleDirectionChanges($insertions, $newProperties, $new, $oldProperties, $filterProperties);
     foreach ($oldProperties as $propertyKey => $diProperty) {
         $oldDataItems = array();
         $newDataItems = array();
         // Populate the data item arrays using keys that are their hash, so matches can be found.
         // Note: this code assumes there are no duplicates.
         foreach ($old->getPropertyValues($diProperty) as $dataItem) {
             $oldDataItems[$dataItem->getHash()] = $dataItem;
         }
         foreach ($new->getPropertyValues($diProperty) as $dataItem) {
             $newDataItems[$dataItem->getHash()] = $dataItem;
         }
         $foundMatches = array();
         // Find values that are both in the old and new version.
         foreach (array_keys($oldDataItems) as $hash) {
             if (array_key_exists($hash, $newDataItems)) {
                 $foundMatches[] = $hash;
             }
         }
         // Remove the values occuring in both sets, so only changes remain.
         foreach ($foundMatches as $foundMatch) {
             unset($oldDataItems[$foundMatch]);
             unset($newDataItems[$foundMatch]);
         }
         // Find which group is biggest, so it's easy to loop over all values of the smallest.
         $oldIsBigger = count($oldDataItems) > count($newDataItems);
         $bigGroup = $oldIsBigger ? $oldDataItems : $newDataItems;
         $smallGroup = $oldIsBigger ? $newDataItems : $oldDataItems;
         // Add all one-to-one changes.
         while ($dataItem = array_shift($smallGroup)) {
             $changes->addPropertyObjectChange($diProperty, new SWLPropertyChange($dataItem, array_shift($bigGroup)));
         }
         // If the bigger group is not-equal to the smaller one, items will be left,
         // that are either insertions or deletions, depending on the group.
         if (count($bigGroup > 0)) {
             $semanticData = $oldIsBigger ? $deletions : $insertions;
             foreach ($bigGroup as $dataItem) {
                 $semanticData->addPropertyObjectValue($diProperty, $dataItem);
             }
         }
     }
     return new self($subject, $changes, $insertions, $deletions);
 }
예제 #23
0
/**
 * Callback function for the hook 'smwShowFactbox'. It is called when SMW creates
 * the factbox for an article.
 * This method replaces the whole factbox with a tabbed version that contains
 * the original factbox in one tab and the derived facts in another.
 *
 * @param string $text
 * 		The HTML for the tabbed factbox is returned in this parameter
 * @param SMWSemanticData $semdata
 * 		All static facts for the article
 * @return bool
 * 		<false> : This means that SMW's factbox is completely replaced.
 */
function smwfAddDerivedFacts(&$text, $semdata)
{
    global $smwgHaloScriptPath, $wgContLang;
    wfLoadExtensionMessages('SemanticMediaWiki');
    SMWOutputs::requireHeadItem(SMW_HEADER_STYLE);
    $rdflink = SMWInfolink::newInternalLink(wfMsgForContent('smw_viewasrdf'), $wgContLang->getNsText(NS_SPECIAL) . ':ExportRDF/' . $semdata->getSubject()->getWikiValue(), 'rdflink');
    $browselink = SMWInfolink::newBrowsingLink($semdata->getSubject()->getText(), $semdata->getSubject()->getWikiValue(), 'swmfactboxheadbrowse');
    $fbText = '<div class="smwfact">' . '<span class="smwfactboxhead">' . wfMsgForContent('smw_factbox_head', $browselink->getWikiText()) . '</span>' . '<span class="smwrdflink">' . $rdflink->getWikiText() . '</span>' . '<table class="smwfacttable">' . "\n";
    foreach ($semdata->getProperties() as $property) {
        if (!$property->isShown()) {
            // showing this is not desired, hide
            continue;
        } elseif ($property->isUserDefined()) {
            // user defined property
            $property->setCaption(preg_replace('/[ ]/u', '&nbsp;', $property->getWikiValue(), 2));
            /// NOTE: the preg_replace is a slight hack to ensure that the left column does not get too narrow
            $fbText .= '<tr><td class="smwpropname">' . $property->getLongWikiText(true) . '</td><td class="smwprops">';
        } elseif ($property->isVisible()) {
            // predefined property
            $fbText .= '<tr><td class="smwspecname">' . $property->getLongWikiText(true) . '</td><td class="smwspecs">';
        } else {
            // predefined, internal property
            continue;
        }
        $propvalues = $semdata->getPropertyValues($property);
        $l = count($propvalues);
        $i = 0;
        foreach ($propvalues as $propvalue) {
            if ($i != 0) {
                if ($i > $l - 2) {
                    $fbText .= wfMsgForContent('smw_finallistconjunct') . ' ';
                } else {
                    $fbText .= ', ';
                }
            }
            $i += 1;
            $fbText .= $propvalue->getLongWikiText(true) . $propvalue->getInfolinkText(SMW_OUTPUT_WIKI);
        }
        $fbText .= '</td></tr>';
    }
    $fbText .= '</table></div>';
    $text = '<div id="smw_dft_rendered_boxcontent"> <br />' . '<table>' . '<tr>' . '<td id="dftTab1" class="dftTabActive">' . str_replace(' ', '&nbsp;', wfMsg('smw_df_static_tab')) . '</td>' . '<td class="dftTabSpacer">&nbsp;</td>' . '<td id="dftTab2" class="dftTabInactive">' . str_replace(' ', '&nbsp;', wfMsg('smw_df_derived_tab')) . '</td>' . '<td class="dftTabSpacer" width="100%"></td>' . '</tr>' . '<tr>' . '<td colspan="4" class="dftTabCont">' . '<div id="dftTab1Content" >' . $fbText . '</div>' . '<div id="dftTab2Content" style="display:none">' . '<div id="dftTab2ContentInnerDiv">' . wfMsg('smw_df_loading_df') . '</div>' . '</div>' . '</td>' . '</tr>' . '</table>' . '</div>';
    return false;
}