Example #1
0
 public function testExistsByLibraryAndKey()
 {
     $this->assertFalse(Zotero_Items::existsByLibraryAndKey(self::$config['userLibraryID'], "AAAAAAAA"));
     $item = new Zotero_Item();
     $item->libraryID = self::$config['userLibraryID'];
     $item->itemTypeID = Zotero_ItemTypes::getID("book");
     $item->save();
     $key = $item->key;
     $this->assertTrue(Zotero_Items::existsByLibraryAndKey(self::$config['userLibraryID'], $key));
     Zotero_Items::delete(self::$config['userLibraryID'], $key);
     $this->assertFalse(Zotero_Items::existsByLibraryAndKey(self::$config['userLibraryID'], $key));
 }
Example #2
0
 /**
  * Import an item by URL using the translation server
  *
  * Initial request:
  *
  * {
  *   "url": "http://..."
  * }
  *
  * Item selection for multi-item results:
  *
  * {
  *   "url": "http://...",
  *   "token": "<token>"
  *   "items": {
  *     "0": "Item 1 Title",
  *     "3": "Item 2 Title"
  *   }
  * }
  *
  * Returns an array of keys of added items (like updateMultipleFromJSON) or an object
  * with a 'select' property containing an array of titles for multi-item results
  */
 public static function addFromURL($json, $requestParams, $libraryID, $userID, Zotero_Permissions $permissions, $translationToken)
 {
     if (!$translationToken) {
         throw new Exception("Translation token not provided");
     }
     self::validateJSONURL($json, $requestParams);
     $cacheKey = 'addFromURLKeyMappings_' . md5($json->url . $translationToken);
     // Replace numeric keys with URLs for selected items
     if (isset($json->items) && $requestParams['v'] >= 2) {
         $keyMappings = Z_Core::$MC->get($cacheKey);
         $newItems = [];
         foreach ($json->items as $number => $title) {
             if (!isset($keyMappings[$number])) {
                 throw new Exception("Index '{$number}' not found for URL and token", Z_ERROR_INVALID_INPUT);
             }
             $url = $keyMappings[$number];
             $newItems[$url] = $title;
         }
         $json->items = $newItems;
     }
     $response = Zotero_Translate::doWeb($json->url, $translationToken, isset($json->items) ? $json->items : null);
     if (!$response || is_int($response)) {
         return $response;
     }
     if (isset($response->items)) {
         if ($requestParams['v'] >= 2) {
             $response = $response->items;
             for ($i = 0, $len = sizeOf($response); $i < $len; $i++) {
                 // Assign key here so that we can add notes if necessary
                 do {
                     $itemKey = Zotero_ID::getKey();
                 } while (Zotero_Items::existsByLibraryAndKey($libraryID, $itemKey));
                 $response[$i]->key = $itemKey;
                 // Pull out notes and stick in separate items
                 if (isset($response[$i]->notes)) {
                     foreach ($response[$i]->notes as $note) {
                         $newNote = (object) ["itemType" => "note", "note" => $note->note, "parentItem" => $itemKey];
                         $response[] = $newNote;
                     }
                     unset($response[$i]->notes);
                 }
                 // TODO: link attachments, or not possible from translation-server?
             }
         }
         try {
             self::validateMultiObjectJSON($response, $requestParams);
         } catch (Exception $e) {
             error_log($e);
             error_log(json_encode($response));
             throw new Exception("Invalid JSON from doWeb()");
         }
     } else {
         if (isset($response->select)) {
             // Replace URLs with numeric keys for found items
             if ($requestParams['v'] >= 2) {
                 $keyMappings = [];
                 $newItems = new stdClass();
                 $number = 0;
                 foreach ($response->select as $url => $title) {
                     $keyMappings[$number] = $url;
                     $newItems->{$number} = $title;
                     $number++;
                 }
                 Z_Core::$MC->set($cacheKey, $keyMappings, 600);
                 $response->select = $newItems;
             }
             return $response;
         } else {
             throw new Exception("Invalid return value from doWeb()");
         }
     }
     return self::updateMultipleFromJSON($response, $requestParams, $libraryID, $userID, $permissions, false, null);
 }
