Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unfiled items api calls #152

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions controllers/ItemsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,15 @@ public function items() {
$this->permissions
);
}
// Unfiled items
else if ($this->subset == 'unfiled') {
$this->allowMethods(array('GET'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can always use […] instead of array(…) for new code


$title = "Unfiled items";
$itemIDs = Zotero_Items::getItemsWithoutCollection(
$this->objectLibraryID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to use Zotero_Items::search() like trash above, since otherwise other query parameters don't work. (E.g., people still need to be able to use the search bar, which uses q.) Zotero_Items::search() is quite convoluted, for complicated reasons, so let me know if something is unclear.

/unfiled also implies /top, but I think just setting $onlyTopLevel = true (the second parameter to search()) won't work, since that matches parent items of matching items, and all child items are technically unfiled, so it would match all items with children. So instead of that, the actual unfiled JOIN condition in search() should probably include a negative match on itemTopLevel.itemID, which contains child items mapped to top-level items, so that the actual matches are only top-level items. You can test, but I think this would be the unincorporated version of the SQL:

SELECT * FROM items I
    LEFT JOIN itemTopLevel ITL USING (itemID)
    LEFT JOIN collectionItems CI USING (itemID)
    WHERE libraryID=?
    AND ITL.itemID IS NULL
    AND CI.collectionID IS NULL

Copy link
Contributor Author

@abaevbog abaevbog Jun 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I added another parameter to search function to tell if it's an unfiled request, and a few conditionals to construct the query above. It seems to give us exactly what we want. I added a small commit with a few tests to check

);
}
else if ($this->subset == 'children') {
$item = Zotero_Items::getByLibraryAndKey($this->objectLibraryID, $this->objectKey);
if (!$item) {
Expand Down
7 changes: 7 additions & 0 deletions controllers/TagsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ public function tags() {
$results = Zotero_Tags::search($this->objectLibraryID, $tagParams);
}
}
// Unfiled
else if($this->scopeObjectKey == 'unfiled') {
$title = "Unfiled tags";
$items = Zotero_Items::getItemsWithoutCollection($this->objectLibraryID);
$this->queryParams['itemIDs'] = $items;
$results = Zotero_Tags::search($this->objectLibraryID, $this->queryParams);
}
// Tags within a collection or item
else if ($this->scopeObjectKey) {
switch ($this->scopeObject) {
Expand Down
4 changes: 4 additions & 0 deletions include/config/routes.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
$router->map('/users/i:objectUserID/publications/items/:objectKey/children', ['controller' => 'Items', 'extra' => ['publications' => true, 'subset' => 'children']]);
$router->map('/users/i:objectUserID/publications/items/:objectKey', ['controller' => 'Items', 'extra' => ['publications' => true]]);

// Unfiled items
$router->map('/users/i:objectUserID/items/unfiled', array('controller' => 'Items', 'extra' => array('subset' => 'unfiled')));
$router->map('/users/i:objectUserID/items/unfiled/tags', array('controller' => 'Tags', 'extra' => array('subset' => 'unfiled')));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

array() => []


// Other top-level URLs, with an optional key and subset
$router->map('/users/i:objectUserID/:controller/:objectKey/:subset');
$router->map('/groups/i:objectGroupID/:controller/:objectKey/:subset');
Expand Down
10 changes: 10 additions & 0 deletions model/Items.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -2574,6 +2574,16 @@ private static function loadItems($libraryID, $itemIDs=array()) {
}
}
}

public static function getItemsWithoutCollection($libraryID) {
$sql = "SELECT items.itemID
FROM items
LEFT JOIN collectionItems ON items.itemID = collectionItems.itemID
WHERE collectionItems.collectionID IS NULL
AND items.libraryID = ?;";
$items = Zotero_DB::columnQuery($sql, $libraryID, Zotero_Shards::getByLibraryID($libraryID));
return $items;
}


public static function getSortTitle($title) {
Expand Down