/** * 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; }
/** * 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; }
/** * Change the object to become an exact copy of the given * SMWSemanticData object. This is used to make other types of * SMWSemanticData into an SMWContainerSemanticData. To copy objects of * the same type, PHP clone() should be used. * * @since 1.7 * * @param $semanticData SMWSemanticData object to copy from */ public function copyDataFrom(SMWSemanticData $semanticData) { $this->mSubject = $semanticData->getSubject(); $this->mProperties = $semanticData->getProperties(); $this->mPropVals = array(); foreach ($this->mProperties as $property) { $this->mPropVals[$property->getKey()] = $semanticData->getPropertyValues($property); } $this->mHasVisibleProps = $semanticData->hasVisibleProperties(); $this->mHasVisibleSpecs = $semanticData->hasVisibleSpecialProperties(); $this->mNoDuplicates = $semanticData->mNoDuplicates; }
/** * This 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', ' ', $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; }
public function updateData(SMWSemanticData $data, $store) { //get list of properties which are set by this article //todo: think about only querying for modified properties $properties = $data->getProperties(); foreach ($properties as $name => $property) { //ignore internal properties if (!$property->isUserDefined() || $name == QRC_HQID_LABEL) { unset($properties[$name]); } } //determine differences between the new and the original semantic data global $wgTitle; if ($wgTitle) { $originalData = $store->getSemanticData($wgTitle); foreach ($originalData->getProperties() as $oName => $oProperty) { if (array_key_exists($oName, $properties)) { $oValues = $originalData->getPropertyValues($oProperty); $values = $data->getPropertyValues($properties[$oName]); if (count($oValues) == count($values)) { $oWikiValues = array(); foreach ($oValues as $key => $value) { $oWikiValues[$value->getWikiValue()] = true; } $wikiValues = array(); foreach ($values as $key => $value) { $wikiValues[$value->getWikiValue()] = true; } $unset = true; foreach (array_keys($values) as $value) { if (!array_key_exists($value, $oWikiValues)) { $unset = false; break; } } if ($unset) { unset($properties[$oName]); } } //echo('<pre>'.print_r($oProperty, true).'</pre>'); //echo('<pre>'.print_r(, true).'</pre>'); } else { if ($oProperty->isUserDefined() && $name != QRC_HQID_LABEL) { $properties[$oName] = $oProperty; } } } } //deal with categories and determine which queries to update $categories = array(); global $wgParser; if ($wgParser && $wgParser->getOutput() && $wgTitle) { $categories = $wgParser->getOutput()->getCategories(); $originalCategories = $wgTitle->getParentCategories(); //echo('<pre>'.print_r($originalCategories, true).'</pre>'); foreach (array_keys($originalCategories) as $category) { $category = substr($category, strpos($category, ':') + 1); if (array_key_exists($category, $categories)) { unset($categories[$category]); } else { $categories[$category] = true; } } } //echo('<pre>'.print_r(array_keys($categories), true).'</pre>'); //echo('<pre>'.print_r(array_keys($properties), true).'</pre>'); if (count($properties) > 0 || count($categories) > 0) { //query for all articles that use a query which depends on one of the properties $queryString = SMWQRCQueryManagementHandler::getInstance()->getSearchQueriesAffectedByDataModification(array_keys($properties), array_keys($categories)); SMWQueryProcessor::processFunctionParams(array($queryString), $queryString, $params, $printouts); $query = SMWQueryProcessor::createQuery($queryString, $params); $queryResults = $this->getQueryResult($query, true, false)->getResults(); //get query ids which have to be invalidated $queryIds = array(); foreach ($queryResults as $queryResult) { $semanticData = $store->getSemanticData($queryResult); $invalidatePC = false; $tQueryIds = SMWQRCQueryManagementHandler::getInstance()->getIdsOfQueriesUsingProperty($semanticData, $properties); if (count($tQueryIds) > 0) { $invalidatePC = true; } $queryIds = array_merge($queryIds, $tQueryIds); $tQueryIds = SMWQRCQueryManagementHandler::getInstance()->getIdsOfQueriesUsingCategory($semanticData, $categories); if (count($tQueryIds) > 0) { $invalidatePC = true; } $queryIds = array_merge($queryIds, $tQueryIds); global $invalidateParserCache, $showInvalidatedCacheEntries; if ($invalidatePC && $invalidateParserCache && !$showInvalidatedCacheEntries) { $title = $queryResult->getTitle(); $title->invalidateCache(); } } $qrcStore = SMWQRCStore::getInstance()->getDB(); $qrcStore->invalidateQueryData($queryIds); } return $store->doUpdateData($data); }
/** * Removes data from the given SMWSemanticData. * If the subject of the data that is to be removed is not equal to the * subject of this SMWSemanticData, it will just be ignored (nothing to * remove). Likewise, removing data that is not present does not change * anything. * * @since 1.8 * * @param $semanticData SMWSemanticData */ public function removeDataFrom(SMWSemanticData $semanticData) { if (!$this->mSubject->equals($semanticData->getSubject())) { return; } foreach ($semanticData->getProperties() as $property) { $values = $semanticData->getPropertyValues($property); foreach ($values as $dataItem) { $this->removePropertyObjectValue($property, $dataItem); } } foreach ($semanticData->getSubSemanticData() as $semData) { $this->removeSubSemanticData($semData); } }
/** * Get the array of all properties that have stored values. * * @return array of SMWDIProperty objects */ public function getProperties() { $this->unstubProperties(); return parent::getProperties(); }
/** * Extend the given update array to account for the data in the * SMWSemanticData object. The subject page of the data container is * ignored, and the given $sid (subject page id) is used directly. If * this ID is 0, then $subject is used to find an ID. This is usually * the case for all internal objects that are created in writing * container values. * * The function returns the id that was used for writing. Especially, * any newly created internal id is returned. * * @param $updates array * @param $data SMWSemanticData * @param $sid integer pre-computed id if available or 0 if ID should be sought * @param $subject SMWDIWikiPage subject to which the data refers */ protected function prepareDBUpdates(&$updates, SMWSemanticData $data, $sid, SMWDIWikiPage $subject) { $subSemanticData = $data->getSubSemanticData(); if ($sid == 0) { $sid = $this->makeSMWPageID($subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName(), true, str_replace('_', ' ', $subject->getDBkey()) . $subject->getSubobjectName()); } $proptables = self::getPropertyTables(); foreach ($data->getProperties() as $property) { if ($property->getKey() == '_SKEY' || $property->getKey() == '_REDI') { continue; // skip these here, we store them differently } $tableid = self::findPropertyTableID($property); $proptable = $proptables[$tableid]; foreach ($data->getPropertyValues($property) as $di) { if ($di instanceof SMWDIError) { // error values, ignore continue; } // redirects were treated above // To support compatibility with the new handling of Subobjects if ($di->getDIType() == SMWDataItem::TYPE_WIKIPAGE && array_key_exists($di->getSubobjectName(), $subSemanticData)) { $di = new SMWDIContainer($subSemanticData[$di->getSubobjectName()]); } ///TODO check needed if subject is null (would happen if a user defined proptable with !idsubject was used on an internal object -- currently this is not possible $uvals = $proptable->idsubject ? array('s_id' => $sid) : array('s_title' => $subject->getDBkey(), 's_namespace' => $subject->getNamespace()); if ($proptable->fixedproperty == false) { $uvals['p_id'] = $this->makeSMWPropertyID($property); } if ($di instanceof SMWDIContainer) { // process subobjects recursively $subObject = $di->getSemanticData()->getSubject(); $subObjectId = $this->prepareDBUpdates($updates, $di->getSemanticData(), 0, $subObject); // Note: tables for container objects MUST have objectfields == array(<somename> => 'p') reset($proptable->objectfields); $uvals[key($proptable->objectfields)] = $subObjectId; } else { $dbkeys = SMWCompatibilityHelpers::getDBkeysFromDataItem($di); reset($dbkeys); foreach ($proptable->objectfields as $fieldname => $typeid) { if ($typeid != 'p') { $uvals[$fieldname] = current($dbkeys); } else { $uvals[$fieldname] = $this->makeSMWPageID($di->getDBkey(), $di->getNamespace(), $di->getInterwiki(), $di->getSubobjectName()); } next($dbkeys); } } if (!array_key_exists($proptable->name, $updates)) { $updates[$proptable->name] = array(); } $updates[$proptable->name][] = $uvals; } } return $sid; }
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 ); } }
/** * Extend the given update array to account for the data in the * SMWSemanticData object. The subject page of the data container is * ignored, and the given $sid (subject page id) is used directly. If * this ID is 0, then $subject is used to find an ID. This is usually * the case for all internal objects (subobjects) that are created in * writing sub-SemanticData. * * The function returns the id that was used for writing. Especially, * any newly created internal id is returned. * * @param $updates array * @param $data SMWSemanticData * @param $sid integer pre-computed id if available or 0 if ID should be sought * @param $subject SMWDIWikiPage subject to which the data refers */ protected function prepareDBUpdates(&$updates, SMWSemanticData $data, $sid, SMWDIWikiPage $subject) { if ($sid == 0) { $sid = $this->store->smwIds->makeSMWPageID($subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName(), true, str_replace('_', ' ', $subject->getDBkey()) . $subject->getSubobjectName()); } $proptables = SMWSQLStore3::getPropertyTables(); foreach ($data->getProperties() as $property) { if ($property->getKey() == '_SKEY' || $property->getKey() == '_REDI') { continue; // skip these here, we store them differently } $tableid = SMWSQLStore3::findPropertyTableID($property); $proptable = $proptables[$tableid]; ///TODO check needed if subject is null (would happen if a user defined proptable with !idsubject was used on an internal object -- currently this is not possible $uvals = $proptable->idsubject ? array('s_id' => $sid) : array('s_title' => $subject->getDBkey(), 's_namespace' => $subject->getNamespace()); if ($proptable->fixedproperty == false) { $uvals['p_id'] = $this->store->smwIds->makeSMWPropertyID($property); } foreach ($data->getPropertyValues($property) as $di) { if ($di instanceof SMWDIError) { // error values, ignore continue; } $diHandler = $this->store->getDataItemHandlerForDIType($di->getDIType()); $uvals = array_merge($uvals, $diHandler->getInsertValues($di)); if (!array_key_exists($proptable->name, $updates)) { $updates[$proptable->name] = array(); } $updates[$proptable->name][] = $uvals; } } // Special handling of Concepts if ($subject->getNamespace() == SMW_NS_CONCEPT && $subject->getSubobjectName() == '') { if (array_key_exists('smw_fpt_conc', $updates) && count($updates['smw_fpt_conc']) != 0) { $updates['smw_fpt_conc'] = end($updates['smw_fpt_conc']); unset($updates['smw_fpt_conc']['cache_date']); unset($updates['smw_fpt_conc']['cache_count']); } else { $updates['smw_fpt_conc'] = array('concept_txt' => '', 'concept_docu' => '', 'concept_features' => 0, 'concept_size' => -1, 'concept_depth' => -1); } } return $sid; }
/** * 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); }
/** * 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; }
/** * Takes the request and turns requests like ***, s** and sp* into actual * remove and add requests which are saved in this objects remove and add * value. * * @param SMWSemanticData $remove All the facts meant to be removed * @param SMWSemanticData $add All the facts meant to be added */ private function normalizeRequest( SMWSemanticData $remove, SMWSemanticData $add ) { $this->initCurrent(); $this->initUpdateable(); $this->initFixed(); // if remove = ***, then nothing needs to be removed if ( $this->nosubject ) { $this->remove = new SMWWriterData(); $this->add = new SMWWriterData(); $this->add->copySemanticData( $add ); // for each spv in a : $propertiesAdd = $this->add->getPropertynames(); foreach ( $propertiesAdd as $propertyname ) { $values = $this->add->getPropertyValues( $propertyname ); foreach ( $values as $value ) { // if spv in current : a -= spv if ( $this->current->contains( $propertyname, $value ) ) $this->add->removePropertynameValue( $propertyname, $value ); } } return; } // rr = requested to remove and removable $rr = new SMWWriterData(); // rc = requested to remove but constant $rc = new SMWWriterData(); // rx = requested to remove but not existent $rx = new SMWWriterData(); // if remove = s** if ( count( $remove->getProperties() ) == 0 ) { $rr->copy( $this->updateable ); $rc->copy( $this->fixed ); } else { $properties = $remove->getProperties(); foreach ( $properties as $property ) { if ( !$property->isUserDefined() ) continue; $propertyname = $property->getWikiValue(); $values = $remove->getPropertyValues( $property ); // is sp*? $vals = $values; foreach ( $values as $value ) { if ( count( $values ) > 1 ) break; $hash = $value->getHash(); if ( empty( $hash ) ) $vals = $this->current->getPropertyValues( $property ); } // and spo foreach ( $vals as $value ) if ( $this->updateable->contains( $propertyname, $value ) ) $rr->addPropertyValue( $property, $value ); elseif ( $this->fixed->contains( $propertyname, $value ) ) $rc->addPropertyValue( $property, $value ); else $rx->addPropertyValue( $property, $value ); } } // a = what to add $a = new SMWWriterData(); $a->copySemanticData( $add ); // if ATOM and rx not empty : raise error if ( ( $this->flags & SMWWriter::ATOMIC_CHANGE ) && ( count( $rx->getPropertynames() ) > 0 ) ) { $this->addError( "There is metadata that was asked to be removed, but does not exist." ); return; } // for each spv in a : $propertiesAdd = $a->getPropertynames(); foreach ( $propertiesAdd as $propertyname ) { $values = $a->getPropertyValues( $propertyname ); foreach ( $values as $value ) { // if spv in rr : rr -= spv, a -= spv if ( $rr->contains( $propertyname, $value ) ) { $rr->removePropertynameValue( $propertyname, $value ); $a->removePropertynameValue( $propertyname, $value ); } // if spv in rc : rc -= spv, a -= spv if ( $rc->contains( $propertyname, $value ) ) { $rc->removePropertynameValue( $propertyname, $value ); $a->removePropertynameValue( $propertyname, $value ); } // if spv in current : a -= spv if ( $this->current->contains( $propertyname, $value ) ) $a->removePropertynameValue( $propertyname, $value ); } } // if ATOM and not CONSTIGNORE and rc not empty : raise error if ( ( $this->flags & SMWWriter::ATOMIC_CHANGE ) && !( $this->flags & SMWWriter::IGNORE_CONSTANT ) && ( count( $rc->getPropertynames() ) > 0 ) ) { $this->addError( "There is metadata that was asked to be removed, but cannot be removed." ); return; } $this->add = $a; $this->remove = $rr; }
/** * 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; }
/** * Add all data from the given SMWSemanticData. * * @since 1.7 * * @param $semanticData SMWSemanticData object to copy from */ public function importDataFrom(SMWSemanticData $semanticData) { // Shortcut when copying into empty objects that don't ask for more duplicate elimination: if (count($this->mProperties) == 0 && $semanticData->mNoDuplicates >= $this->mNoDuplicates) { $this->mProperties = $semanticData->getProperties(); $this->mPropVals = array(); foreach ($this->mProperties as $property) { $this->mPropVals[$property->getKey()] = $semanticData->getPropertyValues($property); } $this->mHasVisibleProps = $semanticData->hasVisibleProperties(); $this->mHasVisibleSpecs = $semanticData->hasVisibleSpecialProperties(); } else { foreach ($semanticData->getProperties() as $property) { $values = $semanticData->getPropertyValues($property); foreach ($values as $dataItem) { $this->addPropertyObjectValue($property, $dataItem); } } } }
/** * Creates the HTML table displaying the data of one subject. * * @param[in] $data SMWSemanticData The data to be displayed * @param[in] $left bool Should properties be displayed on the left side? * @param[in] $incoming bool Is this an incoming? Or an outgoing? * * @return A string containing the HTML with the factbox */ private function displayData( SMWSemanticData $data, $left = true, $incoming = false ) { // Some of the CSS classes are different for the left or the right side. // In this case, there is an "i" after the "smwb-". This is set here. $ccsPrefix = $left ? 'smwb-' : 'smwb-i'; $html = "<table class=\"{$ccsPrefix}factbox\" cellpadding=\"0\" cellspacing=\"0\">\n"; $diProperties = $data->getProperties(); $noresult = true; foreach ( $diProperties as $diProperty ) { $dvProperty = SMWDataValueFactory::newDataItemValue( $diProperty, null ); if ( $dvProperty->isVisible() ) { $dvProperty->setCaption( $this->getPropertyLabel( $dvProperty, $incoming ) ); $proptext = $dvProperty->getShortHTMLText( smwfGetLinker() ) . "\n"; } elseif ( $diProperty->getKey() == '_INST' ) { $proptext = smwfGetLinker()->specialLink( 'Categories' ); } elseif ( $diProperty->getKey() == '_REDI' ) { $proptext = smwfGetLinker()->specialLink( 'Listredirects', 'isredirect' ); } else { continue; // skip this line } $head = "<th>" . $proptext . "</th>\n"; $body = "<td>\n"; $values = $data->getPropertyValues( $diProperty ); if ( $incoming && ( count( $values ) >= SMWSpecialBrowse::$incomingvaluescount ) ) { $moreIncoming = true; array_pop( $values ); } else { $moreIncoming = false; } $first = true; foreach ( $values as $di ) { if ( $first ) { $first = false; } else { $body .= ', '; } if ( $incoming ) { $dv = SMWDataValueFactory::newDataItemValue( $di, null ); } else { $dv = SMWDataValueFactory::newDataItemValue( $di, $diProperty ); } $body .= "<span class=\"{$ccsPrefix}value\">" . $this->displayValue( $dvProperty, $dv, $incoming ) . "</span>\n"; } if ( $moreIncoming ) { // link to the remaining incoming pages: $body .= Html::element( 'a', array( 'href' => SpecialPage::getSafeTitleFor( 'SearchByProperty' )->getLocalURL( array( 'property' => $dvProperty->getWikiValue(), 'value' => $this->subject->getWikiValue() ) ) ), wfMsg( "smw_browse_more" ) ); } $body .= "</td>\n"; // display row $html .= "<tr class=\"{$ccsPrefix}propvalue\">\n" . ( $left ? ( $head . $body ):( $body . $head ) ) . "</tr>\n"; $noresult = false; } // end foreach properties if ( $noresult ) { $html .= "<tr class=\"smwb-propvalue\"><th>   </th><td><em>" . wfMsg( $incoming ? 'smw_browse_no_incoming':'smw_browse_no_outgoing' ) . "</em></td></tr>\n"; } $html .= "</table>\n"; return $html; }
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); }
/** * 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', ' ', $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(' ', ' ', wfMsg('smw_df_static_tab')) . '</td>' . '<td class="dftTabSpacer"> </td>' . '<td id="dftTab2" class="dftTabInactive">' . str_replace(' ', ' ', 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; }