Example #3
0
    private function loadPrimaryData($allowFail = false)
    {
        Z_Core::debug("Loading primary data for item {$this->libraryID}/{$this->key}");
        if ($this->loaded['primaryData']) {
            throw new Exception("Primary data already loaded for item {$this->libraryID}/{$this->key}");
        }
        $libraryID = $this->libraryID;
        $id = $this->id;
        $key = $this->key;
        if (!$libraryID) {
            throw new Exception("Library ID not set");
        }
        if (!$id && !$key) {
            throw new Exception("ID or key not set");
        }
        // Use cached check for existence if possible
        if ($libraryID && $key) {
            if (!Zotero_Items::existsByLibraryAndKey($libraryID, $key)) {
                $this->loaded['primaryData'] = true;
                if ($allowFail) {
                    return false;
                }
                throw new Exception("Item " . ($id ? $id : "{$libraryID}/{$key}") . " not found");
            }
        }
        $columns = array();
        foreach (Zotero_Items::$primaryFields as $field) {
            $colSQL = '';
            if (is_null($field == 'itemID' ? $this->id : $this->{$field})) {
                switch ($field) {
                    case 'itemID':
                    case 'itemTypeID':
                    case 'dateAdded':
                    case 'dateModified':
                    case 'libraryID':
                    case 'key':
                    case 'serverDateModified':
                        $colSQL = 'I.' . $field;
                        break;
                    case 'itemVersion':
                        $colSQL = 'I.version AS itemVersion';
                        break;
                    case 'numNotes':
                        $colSQL = '(SELECT COUNT(*) FROM itemNotes INo
							WHERE sourceItemID=I.itemID AND INo.itemID NOT IN
							(SELECT itemID FROM deletedItems)) AS numNotes';
                        break;
                    case 'numAttachments':
                        $colSQL = '(SELECT COUNT(*) FROM itemAttachments IA
							WHERE sourceItemID=I.itemID AND IA.itemID NOT IN
							(SELECT itemID FROM deletedItems)) AS numAttachments';
                        break;
                    case 'numNotes':
                        $colSQL = '(SELECT COUNT(*) FROM itemNotes
									WHERE sourceItemID=I.itemID) AS numNotes';
                        break;
                    case 'numAttachments':
                        $colSQL = '(SELECT COUNT(*) FROM itemAttachments
									WHERE sourceItemID=I.itemID) AS numAttachments';
                        break;
                }
                if ($colSQL) {
                    $columns[] = $colSQL;
                }
            }
        }
        if (!$columns) {
            Z_Core::debug("No primary columns to load");
            return;
        }
        $sql = 'SELECT ' . implode(', ', $columns) . " FROM items I WHERE ";
        if ($id) {
            if (!is_numeric($id)) {
                trigger_error("Invalid itemID '{$id}'", E_USER_ERROR);
            }
            $sql .= "itemID=?";
            $stmt = Zotero_DB::getStatement($sql, 'loadPrimaryData_id', Zotero_Shards::getByLibraryID($libraryID));
            $row = Zotero_DB::rowQueryFromStatement($stmt, array($id));
        } else {
            if (!is_numeric($libraryID)) {
                trigger_error("Invalid libraryID '{$libraryID}'", E_USER_ERROR);
            }
            if (!preg_match('/[A-Z0-9]{8}/', $key)) {
                trigger_error("Invalid key '{$key}'!", E_USER_ERROR);
            }
            $sql .= "libraryID=? AND `key`=?";
            $stmt = Zotero_DB::getStatement($sql, 'loadPrimaryData_key', Zotero_Shards::getByLibraryID($libraryID));
            $row = Zotero_DB::rowQueryFromStatement($stmt, array($libraryID, $key));
        }
        $this->loaded['primaryData'] = true;
        if (!$row) {
            if ($allowFail) {
                return false;
            }
            throw new Exception("Item " . ($id ? $id : "{$libraryID}/{$key}") . " not found");
        }
        $this->loadFromRow($row);
        return true;
    }
Example #4
0
 public function setLinkedItems($newKeys)
 {
     if (!$this->linkedItemsLoaded) {
         $this->loadLinkedItems();
     }
     if (!is_array($newKeys)) {
         throw new Exception('$newKeys must be an array');
     }
     $oldKeys = $this->getLinkedItems(true);
     if (!$newKeys && !$oldKeys) {
         Z_Core::debug("No linked items added", 4);
         return false;
     }
     $addKeys = array_diff($newKeys, $oldKeys);
     $removeKeys = array_diff($oldKeys, $newKeys);
     // Make sure all new keys exist
     foreach ($addKeys as $key) {
         if (!Zotero_Items::existsByLibraryAndKey($this->libraryID, $key)) {
             // Return a specific error for a wrong-library tag issue
             // that I can't reproduce
             throw new Exception("Linked item {$key} of tag " . "{$this->libraryID}/{$this->key} not found", Z_ERROR_TAG_LINKED_ITEM_NOT_FOUND);
         }
     }
     if ($addKeys || $removeKeys) {
         $this->prepFieldChange('linkedItems');
     } else {
         Z_Core::debug('Linked items not changed', 4);
         return false;
     }
     $this->linkedItems = $newKeys;
     return true;
 }