Skip to content

Commit

Permalink
Add support for ink annotations [DB update]
Browse files Browse the repository at this point in the history
  • Loading branch information
dstillman committed Aug 27, 2021
1 parent 779b7aa commit 50992d2
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 7 deletions.
18 changes: 14 additions & 4 deletions controllers/MappingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ public function newItem() {
case 'highlight':
case 'note':
case 'image':
case 'ink':
break;

default:
Expand Down Expand Up @@ -259,10 +260,19 @@ public function newItem() {
$json['annotationColor'] = '';
$json['annotationPageLabel'] = '';
$json['annotationSortIndex'] = '00000|000000|00000';
$json['annotationPosition'] = [
'pageIndex' => 0,
'rects' => []
];
if ($annotationType == 'ink') {
$json['annotationPosition'] = [
'pageIndex' => 0,
'paths' => [],
'width' => 2
];
}
else {
$json['annotationPosition'] = [
'pageIndex' => 0,
'rects' => []
];
}
if ($annotationType == 'image') {
$json['annotationPosition']['width'] = 0;
$json['annotationPosition']['height'] = 0;
Expand Down
13 changes: 13 additions & 0 deletions misc/db-updates/2021-08-27/addInkAnnotationType
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/php -d mysqlnd.net_read_timeout=3600
<?php
set_include_path("../../../include");
require("header.inc.php");

$startShard = !empty($argv[1]) ? $argv[1] : 1;
$shardIDs = Zotero_DB::columnQuery("SELECT shardID FROM shards WHERE shardID >= ? ORDER BY shardID", $startShard);

foreach ($shardIDs as $shardID) {
echo "Shard: $shardID\n";

Zotero_Admin_DB::query("ALTER TABLE `itemAnnotations` CHANGE `type` `type` ENUM( 'highlight', 'note', 'image', 'ink' ) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, CHANGE `position` `position` TEXT CHARACTER SET ascii COLLATE ascii_bin NOT NULL", false, $shardID);
}
4 changes: 2 additions & 2 deletions misc/shard.sql
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ CREATE TABLE `itemAttachments` (
CREATE TABLE `itemAnnotations` (
`itemID` int(10) unsigned NOT NULL,
`parentItemID` int(10) unsigned NOT NULL,
`type` enum('highlight','note','image') CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`type` enum('highlight','note','image', 'ink') CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL,
`comment` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL,
`color` char(6) CHARACTER SET ascii NOT NULL,
`pageLabel` varchar(50) NOT NULL,
`sortIndex` varchar(18) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`position` varchar(20000) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`position` text CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
PRIMARY KEY (`itemID`),
KEY `parentItemID` (`parentItemID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Expand Down
16 changes: 15 additions & 1 deletion model/Item.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -3465,11 +3465,12 @@ private function setAnnotationField($field, $val) {
case 'highlight':
case 'note':
case 'image':
case 'ink':
break;

default:
throw new Exception(
"annotationType must be 'highlight', 'note', or 'image'",
"annotationType must be 'highlight', 'note', 'image', or 'ink'",
Z_ERROR_INVALID_INPUT
);
}
Expand Down Expand Up @@ -3511,6 +3512,19 @@ private function setAnnotationField($field, $val) {
Z_ERROR_INVALID_INPUT
);
}
// Check annotationPosition length
if ($field == 'position' && strlen($val) > Zotero_Items::$maxAnnotationPositionLength) {
throw new Exception(
// TODO: Restore once output isn't HTML-encoded
//"Annotation position '" . mb_substr($val, 0, 50) . "…' is too long",
"Annotation position is too long",
// TEMP: Return 400 until client can handle a specified annotation item,
// either by selecting the parent attachment or displaying annotation items
// in the items list
//Z_ERROR_FIELD_TOO_LONG
Z_ERROR_INVALID_INPUT
);
}
break;

default:
Expand Down
1 change: 1 addition & 0 deletions model/Items.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class Zotero_Items {

public static $maxDataValueLength = 65535;
public static $maxAnnotationTextLength = 25000;
public static $maxAnnotationPositionLength = 65535;

/**
*
Expand Down
69 changes: 69 additions & 0 deletions tests/remote/tests/API/3/AnnotationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,44 @@ public function test_should_save_an_image_annotation() {
}


public function test_should_save_an_ink_annotation() {
$paths = [
[173.54, 647.25, 175.88, 647.25, 181.32, 647.25, 184.44, 647.25, 191.44, 647.25, 197.67, 647.25, 203.89, 645.7, 206.23, 645.7, 210.12, 644.92, 216.34, 643.36, 218.68],
[92.4075, 245.284, 92.4075, 245.284, 92.4075, 246.034, 91.6575, 248.284, 91.6575, 253.534, 91.6575, 255.034, 91.6575, 261.034, 91.6575, 263.284, 95.4076, 271.535, 99.9077]
];
$json = [
'itemType' => 'annotation',
'parentItem' => self::$attachmentKey,
'annotationType' => 'ink',
'annotationColor' => '#ff8c19',
'annotationPageLabel' => '10',
'annotationSortIndex' => '00015|002431|00000',
'annotationPosition' => json_encode([
'pageIndex' => 123,
'paths' => $paths,
'width'=> 2
])
];
$response = API::userPost(
self::$config['userID'],
"items",
json_encode([$json]),
["Content-Type: application/json"]
);
$this->assert200ForObject($response);
$json = API::getJSONFromResponse($response);
$jsonData = $json['successful'][0]['data'];
$this->assertEquals('annotation', (string) $jsonData['itemType']);
$this->assertEquals('ink', $jsonData['annotationType']);
$this->assertEquals('#ff8c19', $jsonData['annotationColor']);
$this->assertEquals('10', $jsonData['annotationPageLabel']);
$this->assertEquals('00015|002431|00000', $jsonData['annotationSortIndex']);
$position = json_decode($jsonData['annotationPosition'], true);
$this->assertEquals(123, $position['pageIndex']);
$this->assertSame($paths, $position['paths']);
}


public function test_should_not_allow_changing_annotation_type() {
// Create highlight annotation
$json = [
Expand Down Expand Up @@ -385,6 +423,37 @@ public function test_should_clear_annotation_fields() {
}


public function test_should_reject_long_position() {
$positionJSON = json_encode([
'pageIndex' => 123,
'rects' => [
range(0, 13000)
]
]);
$json = [
'itemType' => 'annotation',
'parentItem' => self::$attachmentKey,
'annotationType' => 'ink',
'annotationSortIndex' => '00015|002431|00000',
'annotationColor' => '#ff8c19',
'annotationPosition' => $positionJSON
];
$response = API::userPost(
self::$config['userID'],
"items",
json_encode([$json]),
["Content-Type: application/json"]
);
// TEMP: See note in Item.inc.php
//$this->assert413ForObject(
$this->assert400ForObject(
// TODO: Restore once output isn't HTML-encoded
//$response, "Annotation position '" . mb_substr($positionJSON, 0, 50) . "…' is too long", 0
$response, "Annotation position is too long", 0
);
}


public function test_should_reject_long_text() {
$json = [
'itemType' => 'annotation',
Expand Down

0 comments on commit 50992d2

Please sign in to comment.