protected function loadRelations($reload = false) { if ($this->loaded['relations'] && !$reload) return; if (!$this->id) { return; } Z_Core::debug("Loading relations for item $this->id"); $this->loadPrimaryData(false, true); $itemURI = Zotero_URI::getItemURI($this); $relations = Zotero_Relations::getByURIs($this->libraryID, $itemURI); $relations = array_map(function ($rel) { return [$rel->predicate, $rel->object]; }, $relations); // Related items are bidirectional, so include any with this item as the object $reverseRelations = Zotero_Relations::getByURIs( $this->libraryID, false, Zotero_Relations::$relatedItemPredicate, $itemURI ); foreach ($reverseRelations as $rel) { $r = [$rel->predicate, $rel->subject]; // Only add if not already added in other direction if (!in_array($r, $relations)) { $relations[] = $r; } } // Also include any owl:sameAs relations with this item as the object // (as sent by client via classic sync) $reverseRelations = Zotero_Relations::getByURIs( $this->libraryID, false, Zotero_Relations::$linkedObjectPredicate, $itemURI ); foreach ($reverseRelations as $rel) { $relations[] = [$rel->predicate, $rel->subject]; } // TEMP: Get old-style related items // // Add related items $sql = "SELECT `key` FROM itemRelated IR " . "JOIN items I ON (IR.linkedItemID=I.itemID) " . "WHERE IR.itemID=?"; $relatedItemKeys = Zotero_DB::columnQuery($sql, $this->id, Zotero_Shards::getByLibraryID($this->libraryID)); if ($relatedItemKeys) { $prefix = Zotero_URI::getLibraryURI($this->libraryID) . "/items/"; $predicate = Zotero_Relations::$relatedItemPredicate; foreach ($relatedItemKeys as $key) { $relations[] = [$predicate, $prefix . $key]; } } // Reverse as well $sql = "SELECT `key` FROM itemRelated IR JOIN items I USING (itemID) WHERE IR.linkedItemID=?"; $reverseRelatedItemKeys = Zotero_DB::columnQuery( $sql, $this->id, Zotero_Shards::getByLibraryID($this->libraryID) ); if ($reverseRelatedItemKeys) { $prefix = Zotero_URI::getLibraryURI($this->libraryID) . "/items/"; $predicate = Zotero_Relations::$relatedItemPredicate; foreach ($reverseRelatedItemKeys as $key) { $relations[] = [$predicate, $prefix . $key]; } } $this->relations = $relations; $this->loaded['relations'] = true; $this->clearChanged('relations'); }
/** * Updates the collection's relations. No separate save of the collection is required. * * @param object $newRelations Object with predicates as keys and URIs as values * @param int $userID User making the change */ public function setRelations($newRelations, $userID) { if (!$this->_id) { throw new Exception('collectionID not set'); } // An empty array is allowed by updateFromJSON() if (is_array($newRelations) && empty($newRelations)) { $newRelations = new stdClass(); } Zotero_DB::beginTransaction(); // Get arrays from objects $oldRelations = get_object_vars($this->getRelations()); $newRelations = get_object_vars($newRelations); $toAdd = array_diff($newRelations, $oldRelations); $toRemove = array_diff($oldRelations, $newRelations); if (!$toAdd && !$toRemove) { Zotero_DB::commit(); return false; } $subject = Zotero_URI::getCollectionURI($this); foreach ($toAdd as $predicate => $object) { Zotero_Relations::add($this->libraryID, $subject, $predicate, $object); } foreach ($toRemove as $predicate => $object) { $relations = Zotero_Relations::getByURIs($this->libraryID, $subject, $predicate, $object); foreach ($relations as $relation) { Zotero_Relations::delete($this->libraryID, $relation->key); } } $this->updateVersion($userID); Zotero_DB::commit(); return true; }