/** * Helper function to compute from and where strings for a DB query so that * only rows of the given value object match. The parameter $tableindex * counts that tables used in the query to avoid duplicate table names. The * parameter $proptable provides the SMWSQLStore2Table object that is * queried. * * @todo Maybe do something about redirects. The old code was * $oid = $this->getSMWPageID($value->getDBkey(),$value->getNamespace(),$value->getInterwiki(),false); * * @param string $from * @param string $where * @param SMWSQLStore2Table $proptable * @param SMWDataItem $value * @param integer $tableindex */ protected function prepareValueQuery(&$from, &$where, $proptable, $value, $tableindex = 1) { $db = wfGetDB(DB_SLAVE); if ($value instanceof SMWDIContainer) { // recursive handling of containers $keys = array_keys($proptable->objectfields); $joinfield = "t{$tableindex}." . reset($keys); // this must be a type 'p' object $proptables = self::getPropertyTables(); $semanticData = $value->getSemanticData(); foreach ($semanticData->getProperties() as $subproperty) { $tableid = self::findPropertyTableID($subproperty); $subproptable = $proptables[$tableid]; foreach ($semanticData->getPropertyValues($subproperty) as $subvalue) { $tableindex++; if ($subproptable->idsubject) { // simply add property table to check values $from .= " INNER JOIN " . $db->tableName($subproptable->name) . " AS t{$tableindex} ON t{$tableindex}.s_id={$joinfield}"; } else { // exotic case with table that uses subject title+namespace in container object (should never happen in SMW core) $from .= " INNER JOIN " . $db->tableName('smw_ids') . " AS ids{$tableindex} ON ids{$tableindex}.smw_id={$joinfield}" . " INNER JOIN " . $db->tableName($subproptable->name) . " AS t{$tableindex} ON " . "t{$tableindex}.s_title=ids{$tableindex}.smw_title AND t{$tableindex}.s_namespace=ids{$tableindex}.smw_namespace"; } if ($subproptable->fixedproperty == false) { // the ID we get should be !=0, so no point in filtering the converse $where .= ($where ? ' AND ' : '') . "t{$tableindex}.p_id=" . $db->addQuotes($this->getSMWPropertyID($subproperty)); } $this->prepareValueQuery($from, $where, $subproptable, $subvalue, $tableindex); } } } elseif (!is_null($value)) { // add conditions for given value /// TODO This code still partly supports some abandoned flexibility of the DBkeys system; /// this is not very clean (see break; below) and should be improved $dbkeys = SMWCompatibilityHelpers::getDBkeysFromDataItem($value); $i = 0; foreach ($proptable->objectfields as $fieldname => $typeid) { if ($i >= count($dbkeys)) { break; } if ($typeid == 'p') { // Special case: page id, resolve this in advance $oid = $this->getSMWPageID($value->getDBkey(), $value->getNamespace(), $value->getInterwiki(), $value->getSubobjectName()); $where .= ($where ? ' AND ' : '') . "t{$tableindex}.{$fieldname}=" . $db->addQuotes($oid); break; } elseif ($typeid != 'l') { // plain value, but not a text blob $where .= ($where ? ' AND ' : '') . "t{$tableindex}.{$fieldname}=" . $db->addQuotes($dbkeys[$i]); } $i += 1; } } }
/** * Create an SWMExpElement that encodes the data of the given * dataitem object. This method is meant to be used when exporting a * dataitem as a subject or object. To get the URI of a property, use * SMWExporter::getResourceElementForProperty() or * SMWExporter::getSpecialPropertyResource(). * * @param $dataItem SMWDataItem * @return SMWExpElement */ public static function getDataItemExpElement(SMWDataItem $dataItem) { switch ($dataItem->getDIType()) { case SMWDataItem::TYPE_NUMBER: $lit = new SMWExpLiteral($dataItem->getNumber(), 'http://www.w3.org/2001/XMLSchema#double', $dataItem); return $lit; case SMWDataItem::TYPE_STRING: case SMWDataItem::TYPE_BLOB: $lit = new SMWExpLiteral(smwfHTMLtoUTF8($dataItem->getString()), 'http://www.w3.org/2001/XMLSchema#string', $dataItem); return $lit; case SMWDataItem::TYPE_BOOLEAN: $xsdvalue = $dataItem->getBoolean() ? 'true' : 'false'; $lit = new SMWExpLiteral($xsdvalue, 'http://www.w3.org/2001/XMLSchema#boolean', $dataItem); return $lit; case SMWDataItem::TYPE_URI: $res = new SMWExpResource($dataItem->getURI(), $dataItem); return $res; case SMWDataItem::TYPE_TIME: $gregorianTime = $dataItem->getForCalendarModel(SMWDITime::CM_GREGORIAN); if ($gregorianTime->getYear() > 0) { $xsdvalue = str_pad($gregorianTime->getYear(), 4, "0", STR_PAD_LEFT); } else { $xsdvalue = '-' . str_pad(1 - $gregorianTime->getYear(), 4, "0", STR_PAD_LEFT); } $xsdtype = 'http://www.w3.org/2001/XMLSchema#gYear'; if ($gregorianTime->getPrecision() >= SMWDITime::PREC_YM) { $xsdtype = 'http://www.w3.org/2001/XMLSchema#gYearMonth'; $xsdvalue .= '-' . str_pad($gregorianTime->getMonth(), 2, "0", STR_PAD_LEFT); if ($gregorianTime->getPrecision() >= SMWDITime::PREC_YMD) { $xsdtype = 'http://www.w3.org/2001/XMLSchema#date'; $xsdvalue .= '-' . str_pad($gregorianTime->getDay(), 2, "0", STR_PAD_LEFT); if ($gregorianTime->getPrecision() == SMWDITime::PREC_YMDT) { $xsdtype = 'http://www.w3.org/2001/XMLSchema#dateTime'; $xsdvalue .= 'T' . sprintf("%02d", $gregorianTime->getHour()) . ':' . sprintf("%02d", $gregorianTime->getMinute()) . ':' . sprintf("%02d", $gregorianTime->getSecond()); } } } $xsdvalue .= 'Z'; $lit = new SMWExpLiteral($xsdvalue, $xsdtype, $gregorianTime); return $lit; case SMWDataItem::TYPE_GEO: /// TODO return null; case SMWDataItem::TYPE_CONTAINER: return self::makeExportData($dataItem->getSemanticData()); case SMWDataItem::TYPE_WIKIPAGE: return self::getResourceElementForWikiPage($dataItem); case SMWDataItem::TYPE_CONCEPT: /// TODO return null; case SMWDataItem::TYPE_PROPERTY: return self::getResourceElementForProperty($dataItem); } }
/** * Helper function to compute from and where strings for a DB query so that * only rows of the given value object match. The parameter $tableindex * counts that tables used in the query to avoid duplicate table names. The * parameter $proptable provides the SMWSQLStore3Table object that is * queried. * * @todo Maybe do something about redirects. The old code was * $oid = $this->store->smwIds->getSMWPageID($value->getDBkey(),$value->getNamespace(),$value->getInterwiki(),false); * * @param string $from * @param string $where * @param SMWSQLStore3Table $proptable * @param SMWDataItem $value * @param integer $tableindex */ protected function prepareValueQuery(&$from, &$where, $proptable, $value, $tableindex = 1) { $db = wfGetDB(DB_SLAVE); if ($value instanceof SMWDIContainer) { // recursive handling of containers $keys = array_keys($proptable->getFields($this->store)); $joinfield = "t{$tableindex}." . reset($keys); // this must be a type 'p' object $proptables = SMWSQLStore3::getPropertyTables(); $semanticData = $value->getSemanticData(); foreach ($semanticData->getProperties() as $subproperty) { $tableid = SMWSQLStore3::findPropertyTableID($subproperty); $subproptable = $proptables[$tableid]; foreach ($semanticData->getPropertyValues($subproperty) as $subvalue) { $tableindex++; if ($subproptable->idsubject) { // simply add property table to check values $from .= " INNER JOIN " . $db->tableName($subproptable->name) . " AS t{$tableindex} ON t{$tableindex}.s_id={$joinfield}"; } else { // exotic case with table that uses subject title+namespace in container object (should never happen in SMW core) $from .= " INNER JOIN " . $db->tableName('smw_ids') . " AS ids{$tableindex} ON ids{$tableindex}.smw_id={$joinfield}" . " INNER JOIN " . $db->tableName($subproptable->name) . " AS t{$tableindex} ON " . "t{$tableindex}.s_title=ids{$tableindex}.smw_title AND t{$tableindex}.s_namespace=ids{$tableindex}.smw_namespace"; } if ($subproptable->fixedproperty == false) { // the ID we get should be !=0, so no point in filtering the converse $where .= ($where ? ' AND ' : '') . "t{$tableindex}.p_id=" . $db->addQuotes($this->store->smwIds->getSMWPropertyID($subproperty)); } $this->prepareValueQuery($from, $where, $subproptable, $subvalue, $tableindex); } } } elseif (!is_null($value)) { // add conditions for given value $diHandler = $this->store->getDataItemHandlerForDIType($value->getDIType()); foreach ($diHandler->getWhereConds($value) as $fieldname => $value) { $where .= ($where ? ' AND ' : '') . "t{$tableindex}.{$fieldname}=" . $db->addQuotes($value); } } }
/** * Remove a value for a property identified by its SMWDataItem object. * This method removes a property-value specified by the property and * dataitem. If there are no more property-values for this property it * also removes the property from the mProperties. * * @note There is no check whether the type of the given data item * agrees with the type of the property. Since property types can * change, all parts of SMW are prepared to handle mismatched data item * types anyway. * * @param $property SMWDIProperty * @param $dataItem SMWDataItem * * @since 1.8 */ public function removePropertyObjectValue(SMWDIProperty $property, SMWDataItem $dataItem) { //delete associated subSemanticData if ($dataItem instanceof SMWDIContainer) { $this->removeSubSemanticData($dataItem->getSemanticData()); $dataItem = $dataItem->getSemanticData()->getSubject(); } if ($property->isInverse()) { // inverse properties cannot be used for annotation return; } if (!array_key_exists($property->getKey(), $this->mPropVals) || !array_key_exists($property->getKey(), $this->mProperties)) { return; } if ($this->mNoDuplicates) { //this didn't get checked for my tests, but should work unset($this->mPropVals[$property->getKey()][$dataItem->getHash()]); } else { foreach ($this->mPropVals[$property->getKey()] as $index => $di) { if ($di->equals($dataItem)) { unset($this->mPropVals[$property->getKey()][$index]); } } $this->mPropVals[$property->getKey()] = array_values($this->mPropVals[$property->getKey()]); } if ($this->mPropVals[$property->getKey()] === array()) { unset($this->mProperties[$property->getKey()]); unset($this->mPropVals[$property->getKey()]); } }