/** * Constructor for a single indi in the file. */ public function __construct(SMWDIWikiPage $page) { $values = array(); $storage = smwfGetStore(); $this->page = $page; $this->title = $page->getTitle(); $properties = SemanticGenealogy::getProperties(); foreach ($properties as $key => $prop) { $values = $storage->getPropertyValues($page, $prop); if (count($values) != 0 && property_exists('PersonPageValues', $key)) { $this->{$key} = $values[0]; } } if (!$this->fullname instanceof SMWDIBlob) { if ($this->surname instanceof SMWDIBlob && $this->surname->getString() != '') { $fullname = ''; if ($this->givenname instanceof SMWDIBlob) { $fullname .= $this->givenname->getString() . ' '; } $this->fullname = new SMWDIBlob($fullname . $this->surname->getString()); } else { $this->fullname = new SMWDIBlob($this->title->getText()); } } }
public function changeTitle( Title $oldtitle, Title $newtitle, $pageid, $redirid = 0 ) { $oldWikiPage = SMWDIWikiPage::newFromTitle( $oldtitle ); $newWikiPage = SMWDIWikiPage::newFromTitle( $newtitle ); $oldExpResource = SMWExporter::getDataItemExpElement( $oldWikiPage ); $newExpResource = SMWExporter::getDataItemExpElement( $newWikiPage ); $namespaces = array( $oldExpResource->getNamespaceId() => $oldExpResource->getNamespace() ); $namespaces[$newExpResource->getNamespaceId()] = $newExpResource->getNamespace(); $oldUri = SMWTurtleSerializer::getTurtleNameForExpElement( $oldExpResource ); $newUri = SMWTurtleSerializer::getTurtleNameForExpElement( $newExpResource ); parent::changeTitle( $oldtitle, $newtitle, $pageid, $redirid ); // do this only here, so Imported from is not moved too early $sparqlDatabase = smwfGetSparqlDatabase(); $sparqlDatabase->insertDelete( "?s ?p $newUri", "?s ?p $oldUri", "?s ?p $oldUri", $namespaces ); if ( $oldtitle->getNamespace() == SMW_NS_PROPERTY ) { $sparqlDatabase->insertDelete( "?s $newUri ?o", "?s $oldUri ?o", "?s $oldUri ?o", $namespaces ); } // Note that we cannot change oldUri to newUri in triple subjects, // since some triples change due to the move. Use SMWUpdateJob. $newUpdate = new SMWUpdateJob( $newtitle ); $newUpdate->run(); if ( $redirid != 0 ) { // update/create redirect page data $oldUpdate = new SMWUpdateJob( $oldtitle ); $oldUpdate->run(); } }
/** * This method will be called before an article is displayed or previewed. * For display and preview we strip out the semantic properties and append them * at the end of the article. * * @param Parser $parser * @param string $text */ static public function onInternalParseBeforeLinks( &$parser, &$text ) { global $smwgStoreAnnotations, $smwgLinksInValues; SMWParseData::stripMagicWords( $text, $parser ); // Store the results if enabled (we have to parse them in any case, // in order to clean the wiki source for further processing). $smwgStoreAnnotations = smwfIsSemanticsProcessed( $parser->getTitle()->getNamespace() ); SMWParserExtensions::$mTempStoreAnnotations = true; // used for [[SMW::on]] and [[SMW:off]] // Process redirects, if any (it seems that there is indeed no more direct way of getting this info from MW) if ( $smwgStoreAnnotations ) { $rt = Title::newFromRedirect( $text ); if ( !is_null( $rt ) ) { $p = new SMWDIProperty( '_REDI' ); $di = SMWDIWikiPage::newFromTitle( $rt, '__red' ); SMWParseData::getSMWData( $parser )->addPropertyObjectValue( $p, $di ); } } // only used in subsequent callbacks, forgotten afterwards SMWParserExtensions::$mTempParser = $parser; // In the regexp matches below, leading ':' escapes the markup, as known for Categories. // Parse links to extract semantic properties. if ( $smwgLinksInValues ) { // More complex regexp -- lib PCRE may cause segfaults if text is long :-( $semanticLinkPattern = '/\[\[ # Beginning of the link (?:([^:][^]]*):[=:])+ # Property name (or a list of those) ( # After that: (?:[^|\[\]] # either normal text (without |, [ or ]) |\[\[[^]]*\]\] # or a [[link]] |\[[^]]*\] # or an [external link] )*) # all this zero or more times (?:\|([^]]*))? # Display text (like "text" in [[link|text]]), optional \]\] # End of link /xu'; $text = preg_replace_callback( $semanticLinkPattern, array( 'SMWParserExtensions', 'parsePropertiesCallback' ), $text ); } else { // Simpler regexps -- no segfaults found for those, but no links in values. $semanticLinkPattern = '/\[\[ # Beginning of the link (?:([^:][^]]*):[=:])+ # Property name (or a list of those) ([^\[\]]*) # content: anything but [, |, ] \]\] # End of link /xu'; $text = preg_replace_callback( $semanticLinkPattern, array( 'SMWParserExtensions', 'simpleParsePropertiesCallback' ), $text ); } // Add link to RDF to HTML header. // TODO: do escaping via Html or Xml class. SMWOutputs::requireHeadItem( 'smw_rdf', '<link rel="alternate" type="application/rdf+xml" title="' . htmlspecialchars( $parser->getTitle()->getPrefixedText() ) . '" href="' . htmlspecialchars( SpecialPage::getTitleFor( 'ExportRDF', $parser->getTitle()->getPrefixedText() )->getLocalUrl( 'xmlmime=rdf' ) ) . "\" />" ); SMWOutputs::commitToParser( $parser ); return true; // always return true, in order not to stop MW's hook processing! }
/** * Gets the properties pointing from the current page to this one. */ static function getPagePropertiesOfPage( $title ) { if ( self::$mLinkedPagesRetrieved ) { return; } $store = smwfGetStore(); if ( class_exists( 'SMWDataItem' ) ) { $value = SMWDIWikiPage::newFromTitle( $title ); } else { $value = $title; } $data = $store->getSemanticData( $value ); foreach ( $data->getProperties() as $property ) { $propertyValues = $data->getPropertyValues( $property ); foreach ( $propertyValues as $propertyValue ) { $linkedPageName = null; if ( $propertyValue instanceof SMWDIWikiPage ) { $propertyName = $property->getKey(); $linkedPageName = $propertyValue->getDBkey(); } elseif ( $propertyValue instanceof SMWWikiPageValue ) { $propertyName = $property->getWikiValue(); $linkedPageName = $propertyValue->getWikiValue(); } if ( !is_null( $linkedPageName ) ) { if ( array_key_exists( $linkedPageName, self::$mLinkedPages ) ) { self::$mLinkedPages[$linkedPageName][] = $propertyName; } else { self::$mLinkedPages[$linkedPageName] = array( $propertyName ); } } } } self::$mLinkedPagesRetrieved = true; }
function saclGetPermissionErrors($title, $user, $action, &$result) { // Failsafe: Some users are exempt from Semantic ACLs if ($user->isAllowed('sacl-exempt')) { return true; } $store = smwfGetStore(); $subject = SMWDIWikiPage::newFromTitle($title); // The prefix for the whitelisted group and user properties // Either ___VISIBLE or ___EDITABLE $prefix = ''; if ($action == 'read') { $prefix = '___VISIBLE'; } else { $type_property = 'Editable by'; $prefix = '___EDITABLE'; } $property = new SMWDIProperty($prefix); $aclTypes = $store->getPropertyValues($subject, $property); foreach ($aclTypes as $valueObj) { $value = strtolower($valueObj->getString()); if ($value == 'users') { if ($user->isAnon()) { $result = false; return false; } } elseif ($value == 'whitelist') { $isWhitelisted = false; $groupProperty = new SMWDIProperty("{$prefix}_WL_GROUP"); $userProperty = new SMWDIProperty("{$prefix}_WL_USER"); $whitelistValues = $store->getPropertyValues($subject, $groupProperty); foreach ($whitelistValues as $whitelistValue) { $group = strtolower($whitelistValue->getString()); if (in_array($group, $user->getEffectiveGroups())) { $isWhitelisted = true; break; } } $whitelistValues = $store->getPropertyValues($subject, $userProperty); foreach ($whitelistValues as $whitelistValue) { $title = $whitelistValue->getTitle(); if ($title->equals($user->getUserPage())) { $isWhitelisted = true; } } if (!$isWhitelisted) { $result = false; return false; } } elseif ($value == 'public') { return true; } } return true; }
/** * * Load all semantic properties of a page as a hash * @param String $pagename * @param Integer $namespace * @param Boolean $normalizeTitle * @return an associative array with the property name as key and property value as value. */ public static function &loadSemanticProperties($pagename, $namespace = NS_MAIN, $normalizeTitle = true) { //-----normalize title $data = null; if ($normalizeTitle) { $title = MWUtil::normalizePageTitle($pagename, false); $di = SMWDIWikiPage::newFromTitle($title); $data = smwfGetStore()->getSemanticData($di); } else { $di = new SMWDIWikiPage($pagename, $namespace, ''); $data = smwfGetStore()->getSemanticData($di); } $valuehash = array(); $diProperties = $data->getProperties(); foreach ($diProperties as $diProperty) { $dvProperty = SMWDataValueFactory::newDataItemValue($diProperty, null); $name = null; if ($dvProperty->isVisible()) { $name = $diProperty->getLabel(); } elseif ($diProperty->getKey() == '_INST') { $name = 'Categories'; } else { continue; // skip this line } if (!$name) { continue; } $values = $data->getPropertyValues($diProperty); $vs = array(); foreach ($values as $di) { $dv = SMWDataValueFactory::newDataItemValue($di, $diProperty); $vs[] = $dv->getWikiValue(); } if (count($vs) == 1) { $valuehash[$name] = $vs[0]; } else { $valuehash[$name] = $vs; } } #error_log(print_r($valuehash, true)); return $valuehash; }
/** * Load results of the given print request and result subject. This is only * done when needed. */ protected function loadContent() { if ($this->mContent !== false) { return; } wfProfileIn('SMWQueryResult::loadContent (SMW)'); switch ($this->mPrintRequest->getMode()) { case SMWPrintRequest::PRINT_THIS: // NOTE: The limit is ignored here. $this->mContent = array($this->mResult); break; case SMWPrintRequest::PRINT_CATS: // Always recompute cache here to ensure output format is respected. self::$catCache = $this->mStore->getPropertyValues($this->mResult, new SMWDIProperty('_INST'), $this->getRequestOptions(false)); self::$catCacheObj = $this->mResult->getHash(); $limit = $this->mPrintRequest->getParameter('limit'); $this->mContent = $limit === false ? self::$catCache : array_slice(self::$catCache, 0, $limit); break; case SMWPrintRequest::PRINT_PROP: $propertyValue = $this->mPrintRequest->getData(); if ($propertyValue->isValid()) { $this->mContent = $this->mStore->getPropertyValues($this->mResult, $propertyValue->getDataItem(), $this->getRequestOptions()); } else { $this->mContent = array(); } // Print one component of a multi-valued string. // Known limitation: the printrequest still is of type _rec, so if printers check // for this then they will not recognize that it returns some more concrete type. if ($this->mPrintRequest->getTypeID() == '_rec' && $this->mPrintRequest->getParameter('index') !== false) { $pos = $this->mPrintRequest->getParameter('index') - 1; $newcontent = array(); foreach ($this->mContent as $diContainer) { /* SMWRecordValue */ $recordValue = SMWDataValueFactory::newDataItemValue($diContainer, $propertyValue->getDataItem()); $dataItems = $recordValue->getDataItems(); if (array_key_exists($pos, $dataItems) && !is_null($dataItems[$pos])) { $newcontent[] = $dataItems[$pos]; } } $this->mContent = $newcontent; } break; case SMWPrintRequest::PRINT_CCAT: ///NOTE: The limit is ignored here. if (self::$catCacheObj != $this->mResult->getHash()) { self::$catCache = $this->mStore->getPropertyValues($this->mResult, new SMWDIProperty('_INST')); self::$catCacheObj = $this->mResult->getHash(); } $found = false; $prkey = $this->mPrintRequest->getData()->getDBkey(); foreach (self::$catCache as $cat) { if ($cat->getDBkey() == $prkey) { $found = true; break; } } $this->mContent = array(new SMWDIBoolean($found)); break; default: $this->mContent = array(); // Unknown print request. } reset($this->mContent); wfProfileOut('SMWQueryResult::loadContent (SMW)'); }
/** * Fetch additional information that is related to the saving that has just happened, * e.g. regarding the last edit date. In runs where this hook is not triggered, the * last DB entry (of MW) will be used to fill such properties. * * @note This method directly accesses a member of Article that is informally declared to * be private. However, there is no way to otherwise access an article's parseroutput for * the purpose of adding information there. If the private access ever becomes a problem, * a global/static variable appears to be the only way to get more article data to * LinksUpdate. * * @param WikiPage|Article $article WikiPage on 1.19 and later * @param Revision $rev * @param integer $baseID * @param User $user * * @return true */ public static function onNewRevisionFromEditComplete($article, Revision $rev, $baseID, User $user) { global $smwgPageSpecialProperties; if ($article->mPreparedEdit && $article->mPreparedEdit->output instanceof ParserOutput) { $output = $article->mPreparedEdit->output; $title = $article->getTitle(); if (!isset($title)) { return true; // nothing we can do } if (!isset($output->mSMWData)) { // no data container yet, make one $output->mSMWData = new SMWSemanticData(new SMWDIWikiPage($title->getDBkey(), $title->getNamespace(), $title->getInterwiki())); } $semdata = $output->mSMWData; } else { // give up, just keep the old data return true; } if (in_array('_MDAT', $smwgPageSpecialProperties)) { $timestamp = $article->getTimestamp(); $di = self::getDataItemFromMWTimestamp($timestamp); if (!is_null($di)) { $semdata->addPropertyObjectValue(new SMWDIProperty('_MDAT'), $di); } } if (in_array('_LEDT', $smwgPageSpecialProperties)) { $di = SMWDIWikiPage::newFromTitle($user->getUserPage()); if (!is_null($di)) { $semdata->addPropertyObjectValue(new SMWDIProperty('_LEDT'), $di); } } if (in_array('_NEWP', $smwgPageSpecialProperties)) { $semdata->addPropertyObjectValue(new SMWDIProperty('_NEWP'), new SMWDIBoolean(is_null($rev->getParentId()))); } return true; }
/** * Implementation of SMWStore::changeTitle(). In contrast to * updateRedirects(), this function does not simply write a redirect * from the old page to the new one, but also deletes all data that may * already be stored for the new title (normally the new title should * belong to an empty page that has no data but at least it could have a * redirect to the old page), and moves all data that exists for the old * title to the new location. Thus, the function executes three steps: * delete data at newtitle, move data from oldtitle to newtitle, and set * redirect from oldtitle to newtitle. In some cases, the goal can be * achieved more efficiently, e.g. if the new title does not occur in SMW * yet: then we can just change the ID records for the titles instead of * changing all data tables * * Note that the implementation ignores the MediaWiki IDs since this * store has its own ID management. Also, the function requires that both * titles are local, i.e. have empty interwiki prefix. * * @todo Currently the sortkey is not moved with the remaining data. It is * not possible to move it reliably in all cases: we cannot distinguish an * unset sortkey from one that was set to the name of oldtitle. Maybe use * update jobs right away? * * @since 1.8 * @param Title $oldtitle * @param Title $newtitle * @param integer $pageid * @param integer $redirid */ public function changeTitle(Title $oldtitle, Title $newtitle, $pageid, $redirid = 0) { global $smwgQEqualitySupport; wfProfileIn("SMWSQLStore3::changeTitle (SMW)"); // get IDs but do not resolve redirects: $sid = $this->store->smwIds->getSMWPageID($oldtitle->getDBkey(), $oldtitle->getNamespace(), '', '', false); $tid = $this->store->smwIds->getSMWPageID($newtitle->getDBkey(), $newtitle->getNamespace(), '', '', false); $db = wfGetDB(DB_MASTER); // Easy case: target not used anywhere yet, just hijack its title for our current id if ($tid == 0 && $smwgQEqualitySupport != SMW_EQ_NONE) { // This condition may not hold even if $newtitle is // currently unused/non-existing since we keep old IDs. // If equality support is off, then this simple move // does too much; fall back to general case below. if ($sid != 0) { // change id entry to refer to the new title // Note that this also changes the reference for internal objects (subobjects) $db->update(SMWSql3SmwIds::tableName, array('smw_title' => $newtitle->getDBkey(), 'smw_namespace' => $newtitle->getNamespace(), 'smw_iw' => ''), array('smw_title' => $oldtitle->getDBkey(), 'smw_namespace' => $oldtitle->getNamespace(), 'smw_iw' => ''), __METHOD__); $this->store->smwIds->moveSubobjects($oldtitle->getDBkey(), $oldtitle->getNamespace(), $newtitle->getDBkey(), $newtitle->getNamespace()); $this->store->smwIds->setCache($oldtitle->getDBkey(), $oldtitle->getNamespace(), '', '', 0, ''); // We do not know the new sortkey, so just clear the cache: // FIXME: This is calling a protected method - wtf! $this->store->smwIds->deleteCache($newtitle->getDBkey(), $newtitle->getNamespace(), '', ''); } else { // make new (target) id for use in redirect table $sid = $this->store->smwIds->makeSMWPageID($newtitle->getDBkey(), $newtitle->getNamespace(), '', ''); } // at this point, $sid is the id of the target page (according to the IDs table) // make redirect id for oldtitle: $this->store->smwIds->makeSMWPageID($oldtitle->getDBkey(), $oldtitle->getNamespace(), SMW_SQL3_SMWREDIIW, ''); $db->insert('smw_fpt_redi', array('s_title' => $oldtitle->getDBkey(), 's_namespace' => $oldtitle->getNamespace(), 'o_id' => $sid), __METHOD__); $this->addToPropertyUsageCount($this->store->smwIds->getSMWPropertyID(new SMWDIProperty('_REDI')), 1, $db); /// NOTE: there is the (bad) case that the moved page is a redirect. As chains of /// redirects are not supported by MW or SMW, the above is maximally correct in this case too. /// NOTE: this temporarily leaves existing redirects to oldtitle point to newtitle as well, which /// will be lost after the next update. Since double redirects are an error anyway, this is not /// a bad behaviour: everything will continue to work until the existing redirects are updated, /// which will hopefully be done to fix the double redirect. } else { // General move method: should always be correct // (equality support respected when updating redirects) // Delete any existing data (including redirects) from new title // ($newtitle should not have data, but let's be sure) $emptyNewSemanticData = new SMWSemanticData(SMWDIWikiPage::newFromTitle($newtitle)); $this->doDataUpdate($emptyNewSemanticData); // Move all data of old title to new position: if ($sid != 0) { $this->store->changeSMWPageID($sid, $tid, $oldtitle->getNamespace(), $newtitle->getNamespace(), true, false); } // Associate internal objects (subobjects) with the new title: $table = $db->tableName(SMWSql3SmwIds::tableName); $values = array('smw_title' => $newtitle->getDBkey(), 'smw_namespace' => $newtitle->getNamespace(), 'smw_iw' => ''); $sql = "UPDATE {$table} SET " . $db->makeList($values, LIST_SET) . ' WHERE smw_title = ' . $db->addQuotes($oldtitle->getDBkey()) . ' AND ' . 'smw_namespace = ' . $db->addQuotes($oldtitle->getNamespace()) . ' AND ' . 'smw_iw = ' . $db->addQuotes('') . ' AND ' . 'smw_subobject != ' . $db->addQuotes(''); // The "!=" is why we cannot use MW array syntax here $db->query($sql, __METHOD__); $this->store->smwIds->moveSubobjects($oldtitle->getDBkey(), $oldtitle->getNamespace(), $newtitle->getDBkey(), $newtitle->getNamespace()); // Write a redirect from old title to new one: // (this also updates references in other tables as needed.) /// TODO: may not be optimal for the standard case that newtitle existed and redirected to oldtitle (PERFORMANCE) $this->updateRedirects($oldtitle->getDBkey(), $oldtitle->getNamespace(), $newtitle->getDBkey(), $newtitle->getNamespace()); } wfProfileOut("SMWSQLStore3::changeTitle (SMW)"); }
/** * Having a title of a page, what is the URI that is described by that page? * The result still requires expandURI() * @param string $title * @return string $uri */ private function getURI($title) { $uri = ""; if ($title instanceof Title) { $wikiPageDI = SMWDIWikiPage::newFromTitle($title); $exp = SMWExporter::getInstance()->makeExportDataForSubject($wikiPageDI); $uri = $exp->getSubject()->getUri(); } else { // There could be other types as well that we do NOT handle here } return $uri; // still requires expandURI() }
/** * This function creates wiki text suitable for rendering a Factbox based on the * information found in a given ParserOutput object. If the required custom data * is not found in the given ParserOutput, then semantic data for the provided Title * object is retreived from the store. * * @param ParserOutput $parseroutput * @param Title $title * * @return string */ public static function getFactboxTextFromOutput(ParserOutput $parseroutput, Title $title) { global $wgRequest, $smwgShowFactboxEdit, $smwgShowFactbox; $mws = isset($parseroutput->mSMWMagicWords) ? $parseroutput->mSMWMagicWords : array(); if (in_array('SMW_SHOWFACTBOX', $mws)) { $showfactbox = SMW_FACTBOX_NONEMPTY; } elseif (in_array('SMW_NOFACTBOX', $mws)) { $showfactbox = SMW_FACTBOX_HIDDEN; } elseif ($wgRequest->getCheck('wpPreview')) { $showfactbox = $smwgShowFactboxEdit; } else { $showfactbox = $smwgShowFactbox; } if ($showfactbox == SMW_FACTBOX_HIDDEN) { // use shortcut return ''; } // Deal with complete dataset only if needed: $smwData = SMWParseData::getSMWDataFromParserOutput($parseroutput); if ($smwData === null || $smwData->stubObject) { $smwData = smwfGetStore()->getSemanticData(SMWDIWikiPage::newFromTitle($title)); } return SMWFactbox::getFactboxText($smwData, $showfactbox); }
/** * Static function for creating a new wikipage object from a * MediaWiki Title object. * * @deprecated This method will vanish before SMW 1.7. If you really need this, simply copy its code. * * @return SMWWikiPageValue */ public static function makePageFromTitle(Title $title) { $dvWikiPage = new SMWWikiPageValue('_wpg'); $diWikiPage = SMWDIWikiPage::newFromTitle($title); $dvWikiPage->setDataItem($diWikiPage); $dvWikiPage->m_title = $title; // optional, just for efficiency return $dvWikiPage; }
/** * @since 2.0 made protected; use printAllToFile or printAllToOutput */ protected function printAll($ns_restriction = false, $delay, $delayeach) { $linkCache = LinkCache::singleton(); $db = wfGetDB(DB_SLAVE); $this->delay_flush = 10; $this->serializer->startSerialization(); $this->serializer->serializeExpData(SMWExporter::getInstance()->getOntologyExpData('')); $end = $db->selectField('page', 'max(page_id)', false, __METHOD__); $a_count = 0; // DEBUG $d_count = 0; // DEBUG $delaycount = $delayeach; for ($id = 1; $id <= $end; $id += 1) { $title = Title::newFromID($id); if (is_null($title) || !smwfIsSemanticsProcessed($title->getNamespace())) { continue; } if (!self::fitsNsRestriction($ns_restriction, $title->getNamespace())) { continue; } $a_count += 1; // DEBUG $diPage = SMWDIWikiPage::newFromTitle($title); $this->queuePage($diPage, 1); while (count($this->element_queue) > 0) { $diPage = reset($this->element_queue); $this->serializePage($diPage, $diPage->recdepth); // resolve dependencies that will otherwise not be printed foreach ($this->element_queue as $key => $diaux) { if (!smwfIsSemanticsProcessed($diaux->getNamespace()) || !self::fitsNsRestriction($ns_restriction, $diaux->getNamespace())) { // Note: we do not need to check the cache to guess if an element was already // printed. If so, it would not be included in the queue in the first place. $d_count += 1; // DEBUG } else { // don't carry values that you do not want to export (yet) unset($this->element_queue[$key]); } } // sleep each $delaycount for $delay µs to be nice to the server if ($delaycount-- < 0 && $delayeach != 0) { usleep($delay); $delaycount = $delayeach; } } $this->flush(); $linkCache->clear(); } $this->serializer->finishSerialization(); $this->flush(true); }
private function newDiWikiPage($dbkeys) { $diWikiPage = new SMWDIWikiPage($dbkeys[0], intval($dbkeys[1]), $dbkeys[2], $dbkeys[4]); $diWikiPage->setSortKey($dbkeys[3]); return $diWikiPage; }
/** * @see SMWStore::getProperties * * @param SMWDIWikiPage $subject * @param SMWRequestOptions $requestoptions */ public function getProperties(SMWDIWikiPage $subject, $requestoptions = null) { wfProfileIn("SMWSQLStore3::getProperties (SMW)"); $sid = $this->store->smwIds->getSMWPageID($subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName()); if ($sid == 0) { // no id, no page, no properties wfProfileOut("SMWSQLStore3::getProperties (SMW)"); return array(); } $db = wfGetDB(DB_SLAVE); $result = array(); if ($requestoptions !== null) { // potentially need to get more results, since options apply to union $suboptions = clone $requestoptions; $suboptions->limit = $requestoptions->limit + $requestoptions->offset; $suboptions->offset = 0; } else { $suboptions = null; } foreach (SMWSQLStore3::getPropertyTables() as $proptable) { $from = $db->tableName($proptable->name); if ($proptable->idsubject) { $where = 's_id=' . $db->addQuotes($sid); } elseif ($subject->getInterwiki() === '') { $where = 's_title=' . $db->addQuotes($subject->getDBkey()) . ' AND s_namespace=' . $db->addQuotes($subject->getNamespace()); } else { // subjects with non-emtpy interwiki cannot have properties continue; } if ($proptable->fixedproperty == false) { // select all properties $from .= " INNER JOIN " . $db->tableName('smw_ids') . " ON smw_id=p_id"; $res = $db->select($from, 'DISTINCT smw_title,smw_sortkey', $where . $this->store->getSQLConditions($suboptions, 'smw_sortkey', 'smw_sortkey'), 'SMW::getProperties', $this->store->getSQLOptions($suboptions, 'smw_sortkey')); foreach ($res as $row) { $result[] = new SMWDIProperty($row->smw_title); } } else { // just check if subject occurs in table $res = $db->select($from, '*', $where, 'SMW::getProperties', array('LIMIT' => 1)); if ($db->numRows($res) > 0) { $result[] = new SMWDIProperty($proptable->fixedproperty); } } $db->freeResult($res); } $result = $this->store->applyRequestOptions($result, $requestoptions); // apply options to overall result wfProfileOut("SMWSQLStore3::getProperties (SMW)"); return $result; }
/** * Fetch additional information that is related to the saving that has just happened, * e.g. regarding the last edit date. In runs where this hook is not triggered, the * last DB entry (of MW) will be used to fill such properties. * * @note This method directly accesses a member of Article that is informally declared to * be private. However, there is no way to otherwise access an article's parseroutput for * the purpose of adding information there. If the private access ever becomes a problem, * a global/static variable appears to be the only way to get more article data to * LinksUpdate. * * @param WikiPage|Article $article WikiPage on 1.19 and later * @param Revision $rev * @param integer $baseID * @param User $user * * @return true */ public static function onNewRevisionFromEditComplete($article, Revision $rev, $baseID, User $user) { global $smwgPageSpecialProperties; if ($article->mPreparedEdit && $article->mPreparedEdit->output instanceof ParserOutput) { $semdata = self::getSMWDataFromParserOutput($article->mPreparedEdit->output, $article->getTitle()); } else { // give up, just keep the old data return true; } if (in_array('_MDAT', $smwgPageSpecialProperties)) { $timestamp = $article->getTimestamp(); $di = self::getDataItemFromMWTimestamp($timestamp); if (!is_null($di)) { $semdata->addPropertyObjectValue(new SMWDIProperty('_MDAT'), $di); } } if (in_array('_LEDT', $smwgPageSpecialProperties)) { $di = SMWDIWikiPage::newFromTitle($user->getUserPage()); if (!is_null($di)) { $semdata->addPropertyObjectValue(new SMWDIProperty('_LEDT'), $di); } } if (in_array('_NEWP', $smwgPageSpecialProperties)) { $semdata->addPropertyObjectValue(new SMWDIProperty('_NEWP'), new SMWDIBoolean(is_null($rev->getParentId()))); } return true; }
/** * Returns whether the concepts of the group cover the specified page. * * @since 0.1 * * @param Title $title * * @return boolean */ public function conceptsCoverPage(Title $title) { if (count($this->concepts) == 0) { return true; } $foundMatch = false; foreach ($this->concepts as $groupConcept) { $queryDescription = new SMWConjunction(); $conceptTitle = Title::newFromText($groupConcept, SMW_NS_CONCEPT); if (!$conceptTitle->exists()) { continue; } $queryDescription->addDescription(new SMWConceptDescription(SMWDIWikiPage::newFromTitle($conceptTitle))); $queryDescription->addDescription(new SMWValueDescription(SMWDIWikiPage::newFromTitle($title))); $query = new SMWQuery($queryDescription); $query->querymode = SMWQuery::MODE_COUNT; /* SMWQueryResult */ $result = smwfGetStore()->getQueryResult($query); $foundMatch = $result instanceof SMWQueryResult ? $result->getCount() > 0 : $result > 0; if ($foundMatch) { break; } } return $foundMatch; }
public function execute($par) { global $wgRequest, $wgScript; $this->setHeaders(); $output = $this->getOutput(); if ($par != '') { $parts = explode('/', urldecode($par)); } else { $parts = array(); } $type = isset($parts[0]) ? $parts[0] : $wgRequest->getText('type'); if ($type == '') { $type = 'ancestors'; } $pageName = isset($parts[1]) ? $parts[1] : $wgRequest->getText('page'); if ($type == 'link') { $pageName2 = isset($parts[2]) ? $parts[2] : $wgRequest->getText('page2'); $numOfGenerations = 0; } else { $numOfGenerations = isset($parts[2]) ? intval($parts[2]) : $wgRequest->getInt('gen'); if ($numOfGenerations <= 0) { $numOfGenerations = 5; } $pageName2 = ''; } if (!$this->mIncluding) { $output->addModules('ext.smg.specialfamilytree'); $typeSelect = new XmlSelect('type', 'type', $type); $typeSelect->addOption(wfMsg('semanticgenealogy-specialfamilytree-type-ancestors'), 'ancestors'); $typeSelect->addOption(wfMsg('semanticgenealogy-specialfamilytree-type-descendant'), 'descendant'); $typeSelect->addOption(wfMsg('semanticgenealogy-specialfamilytree-type-link'), 'link'); $output->addHTML(Xml::openElement('form', array('action' => $wgScript)) . Html::hidden('title', $this->getPageTitle()->getPrefixedText()) . Xml::openElement('fieldset') . Xml::openElement('table', array('id' => 'smg-familyTree-form')) . Xml::openElement('tr', array('id' => 'smg-form-entry-page')) . Xml::openElement('th', array('class' => 'mw-label')) . Xml::label(wfMsg('semanticgenealogy-specialfamilytree-label-page'), 'page') . Xml::closeElement('th') . Xml::openElement('td', array('class' => 'mw-input')) . Xml::input('page', 30, $pageName, array('class' => 'smg-input-page')) . Xml::closeElement('td') . Xml::closeElement('tr') . Xml::openElement('tr', array('id' => 'smg-form-entry-type')) . Xml::openElement('th', array('class' => 'mw-label')) . Xml::label(wfMsg('semanticgenealogy-specialfamilytree-label-type'), 'type') . Xml::closeElement('th') . Xml::openElement('td', array('class' => 'mw-input')) . $typeSelect->getHtml() . Xml::closeElement('td') . Xml::closeElement('tr') . Xml::openElement('tr', array('id' => 'smg-form-entry-gen')) . Xml::openElement('th', array('class' => 'mw-label')) . Xml::label(wfMsg('semanticgenealogy-specialfamilytree-label-gen'), 'gen') . Xml::closeElement('th') . Xml::openElement('td', array('class' => 'mw-input')) . Xml::input('gen', 2, $numOfGenerations) . Xml::closeElement('td') . Xml::closeElement('tr') . Xml::openElement('tr', array('id' => 'smg-form-entry-page2')) . Xml::openElement('th', array('class' => 'mw-label')) . Xml::label(wfMsg('semanticgenealogy-specialfamilytree-label-page2'), 'page2') . Xml::closeElement('th') . Xml::openElement('td', array('class' => 'mw-input')) . Xml::input('page2', 30, $pageName2, array('class' => 'smg-input-page')) . Xml::closeElement('td') . Xml::closeElement('tr') . Xml::closeElement('table') . Xml::submitButton(wfMsg('semanticgenealogy-specialfamilytree-button-submit')) . Xml::closeElement('fieldset') . Xml::closeElement('form')); } if ($pageName == '') { return; } $pageTitle = Title::newFromText($pageName); $page = SMWDIWikiPage::newFromTitle($pageTitle); if ($type == '') { $type = 'ancestors'; } switch ($type) { case 'ancestors': $tree = $this->getAncestors($page, $numOfGenerations); $this->outputAncestorsTree($tree, $numOfGenerations); break; case 'descendant': $this->outputDescendantList($page, $numOfGenerations); break; case 'link': if ($pageName2 == '') { $output->addWikiText('<span class="error">' . wfMsg('semanticgenealogy-specialfamilytree-error-nosecondpagename') . '</span>'); return; } $pageTitle2 = Title::newFromText($pageName2); $page2 = SMWDIWikiPage::newFromTitle($pageTitle2); $tree = $this->getRelation($page, $page2); if ($tree !== null) { $this->outputRelationTree($tree); } else { $output->addWikiText('<span class="error">' . wfMsg('semanticgenealogy-specialfamilytree-error-nolinkfound', $pageName, $pageName2) . '</span>'); } break; default: $output->addWikiText('<span class="error">' . wfMsg('semanticgenealogy-specialfamilytree-error-unknowntype', $type) . '</span>'); } return Status::newGood(); }
/** * Delete all semantic data stored for the given subject. Used for * update purposes. Handles Subobjects recursively * * @param $subject SMWDIWikiPage the data of which is deleted */ public function deleteSemanticData(SMWDIWikiPage $subject) { $db = wfGetDB(DB_MASTER); $id = $this->store->smwIds->getSMWPageID($subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName(), false, true); if ($id == 0) { // not (directly) used anywhere yet, may be a redirect but we do not care here wfRunHooks('smwDeleteSemanticData', array($subject)); return; } //get oldData for diffing and updating property counts $oldData = $this->store->getSemanticData($subject); $this->doDiffandUpdateCount($oldData); $oldHashes = $this->store->smwIds->getPropertyTableHashes($id); foreach (SMWSQLStore3::getPropertyTables() as $tableId => $tableDeclaration) { $tableName = $tableDeclaration->name; if (array_key_exists($tableName, $oldHashes)) { $this->deleteTableSemanticData($id, $tableDeclaration); } } if ($subject->getSubobjectName() !== '') { wfRunHooks('smwDeleteSemanticData', array($subject)); return; // Subobjects don't have subsubobjects } // also find subobjects used by this ID ... $oldSubobjects = $this->getSubobjects($subject); // ... and delete their data as well recursively foreach ($oldSubobjects as $subobject) { $this->deleteSemanticData($subobject); } //TODO: delete all unused subobjects wfRunHooks('smwDeleteSemanticData', array($subject)); }
/** * @brief Adds the properties, hooks into SMWStore::updateDataBefore. * * @param SMWStore $store, SMWSemanticData $newData * * @return true * */ public function sespUpdateDataBefore($store, $data) { global $sespSpecialProperties, $wgDisableCounters; // just some compat mode global $smwgPageSpecialProperties2; if (isset($smwgPageSpecialProperties2) && !isset($sespSpecialProperties)) { $sespSpecialProperties = $smwgPageSpecialProperties2; } /* Get array of properties to set */ if (!isset($sespSpecialProperties)) { wfDebug(__METHOD__ . ": SESP array is not specified, please add the following\n"); wfDebug("variables to your LocalSettings.php:\n"); wfDebug("\$sespSpecialProperties\n"); return true; } /* Get current title and article */ $title = $data->getSubject()->getTitle(); $article = Article::newFromTitle($title, RequestContext::getMain()); // return if $title or $article is null if (is_null($title) || is_null($article)) { return true; } /**************************/ /* CUSER (First author) */ /**************************/ if (in_array('_CUSER', $sespSpecialProperties)) { $firstRevision = $title->getFirstRevision(); if ($firstRevision !== null) { $firstAuthor = User::newFromId($firstRevision->getRawUser()); if ($firstAuthor) { $property = new SMWDIProperty('___CUSER'); $dataItem = SMWDIWikiPage::newFromTitle($firstAuthor->getUserPage()); $data->addPropertyObjectValue($property, $dataItem); } } } // end if _CUSER /**************************/ /* REVID (Revision ID) */ /**************************/ if (in_array('_REVID', $sespSpecialProperties)) { $property = new SMWDIProperty('___REVID'); $dataItem = new SMWDINumber($article->getRevIdFetched()); $data->addPropertyObjectValue($property, $dataItem); } /********************************/ /* VIEWS (Number of page views) */ /********************************/ if (in_array('_VIEWS', $sespSpecialProperties) && !$wgDisableCounters) { $property = new SMWDIProperty('___VIEWS'); $dataItem = new SMWDINumber($article->getCount()); $data->addPropertyObjectValue($property, $dataItem); } /*****************************/ /* EUSER (Page contributors) */ /*****************************/ if (in_array('_EUSER', $sespSpecialProperties)) { /* Create property */ $property = new SMWDIProperty('___EUSER'); /* Get options */ global $wgSESPExcludeBots; if (!isset($wgSESPExcludeBots)) { $wgSESPExcludeBots = false; } /* Get author from current revision */ $u = User::newFromId($article->getUser()); /* Get authors from earlier revisions */ $authors = $article->getContributors(); while ($u) { if (!$u->isHidden() && !(in_array('bot', $u->getRights()) && $wgSESPExcludeBots) && !$u->isAnon()) { //no anonymous users /* Add values*/ $dataItem = SMWDIWikiPage::newFromTitle($u->getUserPage()); $data->addPropertyObjectValue($property, $dataItem); } $u = $authors->current(); $authors->next(); } } /******************************/ /* NREV (Number of revisions) */ /******************************/ if (in_array('_NREV', $sespSpecialProperties)) { /* Create property */ $property = new SMWDIProperty('___NREV'); /* Get number of revisions */ $dbr =& wfGetDB(DB_SLAVE); $num = $dbr->estimateRowCount("revision", "*", array("rev_page" => $title->getArticleID())); /* Add values */ $dataItem = new SMWDINumber($num); $data->addPropertyObjectValue($property, $dataItem); } /*****************************************/ /* NTREV (Number of talk page revisions) */ /*****************************************/ if (in_array('_NTREV', $sespSpecialProperties)) { /* Create property */ $property = new SMWDIProperty('___NTREV'); /* Get number of revisions */ if (!isset($dbr)) { $dbr =& wfGetDB(DB_SLAVE); } $talkPage = $title->getTalkPage(); $num = $dbr->estimateRowCount("revision", "*", array("rev_page" => $talkPage->getArticleID())); /* Add values */ $dataItem = new SMWDINumber($num); $data->addPropertyObjectValue($property, $dataItem); } /************************/ /* SUBP (Get sub pages) */ /************************/ if (in_array('_SUBP', $sespSpecialProperties)) { /* Create property */ $property = new SMWDIProperty('___SUBP'); $subpages = $title->getSubpages(-1); //-1 = no limit. Returns TitleArray object /* Add values*/ foreach ($subpages as $t) { $dataItem = SMWDIWikiPage::newFromTitle($t); $data->addPropertyObjectValue($property, $dataItem); } // end foreach } // end _SUBP /************************/ /* MIMETYPE */ /************************/ if ($title->inNamespace(NS_FILE) && in_array('_MIMETYPE', $sespSpecialProperties)) { // Build image page instance $imagePage = new ImagePage($title); $file = $imagePage->getFile(); $mimetype = $file->getMimeType(); $mediaType = MimeMagic::singleton()->findMediaType($mimetype); list($mimetypemajor, $mimetypeminor) = $file->splitMime($mimetype); // MIMETYPE $property = new SMWDIProperty('___MIMETYPE'); $dataItem = new SMWDIString($mimetypeminor); $data->addPropertyObjectValue($property, $dataItem); // MEDIATYPE $property = new SMWDIProperty('___MEDIATYPE'); $dataItem = new SMWDIString($mediaType); $data->addPropertyObjectValue($property, $dataItem); } // end if MIMETYPE /************************/ /* IMAGEMETA */ /************************/ function convertexifdate($exifString) { $exifPieces = explode(":", $exifString); if ($exifPieces[0] && $exifPieces[1] && $exifPieces[2]) { $res = new DateTime($exifPieces[0] . "-" . $exifPieces[1] . "-" . $exifPieces[2] . ":" . $exifPieces[3] . ":" . $exifPieces[4]); return $res; } else { return false; } } if ($title->inNamespace(NS_FILE) && in_array('_METADATA', $sespSpecialProperties)) { $imagePage = new ImagePage($title); $file = $imagePage->getFile(); $metadata = $file->getMetadata(); if ($metadata === ExifBitmapHandler::OLD_BROKEN_FILE || $metadata === ExifBitmapHandler::BROKEN_FILE) { // So we don't try and display metadata from PagedTiffHandler // for example when using InstantCommons. return true; } $exif = unserialize($metadata); if ($exif) { if (count($exif)) { // EXIFDATETIME if (array_key_exists('DateTimeOriginal', $exif) || array_key_exists('DateTime', $exif)) { $property = new SMWDIProperty('___EXIFDATETIME'); if (array_key_exists('DateTimeOriginal', $exif)) { $exifstr = $exif['DateTimeOriginal']; } else { $exifstr = $exif['DateTime']; } $datetime = convertexifdate($exifstr); if ($datetime) { $dataItem = new SMWDITime(SMWDITime::CM_GREGORIAN, $datetime->format('Y'), $datetime->format('n'), $datetime->format('j'), $datetime->format('G'), $datetime->format('i')); $data->addPropertyObjectValue($property, $dataItem); } } // EXIFSOFTWARE if (array_key_exists('Software', $exif) || array_key_exists('metadata', $exif) && array_key_exists('Software', $exif['metadata'])) { $str = array_key_exists('Software', $exif) ? $exif['Software'] : $exif['metadata']['Software']; if (is_array($str)) { $str = array_key_exists('x-default', $str) ? $str['x-default'] : $str[0]; } if (!$str) { return true; } $property = new SMWDIProperty('___EXIFSOFTWARE'); $dataItem = new SMWDIString($str); $data->addPropertyObjectValue($property, $dataItem); } // EXIFLATLON /* //TODO if ( array_key_exists( 'GPSLatitudeRef', $exif ) || array_key_exists( 'GPSLongitudeRef', $exif ) ) { } */ //EXIFLATLON } } } //IMAGEMETA /************************/ /* SHORTURL */ /************************/ //FIXME handle internal and external links if (in_array('_SHORTURL', $sespSpecialProperties) && class_exists('ShortUrlUtils')) { global $wgShortUrlPrefix; if (!is_string($wgShortUrlPrefix)) { $urlPrefix = SpecialPage::getTitleFor('ShortUrl')->getFullUrl() . '/'; } else { $urlPrefix = $wgShortUrlPrefix; } if (ShortUrlUtils::needsShortUrl($title)) { $shortId = ShortUrlUtils::encodeTitle($title); $shortURL = $urlPrefix . $shortId; $property = new SMWDIProperty('___SHORTURL'); $dataItem = new SMWDIUri('http', $shortURL, '', ''); $data->addPropertyObjectValue($property, $dataItem); } else { } } // end if SHORTURL return true; }
public static function getAllPagesForConcept($conceptName, $substring = null) { global $sfgMaxAutocompleteValues, $sfgAutocompleteOnAllChars; $store = smwfGetStore(); $conceptTitle = Title::makeTitleSafe(SMW_NS_CONCEPT, $conceptName); if (!is_null($substring)) { $substring = strtolower($substring); } // Escape if there's no such concept. if ($conceptTitle == null || !$conceptTitle->exists()) { return "Could not find concept: {$conceptName}"; } $conceptDI = SMWDIWikiPage::newFromTitle($conceptTitle); $desc = new SMWConceptDescription($conceptDI); $printout = new SMWPrintRequest(SMWPrintRequest::PRINT_THIS, ""); $desc->addPrintRequest($printout); $query = new SMWQuery($desc); $query->setLimit($sfgMaxAutocompleteValues); $query_result = $store->getQueryResult($query); $pages = array(); while ($res = $query_result->getNext()) { $pageName = $res[0]->getNextText(SMW_OUTPUT_WIKI); if (is_null($substring)) { $pages[] = $pageName; } else { // Filter on the substring manually. It would // be better to do this filtering in the // original SMW query, but that doesn't seem // possible yet. $lowercasePageName = strtolower($pageName); if ($sfgAutocompleteOnAllChars) { if (strpos($lowercasePageName, $substring) >= 0) { $pages[] = $pageName; } } else { if (strpos($lowercasePageName, $substring) === 0 || strpos($lowercasePageName, ' ' . $substring) > 0) { $pages[] = $pageName; } } } } sort($pages); return $pages; }
/** * Implementation of SMWStore::changeTitle(). In contrast to * updateRedirects(), this function does not simply write a redirect * from the old page to the new one, but also deletes all data that may * already be stored for the new title (normally the new title should * belong to an empty page that has no data but at least it could have a * redirect to the old page), and moves all data that exists for the old * title to the new location. Thus, the function executes three steps: * delete data at newtitle, move data from oldtitle to newtitle, and set * redirect from oldtitle to newtitle. In some cases, the goal can be * achieved more efficiently, e.g. if the new title does not occur in SMW * yet: then we can just change the ID records for the titles instead of * changing all data tables * * Note that the implementation ignores the MediaWiki IDs since this * store has its own ID management. Also, the function requires that both * titles are local, i.e. have empty interwiki prefix. * * @todo Currently the sortkey is not moved with the remaining data. It is * not possible to move it reliably in all cases: we cannot distinguish an * unset sortkey from one that was set to the name of oldtitle. Maybe use * update jobs right away? * * @since 1.8 * * @param Title $oldTitle * @param Title $newTitle * @param integer $pageId * @param integer $redirectId */ public function changeTitle(Title $oldTitle, Title $newTitle, $pageId, $redirectId = 0) { global $smwgQEqualitySupport; wfRunHooks('SMW::SQLStore::BeforeChangeTitleComplete', array($this->store, $oldTitle, $newTitle, $pageId, $redirectId)); $db = $this->store->getConnection(); // get IDs but do not resolve redirects: $sid = $this->store->getObjectIds()->getSMWPageID($oldTitle->getDBkey(), $oldTitle->getNamespace(), '', '', false); $tid = $this->store->getObjectIds()->getSMWPageID($newTitle->getDBkey(), $newTitle->getNamespace(), '', '', false); // Easy case: target not used anywhere yet, just hijack its title for our current id if ($tid == 0 && $smwgQEqualitySupport != SMW_EQ_NONE) { // This condition may not hold even if $newtitle is // currently unused/non-existing since we keep old IDs. // If equality support is off, then this simple move // does too much; fall back to general case below. if ($sid != 0) { // change id entry to refer to the new title // Note that this also changes the reference for internal objects (subobjects) $db->update(SMWSql3SmwIds::tableName, array('smw_title' => $newTitle->getDBkey(), 'smw_namespace' => $newTitle->getNamespace(), 'smw_iw' => ''), array('smw_title' => $oldTitle->getDBkey(), 'smw_namespace' => $oldTitle->getNamespace(), 'smw_iw' => ''), __METHOD__); $this->store->getObjectIds()->moveSubobjects($oldTitle->getDBkey(), $oldTitle->getNamespace(), $newTitle->getDBkey(), $newTitle->getNamespace()); $this->store->getObjectIds()->setCache($oldTitle->getDBkey(), $oldTitle->getNamespace(), '', '', 0, ''); // We do not know the new sortkey, so just clear the cache: $this->store->getObjectIds()->deleteCache($newTitle->getDBkey(), $newTitle->getNamespace(), '', ''); } else { // make new (target) id for use in redirect table $sid = $this->store->getObjectIds()->makeSMWPageID($newTitle->getDBkey(), $newTitle->getNamespace(), '', ''); } // at this point, $sid is the id of the target page (according to the IDs table) // make redirect id for oldtitle: $this->store->getObjectIds()->makeSMWPageID($oldTitle->getDBkey(), $oldTitle->getNamespace(), SMW_SQL3_SMWREDIIW, ''); $this->store->getObjectIds()->addRedirectForId($sid, $oldTitle->getDBkey(), $oldTitle->getNamespace()); $statsTable = new PropertyStatisticsTable($db, SMWSQLStore3::PROPERTY_STATISTICS_TABLE); $statsTable->addToUsageCount($this->store->getObjectIds()->getSMWPropertyID(new SMWDIProperty('_REDI')), 1); /// NOTE: there is the (bad) case that the moved page is a redirect. As chains of /// redirects are not supported by MW or SMW, the above is maximally correct in this case too. /// NOTE: this temporarily leaves existing redirects to oldtitle point to newtitle as well, which /// will be lost after the next update. Since double redirects are an error anyway, this is not /// a bad behavior: everything will continue to work until the existing redirects are updated, /// which will hopefully be done to fix the double redirect. } else { // General move method: should always be correct // (equality support respected when updating redirects) // Delete any existing data (including redirects) from new title // ($newtitle should not have data, but let's be sure) $emptyNewSemanticData = new SMWSemanticData(SMWDIWikiPage::newFromTitle($newTitle)); $this->doDataUpdate($emptyNewSemanticData); // Move all data of old title to new position: if ($sid != 0) { $this->store->changeSMWPageID($sid, $tid, $oldTitle->getNamespace(), $newTitle->getNamespace(), true, false); } // Associate internal objects (subobjects) with the new title: $table = $db->tableName(SMWSql3SmwIds::tableName); $values = array('smw_title' => $newTitle->getDBkey(), 'smw_namespace' => $newTitle->getNamespace(), 'smw_iw' => ''); $sql = "UPDATE {$table} SET " . $db->makeList($values, LIST_SET) . ' WHERE smw_title = ' . $db->addQuotes($oldTitle->getDBkey()) . ' AND ' . 'smw_namespace = ' . $db->addQuotes($oldTitle->getNamespace()) . ' AND ' . 'smw_iw = ' . $db->addQuotes('') . ' AND ' . 'smw_subobject != ' . $db->addQuotes(''); // The "!=" is why we cannot use MW array syntax here $db->query($sql, __METHOD__); $this->store->getObjectIds()->moveSubobjects($oldTitle->getDBkey(), $oldTitle->getNamespace(), $newTitle->getDBkey(), $newTitle->getNamespace()); // $redirid == 0 means that the oldTitle was not supposed to be a redirect // (oldTitle is delete from the db) but instead of deleting all // references we will still copy data from old to new during updateRedirects() // and clear the semantic data container for the oldTitle instance // to ensure that no ghost references exists for an deleted oldTitle // @see Title::moveTo(), createRedirect if ($redirectId == 0) { // Delete any existing data (including redirects) from old title $this->updateRedirects($oldTitle->getDBkey(), $oldTitle->getNamespace()); } else { // Write a redirect from old title to new one: // (this also updates references in other tables as needed.) // TODO: may not be optimal for the standard case that newtitle // existed and redirected to oldtitle (PERFORMANCE) $this->updateRedirects($oldTitle->getDBkey(), $oldTitle->getNamespace(), $newTitle->getDBkey(), $newTitle->getNamespace()); } } // Update the page immediately to ensure that only a fresh set of data // is displayed $jobs = array(); // 1.24+ reported "Parser state cleared while parsing. Did you call // Parser::parse recursively" when using the global Parser instance // Set 'pm' (parser-mode) to 2 indicating to use a new Parser // instance when running the job $jobs[] = new UpdateJob($newTitle, array('pm' => 2)); if ($redirectId != 0) { $jobs[] = new UpdateJob($oldTitle, array('pm' => 2)); } $db->onTransactionIdle(function () use($jobs) { foreach ($jobs as $job) { $job->run(); } }); }
/** * Create an SMWExpElement for some internal resource, given by an * SMWDIWikiPage object. This is the one place in the code where URIs * of wiki pages and user-defined properties are determined. A modifier * can be given to make variants of a URI, typically done for * auxiliary properties. In this case, the URI is modiied by appending * "-23$modifier" where "-23" is the URI encoding of "#" (a symbol not * occuring in MW titles). * * @param $diWikiPage SMWDIWikiPage or SMWDIProperty * @param $modifier string, using only Latin letters and numbers * @return SMWExpResource */ public static function getResourceElementForWikiPage(SMWDIWikiPage $diWikiPage, $modifier = '') { global $wgContLang; if ($diWikiPage->getNamespace() == NS_MEDIA) { // special handling for linking media files directly (object only) $title = Title::makeTitle($diWikiPage->getNamespace(), $diWikiPage->getDBkey()); $file = wfFindFile($title); if ($file !== false) { return new SMWExpResource($file->getFullURL()); } // else: Medialink to non-existing file :-/ fall through } if ($diWikiPage->getSubobjectName() !== '') { $modifier = $diWikiPage->getSubobjectName(); } if ($modifier === '') { $importProperty = new SMWDIProperty('_IMPO'); $importDis = smwfGetStore()->getPropertyValues($diWikiPage, $importProperty); $importURI = count($importDis) > 0; } else { $importURI = false; } if ($importURI) { $importValue = SMWDataValueFactory::newDataItemValue(current($importDis), $importProperty); $namespace = $importValue->getNS(); $namespaceId = $importValue->getNSID(); $localName = $importValue->getLocalName(); } else { $localName = ''; if ($diWikiPage->getNamespace() == SMW_NS_PROPERTY) { $namespace = self::getNamespaceUri('property'); $namespaceId = 'property'; $localName = self::encodeURI(rawurlencode($diWikiPage->getDBkey())); } if ($localName === '' || in_array($localName[0], array('-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'))) { $namespace = self::getNamespaceUri('wiki'); $namespaceId = 'wiki'; if ($diWikiPage->getNamespace() !== 0) { $localName = str_replace(' ', '_', $wgContLang->getNSText($diWikiPage->getNamespace())) . ':' . $diWikiPage->getDBkey(); } else { $localName = $diWikiPage->getDBkey(); } $localName = self::encodeURI(wfUrlencode($localName)); } if ($modifier !== '') { $localName .= '-23' . $modifier; } } return new SMWExpNsResource($localName, $namespace, $namespaceId, $diWikiPage); }
/** * Like Article's getTitle(), but returning a suitable SMWDIWikiPage. * * @since 1.6 * * @return SMWDIWikiPage */ protected function getDataItem() { return SMWDIWikiPage::newFromTitle($this->getTitle()); }
/** * Refresh the concept cache for the given concept. * * @since 1.8 * @param $concept Title * @return array of error strings (empty if no errors occurred) */ public function refreshConceptCache(Title $concept) { global $smwgQMaxLimit, $smwgQConceptFeatures, $wgDBtype; $fname = 'SMW::refreshConceptCache'; $cid = $this->m_store->smwIds->getSMWPageID($concept->getDBkey(), SMW_NS_CONCEPT, '', ''); $cid_c = $this->m_store->smwIds->getSMWPageID($concept->getDBkey(), SMW_NS_CONCEPT, '', '', false); if ($cid != $cid_c) { $this->m_errors[] = "Skipping redirect concept."; return $this->m_errors; } $values = $this->m_store->getPropertyValues(SMWDIWikiPage::newFromTitle($concept), new SMWDIProperty('_CONC')); $di = end($values); $desctxt = $di !== false ? $di->getConceptQuery() : false; $this->m_errors = array(); if ($desctxt) { // concept found $this->m_qmode = SMWQuery::MODE_INSTANCES; $this->m_queries = array(); $this->m_hierarchies = array(); $this->m_querylog = array(); $this->m_sortkeys = array(); SMWSQLStore3Query::$qnum = 0; // Pre-process query: $qp = new SMWQueryParser($smwgQConceptFeatures); $desc = $qp->getQueryDescription($desctxt); $qid = $this->compileQueries($desc); $this->executeQueries($this->m_queries[$qid]); // execute query tree, resolve all dependencies $qobj = $this->m_queries[$qid]; if ($qobj->joinfield === '') { return; } // Update database: $this->m_dbs->delete(SMWSQLStore3::CONCEPT_CACHE_TABLE, array('o_id' => $cid), $fname); $smw_conccache = $this->m_dbs->tablename(SMWSQLStore3::CONCEPT_CACHE_TABLE); if ($wgDBtype == 'postgres') { // PostgresQL: no INSERT IGNORE, check for duplicates explicitly $where = $qobj->where . ($qobj->where ? ' AND ' : '') . "NOT EXISTS (SELECT NULL FROM {$smw_conccache}" . " WHERE {$smw_conccache}.s_id = {$qobj->alias}.s_id " . " AND {$smw_conccache}.o_id = {$qobj->alias}.o_id )"; } else { // MySQL just uses INSERT IGNORE, no extra conditions $where = $qobj->where; } $this->m_dbs->query("INSERT " . ($wgDBtype == 'postgres' ? '' : 'IGNORE ') . "INTO {$smw_conccache}" . " SELECT DISTINCT {$qobj->joinfield} AS s_id, {$cid} AS o_id FROM " . $this->m_dbs->tableName($qobj->jointable) . " AS {$qobj->alias}" . $qobj->from . ($where ? ' WHERE ' : '') . $where . " LIMIT {$smwgQMaxLimit}", $fname); $this->m_dbs->update('smw_fpt_conc', array('cache_date' => strtotime("now"), 'cache_count' => $this->m_dbs->affectedRows()), array('s_id' => $cid), $fname); } else { // no concept found; just delete old data if there is any $this->m_dbs->delete(SMWSQLStore3::CONCEPT_CACHE_TABLE, array('o_id' => $cid), $fname); $this->m_dbs->update('smw_fpt_conc', array('cache_date' => null, 'cache_count' => null), array('s_id' => $cid), $fname); $this->m_errors[] = "No concept description found."; } $this->cleanUp(); return $this->m_errors; }
/** * Generate a hash value to simplify the comparison of this data * container with other containers. The hash uses PHP's md5 * implementation, which is among the fastest hash algorithms that * PHP offers. * * @return string */ public function getHash() { $ctx = hash_init('md5'); // here and below, use "_#_" to separate values; really not much care needed here hash_update($ctx, '_#_' . $this->mSubject->getSerialization()); foreach ($this->getProperties() as $property) { hash_update($ctx, '_#_' . $property->getKey() . '##'); foreach ($this->getPropertyValues($property) as $di) { hash_update($ctx, '_#_' . $di->getSerialization()); } } return hash_final($ctx); }
/** * Delete all semantic data stored for the given subject. Used for * update purposes. * * @param $subject SMWDIWikiPage the data of which is deleted */ protected function deleteSemanticData(SMWDIWikiPage $subject) { if ($subject->getSubobjectName() !== '') { return; } // not needed, and would mess up data $db = wfGetDB(DB_MASTER); $id = $this->getSMWPageID($subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), '', false); if ($id == 0) { // not (directly) used anywhere yet, may be a redirect but we do not care here wfRunHooks('smwDeleteSemanticData', array($subject)); return; } foreach (self::getPropertyTables() as $proptable) { if ($proptable->name == 'smw_conc2') { continue; } // skip concepts, since they have chache data in their table which should be kept while the cache is intact if ($proptable->idsubject) { $db->delete($proptable->name, array('s_id' => $id), __METHOD__); } elseif ($proptable->name != 'smw_redi2') { /// NOTE: redirects are handled by updateRedirects(), not here! $db->delete($proptable->name, array('s_title' => $subject->getDBkey(), 's_namespace' => $subject->getNamespace()), __METHOD__); } } // also find subobjects used by this ID ... $res = $db->select('smw_ids', '*', 'smw_title = ' . $db->addQuotes($subject->getDBkey()) . ' AND ' . 'smw_namespace = ' . $db->addQuotes($subject->getNamespace()) . ' AND ' . 'smw_iw = ' . $db->addQuotes($subject->getInterwiki()) . ' AND ' . 'smw_subobject != ' . $db->addQuotes(''), __METHOD__); $subobjects = array(); // ... and delete them as well foreach ($res as $row) { $subobjects[] = $row->smw_id; $this->m_idCache->setId($row->smw_title, $row->smw_namespace, $row->smw_iw, $row->smw_subobject, 0); // deleted below foreach (self::getPropertyTables() as $proptable) { if ($proptable->idsubject) { $db->delete($proptable->name, array('s_id' => $row->smw_id), __METHOD__); } } } $db->freeResult($res); // free all affected subobjects in one call: if (count($subobjects) > 0) { $db->delete('smw_ids', array('smw_id' => $subobjects), __METHOD__); } wfRunHooks('smwDeleteSemanticData', array($subject)); }
/** * 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); } }
/** * Creates and returns a new SWLChangeSet instance from a database result * obtained by doing a select on swl_sets. * * @since 0.1 * * @param array $changeSetArray * * @return SWLChangeSet */ public static function newFromArray(array $changeSetArray) { $changeSet = new SWLChangeSet(SMWDIWikiPage::newFromTitle(Title::newFromID($changeSetArray['page_id'])), null, null, null, $changeSetArray['id'], new SWLEdit($changeSetArray['page_id'], $changeSetArray['user_name'], $changeSetArray['time'], $changeSetArray['editid'])); foreach ($changeSetArray['changes'] as $propName => $changes) { $property = SMWDIProperty::doUnserialize($propName, '__pro'); foreach ($changes as $change) { $changeSet->addChange($property, SWLPropertyChange::newFromSerialization($property, array_key_exists('old', $change) ? $change['old'] : null, array_key_exists('new', $change) ? $change['new'] : null)); } } return $changeSet; }
/** * Return serialised results in specified format. */ protected function getResultText(SMWQueryResult $res, $outputmode) { if ($this->mTreeProp === '') { $res->addErrors(array(wfMessage('srf-noparentprop')->inContentLanguage()->text())); return ''; } $store = $res->getStore(); // put everything in a list and set parent hashes // elements appearing more than once will be inserted more than once and // elements with more than one parent will be cloned for each parent, // but only one instance will ever be inserted with the hash and // only this instance will later be considered as a parent element in the tree $tree = array(); while ($row = $res->getNext()) { $element = new SRFTreeElement($row); $hash = $row[0]->getResultSubject()->getSerialization(); if (array_key_exists($hash, $tree)) { $hash = null; } $parents = $store->getPropertyValues($element->mRow[0]->getResultSubject(), SMWDIProperty::newFromUserLabel($this->mTreeProp)); if (empty($parents)) { // no parents: copy into tree as root level item if ($hash !== null) { $tree[$hash] = $element; } else { $tree[] = $element; } } else { // one or more parents: copy one copy per parent into tree foreach ($parents as $parent) { if ($hash !== null) { $tree[$hash] = $element; $hash = null; } else { $element = clone $element; $tree[] = $element; } $element->mParent = $parent->getSerialization(); } } } $rootElements = array(); // build pointers from parents to children and remove pointers to parents that don't exist in the tree foreach ($tree as $hash => $element) { if ($element->mParent !== null) { if (array_key_exists($element->mParent, $tree)) { $tree[$element->mParent]->mChildren[] = $element; } else { $element->mParent = null; $rootElements[$hash] = $element; } } else { $rootElements[$hash] = $element; } } $result = ''; $rownum = 0; // if a specific page was specified as root element of the tree if ($this->mRoot !== '') { // get the title object of the root page $rootTitle = Title::newFromText($this->mRoot); if ($rootTitle === null) { $res->addErrors(array(wfMessage('srf-rootinvalid')->params($this->mRoot)->inContentLanguage()->text())); return ''; } $rootSerialization = SMWDIWikiPage::newFromTitle($rootTitle)->getSerialization(); // find the root page in the tree and print it and its subtree if (array_key_exists($rootSerialization, $tree)) { $this->printElement($result, $tree[$rootSerialization], $rownum, $this->mStartLevel); } } else { // iterate through all tree elements foreach ($rootElements as $hash => $element) { // print current root element and its subtree $this->printElement($result, $element, $rownum, $this->mStartLevel); } } return $result; }