Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions controllers/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,10 @@ public function init($extra) {
}
$this->objectLibraryID = Zotero_Groups::getLibraryIDFromGroupID($this->objectGroupID);
}
// Temporarily record shardID in GLOBALS so we can access it in header.inc.php
if (isset($this->objectLibraryID)) {
define('Z_TEMP_SHARD_MIGRATED', in_array(Zotero_Shards::getByLibraryID($this->objectLibraryID), $GLOBALS['updatedShards']));
}

$apiVersion = !empty($_SERVER['HTTP_ZOTERO_API_VERSION'])
? (int) $_SERVER['HTTP_ZOTERO_API_VERSION']
Expand Down
24 changes: 14 additions & 10 deletions controllers/ItemsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -378,19 +378,23 @@ public function items() {
if (!$tagIDs) {
$this->e404("Tag not found");
}

foreach ($tagIDs as $tagID) {
$tag = new Zotero_Tag;
$tag->libraryID = $this->objectLibraryID;
$tag->id = $tagID;
// Use a real tag name, in case case differs
if (!$title) {
$title = "Items of Tag ‘" . $tag->name . "’";
if (Z_TEMP_SHARD_MIGRATED) {
$linkedItemKeys = Zotero_Tags::loadLinkedItemsKeys($this->objectLibraryID, $this->scopeObjectName);
$itemKeys = array_merge($itemKeys, $linkedItemKeys);
}
else {
foreach ($tagIDs as $tagID) {
$tag = new Zotero_Tag;
$tag->libraryID = $this->objectLibraryID;
$tag->id = $tagID;
// Use a real tag name, in case case differs
if (!$title) {
$title = "Items of Tag ‘" . $tag->name . "’";
}
$itemKeys = array_merge($itemKeys, $tag->getLinkedItems(true));
}
$itemKeys = array_merge($itemKeys, $tag->getLinkedItems(true));
}
$itemKeys = array_unique($itemKeys);

break;

default:
Expand Down
29 changes: 24 additions & 5 deletions controllers/TagsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@ public function tags() {
}
$title = "Tags of '" . $item->getDisplayTitle() . "'";
$tagIDs = $item->getTags(true);
if (Z_TEMP_SHARD_MIGRATED) {
$tags = $item->getTags(true);
$tagIDs = array_map(function($tag) {
return $tag->id;
}, $tags);
} else {
$tagIDs = $item->getTags(true);
}
break;

default:
Expand All @@ -187,11 +195,22 @@ public function tags() {
$tagNames = !empty($this->queryParams['tag'])
? explode(' || ', $this->queryParams['tag']): array();
Zotero_DB::beginTransaction();
foreach ($tagNames as $tagName) {
$tagIDs = Zotero_Tags::getIDs($this->objectLibraryID, $tagName);
foreach ($tagIDs as $tagID) {
$tag = Zotero_Tags::get($this->objectLibraryID, $tagID, true);
Zotero_Tags::delete($this->objectLibraryID, $tag->key, $this->objectUserID);
// Different delete behavior depending on if we are on migrated shard or not
// because after migration $tag->key does not exist
if (Z_TEMP_SHARD_MIGRATED) {
$tagIDs = [];
foreach ($tagNames as $tagName) {
$tagIDs = array_merge($tagIDs, Zotero_Tags::getIDs($this->objectLibraryID, $tagName));
}
Zotero_Tags::bulkDelete($this->objectLibraryID, null, $tagIDs);
}
else {
foreach ($tagNames as $tagName) {
$tagIDs = Zotero_Tags::getIDs($this->objectLibraryID, $tagName);
foreach ($tagIDs as $tagID) {
$tag = Zotero_Tags::get($this->objectLibraryID, $tagID, true);
Zotero_Tags::delete($this->objectLibraryID, $tag->key, $this->objectUserID);
}
}
}
Zotero_DB::commit();
Expand Down
21 changes: 18 additions & 3 deletions include/header.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,23 @@ function zotero_autoload($className) {
else {
$auth = false;
}

$path = Z_ENV_BASE_PATH . 'model/';
$updatedShards = $GLOBALS['updatedShards'];
$newFiles = [
"Item.inc.php",
"Items.inc.php", "Cite.inc.php",
"Library.inc.php",
"Creator.inc.php",
"Creators.inc.php",
"Tag.inc.php",
"Tags.inc.php",
"TagsController.php"
];
if (defined('Z_TEMP_SHARD_MIGRATED') && !Z_TEMP_SHARD_MIGRATED && in_array($fileName, $newFiles)) {
$path = Z_ENV_BASE_PATH . 'model/old_';
}
else {
$path = Z_ENV_BASE_PATH . 'model/';
}
if ($auth) {
$path .= 'auth/';
}
Expand Down Expand Up @@ -74,7 +89,7 @@ function zotero_autoload($className) {
return;
}
}

$GLOBALS['updatedShards'] = [1];
spl_autoload_register('zotero_autoload');

// Read in configuration variables
Expand Down
71 changes: 71 additions & 0 deletions misc/db-updates/2023-07-17/creatorsAsNonClassicDataObjects
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/local/bin/php -d mysqlnd.net_read_timeout=86400
<?php
set_include_path("../../../include");
require("header.inc.php");

$shardHostID = $argv[1];
$startShard = $argv[2];
$stopShard = $argv[3];

Z_Core::$debug = true;

$shardIDs = Zotero_DB::columnQuery("SELECT shardID FROM shards WHERE shardHostID=? AND shardID >= ? AND shardID <= ? ORDER BY shardID", [$shardHostID, $startShard, $stopShard]);
foreach ($shardIDs as $shardID) {
echo "Shard: $shardID\n";

echo "Setting shard to readonly\n";
Zotero_DB::query("UPDATE shards SET state='readonly' WHERE shardID=?", $shardID);

echo "Waiting 60 seconds for requests to stop\n";
sleep(60);

// Creators
echo "Migrating creators\n";
// Drop foreign key constraint
Zotero_Admin_DB::query("ALTER TABLE `itemCreators` DROP CONSTRAINT `itemCreators_ibfk_1`", false, $shardID);
Zotero_Admin_DB::query("ALTER TABLE `itemCreators` DROP CONSTRAINT `itemCreators_ibfk_2`", false, $shardID);

// Create new itemCreators table
Zotero_Admin_DB::query("CREATE TABLE `itemCreatorsNew` (`itemID` BIGINT UNSIGNED NOT NULL, `firstName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, `lastName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, `fieldMode` tinyint(1) UNSIGNED DEFAULT NULL, `creatorTypeID` smallint(5) UNSIGNED NOT NULL, `orderIndex` smallint(5) UNSIGNED NOT NULL, PRIMARY KEY (`itemID`, `orderIndex`)) ENGINE=InnoDB DEFAULT CHARSET=utf8", false, $shardID);

// Add foreign key to item constraint
Zotero_Admin_DB::query("ALTER TABLE `itemCreatorsNew` ADD CONSTRAINT `itemCreators_ibfk_1` FOREIGN KEY (`itemID`) REFERENCES `items` (`itemID`) ON DELETE CASCADE", false, $shardID);

// Populate new table with data
Zotero_Admin_DB::query("INSERT INTO itemCreatorsNew (firstName, lastName, fieldMode, itemID, creatorTypeID, orderIndex ) SELECT firstName, lastName, fieldMode, itemID, creatorTypeID, orderIndex from creators INNER JOIN itemCreators USING (creatorID)", false, $shardID);

// Drop old creators tables
Zotero_Admin_DB::query("DROP TABLE itemCreators", false, $shardID);
Zotero_Admin_DB::query("DROP TABLE creators", false, $shardID);

// Rename old itemCreators table
Zotero_Admin_DB::query("RENAME TABLE itemCreatorsNew TO itemCreators", false, $shardID);

// Tags
echo "Migrating tags\n";
// Drop foreign key constraint
Zotero_Admin_DB::query("ALTER TABLE `itemTags` DROP CONSTRAINT `itemTags_ibfk_1`", false, $shardID);
Zotero_Admin_DB::query("ALTER TABLE `itemTags` DROP CONSTRAINT `itemTags_ibfk_2`", false, $shardID);

// Create new itemTags table
Zotero_Admin_DB::query("CREATE TABLE `itemTagsNew` ( `tagID` BIGINT UNSIGNED NOT NULL, `itemID` BIGINT UNSIGNED NOT NULL, `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, `type` tinyint(1) unsigned NOT NULL DEFAULT '0', `version` int(10) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (`tagID`, `itemID`), KEY `nameType` (`name`, `type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8", false, $shardID);

// Add foreign key to item constraint
Zotero_Admin_DB::query("ALTER TABLE `itemTagsNew` ADD CONSTRAINT `itemTags_ibfk_1` FOREIGN KEY (`itemID`) REFERENCES `items` (`itemID`) ON DELETE CASCADE", false, $shardID);

// Populate new table with data
Zotero_Admin_DB::query("INSERT INTO itemTagsNew (tagID, itemID, name, type, version) SELECT tagID, itemID, name, type, version from tags INNER JOIN itemTags USING (tagID)", false, $shardID);

// Drop old creators tables
Zotero_Admin_DB::query("DROP TABLE itemTags", false, $shardID);
Zotero_Admin_DB::query("DROP TABLE tags", false, $shardID);

// Rename old itemTags table
Zotero_Admin_DB::query("RENAME TABLE itemTagsNew TO itemTags", false, $shardID);


echo "Bringing shard back up\n";
Zotero_DB::query("UPDATE shards SET state='up' WHERE shardID=?", $shardID);
echo "Done with shard $shardID\n\n";
sleep(1);
}
2 changes: 1 addition & 1 deletion misc/shard.sql
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ CREATE TABLE `syncDeleteLogIDs` (

CREATE TABLE `syncDeleteLogKeys` (
`libraryID` int(10) unsigned NOT NULL,
`objectType` enum('collection','creator','item','relation','search','setting','tag','tagName') NOT NULL,
`objectType` enum('collection','item','relation','search','setting','tag','tagName') NOT NULL,
`key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`version` int(10) unsigned NOT NULL DEFAULT '1',
Expand Down
6 changes: 3 additions & 3 deletions model/Cite.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -297,17 +297,17 @@ public static function retrieveItem($zoteroItem) {
$authorID = Zotero_CreatorTypes::getPrimaryIDForType($zoteroItem->itemTypeID);
$creators = $zoteroItem->getCreators();
foreach ($creators as $creator) {
if ($creator['creatorTypeID'] == $authorID) {
if ($creator->creatorTypeID == $authorID) {
$creatorType = "author";
}
else {
$creatorType = Zotero_CreatorTypes::getName($creator['creatorTypeID']);
$creatorType = Zotero_CreatorTypes::getName($creator->creatorTypeID);
}

$creatorType = isset(self::$zoteroNameMap[$creatorType]) ? self::$zoteroNameMap[$creatorType] : false;
if (!$creatorType) continue;

$nameObj = array('family' => $creator['ref']->lastName, 'given' => $creator['ref']->firstName);
$nameObj = array('family' => $creator->lastName, 'given' => $creator->firstName);

if (isset($cslItem[$creatorType])) {
$cslItem[$creatorType][] = $nameObj;
Expand Down
10 changes: 3 additions & 7 deletions model/Collection.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ public function getRelations() {
* Returns all tags assigned to items in this collection
*/
public function getTags($asIDs=false) {
$sql = "SELECT tagID FROM tags JOIN itemTags USING (tagID)
$sql = "SELECT tagID FROM itemTags
JOIN collectionItems USING (itemID) WHERE collectionID=? ORDER BY name";
$tagIDs = Zotero_DB::columnQuery($sql, $this->id, Zotero_Shards::getByLibraryID($this->libraryID));
if (!$tagIDs) {
Expand All @@ -604,11 +604,7 @@ public function getTags($asIDs=false) {
return $tagIDs;
}

$tagObjs = array();
foreach ($tagIDs as $tagID) {
$tag = Zotero_Tags::get($tagID, true);
$tagObjs[] = $tag;
}
$tagObjs = Zotero_Tags::bulkGet($this->libraryID, $tagIDs);
return $tagObjs;
}

Expand All @@ -618,7 +614,7 @@ public function getTags($asIDs=false) {
* in this collection
*/
public function getTagItemCounts() {
$sql = "SELECT tagID, COUNT(*) AS numItems FROM tags JOIN itemTags USING (tagID)
$sql = "SELECT tagID, COUNT(*) AS numItems FROM itemTags
JOIN collectionItems USING (itemID) WHERE collectionID=? GROUP BY tagID";
$rows = Zotero_DB::query($sql, $this->id, Zotero_Shards::getByLibraryID($this->libraryID));
if (!$rows) {
Expand Down
Loading