public static function init() { if (!self::$objectType) { throw new Exception('self::$objectType must be set before calling Zotero_DataObjects initializer'); } self::$ObjectType = ucwords(self::$objectType); self::$objectTypePlural = \Zotero\DataObjectUtilities::getObjectTypePlural(self::$objectType); self::$ObjectTypePlural = ucwords(self::$objectTypePlural); self::$idColumn = self::$objectType . "ID"; self::$table = isset(self::$_table) ? self::$_table : self::$objectTypePlural; self::$ObjectClass = "Zotero_" . self::$objectType; self::$primaryFields = array_keys(self::$primaryDataSQLParts); self::$primaryDataSQLFrom = " " . (isset(self::$_primaryDataSQLFrom) ? self::$_primaryDataSQLFrom : "FROM " . self::$table . " O") . " " . self::$primaryDataSQLWhere; }
/** * @param object $object Zotero object (Zotero_Item, Zotero_Collection, Zotero_Search, Zotero_Setting) * @param object $json JSON object to check * @param array $requestParams * @param int $requireVersion If 0, don't require; if 1, require if there's * an object key property in the JSON; if 2, * always require */ public static function checkJSONObjectVersion($object, $json, $requestParams, $requireVersion) { $objectType = \Zotero\DataObjectUtilities::getTypeFromObject($object); if (!in_array($objectType, array('item', 'collection', 'search', 'setting'))) { throw new Exception("Invalid object type"); } $oldKeyProp = $objectType . "Key"; $oldVersionProp = $objectType == 'setting' ? 'version' : $objectType . "Version"; $newKeyProp = 'key'; $newVersionProp = 'version'; if ($requestParams['v'] >= 3) { $keyProp = $newKeyProp; $versionProp = $newVersionProp; // Disallow old properties if (isset($json->{$oldKeyProp})) { throw new Exception("'{$oldKeyProp}' property is now '" . $newKeyProp . "'", Z_ERROR_INVALID_INPUT); } else { if (isset($json->{$oldVersionProp}) && $oldVersionProp != $newVersionProp) { throw new Exception("'{$oldVersionProp}' property is now '" . $newVersionProp . "'", Z_ERROR_INVALID_INPUT); } } } else { $keyProp = $oldKeyProp; $versionProp = $oldVersionProp; // Disallow new properties if (isset($json->{$newKeyProp})) { throw new Exception("Invalid property '{$newKeyProp}'", Z_ERROR_INVALID_INPUT); } else { if (isset($json->{$newVersionProp}) && $oldVersionProp != $newVersionProp) { throw new Exception("Invalid property '{$newVersionProp}'", Z_ERROR_INVALID_INPUT); } } } if (isset($json->{$versionProp})) { if ($requestParams['v'] < 2) { throw new Exception("Invalid property '{$versionProp}'", Z_ERROR_INVALID_INPUT); } if (!is_numeric($json->{$versionProp})) { throw new Exception("'{$versionProp}' must be an integer", Z_ERROR_INVALID_INPUT); } if (!isset($json->{$keyProp}) && $objectType != 'setting' && !$object->key) { throw new Exception("'{$versionProp}' is valid only if {$objectType} key is provided", Z_ERROR_INVALID_INPUT); } $originalVersion = Zotero_Libraries::getOriginalVersion($object->libraryID); $updatedVersion = Zotero_Libraries::getUpdatedVersion($object->libraryID); // Make sure the object hasn't been modified since the specified version if ($object->version > $json->{$versionProp}) { // Unless it was modified in this request if ($updatedVersion != $originalVersion && $object->version == $updatedVersion) { return; } throw new HTTPException(ucwords($objectType) . " has been modified since specified version " . "(expected {$json->{$versionProp}}, found {$object->version})", 412); } else { if ($json->{$versionProp} > 0 && !$object->version) { throw new HTTPException(ucwords($objectType) . " doesn't exist (expected version {$json->{$versionProp}}; use 0 instead)", 404); } } } else { if ($requireVersion == 1 && isset($json->{$keyProp})) { if ($objectType == 'setting') { throw new HTTPException("Either If-Unmodified-Since-Version or " . "'{$versionProp}' property must be provided", 428); } else { throw new HTTPException("Either If-Unmodified-Since-Version or " . "'{$versionProp}' property must be provided for " . "'{$keyProp}'-based writes", 428); } } else { if ($requireVersion == 2) { throw new HTTPException("Either If-Unmodified-Since-Version or " . "'{$versionProp}' property must be provided for " . "single-{$objectType} writes", 428); } } } }
protected function handleObjectWrite($objectType, $obj = null) { if (!is_object($obj) && !is_null($obj)) { throw new Exception('$obj must be a data object or null'); } $objectTypePlural = \Zotero\DataObjectUtilities::getObjectTypePlural($objectType); $objectsClassName = "Zotero_" . ucwords($objectTypePlural); $json = !empty($this->body) ? $this->jsonDecode($this->body) : false; $objectVersionValidated = $this->checkSingleObjectWriteVersion($objectType, $obj, $json); $this->libraryVersion = Zotero_Libraries::getUpdatedVersion($this->objectLibraryID); // Update item if ($this->method == 'PUT' || $this->method == 'PATCH') { if ($this->apiVersion < 2) { $this->allowMethods(['PUT']); } if (!$obj) { $className = "Zotero_" . ucwords($objectType); $obj = new $className(); $obj->libraryID = $this->objectLibraryID; $obj->key = $this->objectKey; } if ($objectType == 'item') { $changed = Zotero_Items::updateFromJSON($obj, $json, null, $this->queryParams, $this->userID, $objectVersionValidated ? 0 : 2, $this->method == 'PATCH'); } else { $changed = $objectsClassName::updateFromJSON($obj, $json, $this->queryParams, $this->userID, $objectVersionValidated ? 0 : 2, $this->method == 'PATCH'); } // If not updated, return the original library version if (!$changed) { $this->libraryVersion = Zotero_Libraries::getOriginalVersion($this->objectLibraryID); } if ($cacheKey = $this->getWriteTokenCacheKey()) { Z_Core::$MC->set($cacheKey, true, $this->writeTokenCacheTime); } } else { if ($this->method == 'DELETE') { $objectsClassName::delete($this->objectLibraryID, $this->objectKey); } else { throw new Exception("Unexpected method {$this->method}"); } } if ($this->apiVersion >= 2 || $this->method == 'DELETE') { $this->e204(); } return $obj; }
/** * Set the key of the parent object * * @param {String|false} [key=false] * @return {Boolean} True if changed, false if stayed the same */ public function setParentKey($key) { if ($this->objectType == 'search') { throw new Exception("Cannot set parent key for search"); } $key = \Zotero\DataObjectUtilities::checkKey($key); if (!$key) { $key = false; } if ($key === $this->_parentKey || !$this->_parentKey && !$key) { return false; } Z_Core::debug("Changing parent key from '{$this->_parentKey}' to '{$key}' for " . $this->objectType . " " . $this->libraryKey); //$this->_markFieldChange('parentKey', this._parentKey); $this->changed['parentKey'] = true; $this->_parentKey = $key; $this->_parentID = null; return true; }