From 0da9202a42d2dd46569ab1a4f3188dd8b702df75 Mon Sep 17 00:00:00 2001 From: Eddie Kohler Date: Wed, 26 Jul 2023 14:40:38 -0400 Subject: [PATCH] Add PaperStorage.{npages,width,height}. --- batch/updatedocmetadata.php | 16 +++++++++++- src/conference.php | 22 ++++++++++++++--- src/contactlist.php | 2 +- src/documentinfo.php | 49 +++++++++++++++++++++++++++++++++---- src/paperinfo.php | 31 ++++++++--------------- src/reviewinfo.php | 2 +- src/schema.sql | 5 +++- src/updateschema.php | 6 +++++ 8 files changed, 99 insertions(+), 34 deletions(-) diff --git a/batch/updatedocmetadata.php b/batch/updatedocmetadata.php index f207a190a7..c807dfa6cc 100644 --- a/batch/updatedocmetadata.php +++ b/batch/updatedocmetadata.php @@ -20,7 +20,7 @@ function __construct(Conf $conf, $arg) { private function run_images() { - $result = $this->conf->qe("select " . PaperInfo::document_query() . " from PaperStorage where mimetype like 'image/%'"); + $result = $this->conf->qe("select " . $this->conf->document_query_fields() . " from PaperStorage where mimetype like 'image/%'"); $docs = []; while (($doc = DocumentInfo::fetch($result, $this->conf))) { $docs[] = $doc; @@ -60,9 +60,23 @@ private function run_images_subset($docs) { } } + private function run_pdf() { + $result = $this->conf->qe("select " . $this->conf->document_query_fields() . " from PaperStorage where mimetype='application/pdf'"); + $docs = []; + while (($doc = DocumentInfo::fetch($result, $this->conf))) { + $docs[] = $doc; + } + Dbl::free($result); + while (!empty($docs)) { + $doc = array_pop($docs); + $doc->npages(); + } + } + /** @return int */ function run() { $this->run_images(); + $this->run_pdf(); return 0; } diff --git a/src/conference.php b/src/conference.php index 00299ea681..e94508ccce 100644 --- a/src/conference.php +++ b/src/conference.php @@ -341,7 +341,7 @@ function __load_settings() { function load_settings() { $this->__load_settings(); - if ($this->sversion < 275) { + if ($this->sversion < 276) { $old_nerrors = Dbl::$nerrors; while ((new UpdateSchema($this))->run()) { usleep(50000); @@ -3751,7 +3751,8 @@ function make_csvg($basename, $flags = 0) { // Paper search // - function query_ratings() { + /** @return string */ + function rating_signature_query() { if ($this->setting("rev_ratings") !== REV_RATINGS_NONE) { return "coalesce((select group_concat(contactId, ' ', rating) from ReviewRating where paperId=PaperReview.paperId and reviewId=PaperReview.reviewId),'')"; } else { @@ -3759,10 +3760,23 @@ function query_ratings() { } } - function query_all_reviewer_preference() { + /** @return string */ + function all_reviewer_preference_query() { return "group_concat(contactId,' ',preference,' ',coalesce(expertise,'.'))"; } + /** @return string */ + function document_query_fields() { + return "paperId, paperStorageId, timestamp, mimetype, sha1, crc32, documentType, filename, infoJson, size, filterType, originalStorageId, inactive" + . ($this->sversion >= 276 ? ", npages, width, height" : ""); + } + + /** @return string */ + function document_metadata_query_fields() { + return "infoJson" . ($this->sversion >= 276 ? ", npages, width, height" : ""); + } + + /** @param array{paperId?:list|PaperID_SearchTerm,where?:string} $options * @return Dbl_Result */ function paper_result($options, Contact $user = null) { @@ -3908,7 +3922,7 @@ function paper_result($options, Contact $user = null) { } if ($options["allReviewerPreference"] ?? false) { - $cols[] = "coalesce((select " . $this->query_all_reviewer_preference() . " from PaperReviewPreference force index (primary) where PaperReviewPreference.paperId=Paper.paperId), '') allReviewerPreference"; + $cols[] = "coalesce((select " . $this->all_reviewer_preference_query() . " from PaperReviewPreference force index (primary) where PaperReviewPreference.paperId=Paper.paperId), '') allReviewerPreference"; } if ($options["allConflictType"] ?? false) { diff --git a/src/contactlist.php b/src/contactlist.php index 8339b9e4df..d85a34aadb 100644 --- a/src/contactlist.php +++ b/src/contactlist.php @@ -641,7 +641,7 @@ private function collect_paper_data() { $pids[] = $prow->paperId; } } - $result = $this->conf->qe("select paperId, reviewId, " . $this->conf->query_ratings() . " ratingSignature from PaperReview where paperId?a and reviewType>0 group by paperId, reviewId", $pids); + $result = $this->conf->qe("select paperId, reviewId, " . $this->conf->rating_signature_query() . " ratingSignature from PaperReview where paperId?a and reviewType>0 group by paperId, reviewId", $pids); while (($row = $result->fetch_row())) { $ratings[$row[0]][$row[1]] = $row[2]; } diff --git a/src/documentinfo.php b/src/documentinfo.php index 7c789a6bb4..c490bc069f 100644 --- a/src/documentinfo.php +++ b/src/documentinfo.php @@ -38,6 +38,12 @@ class DocumentInfo implements JsonSerializable { public $originalStorageId; /** @var int */ public $inactive = 0; + /** @var ?int */ + private $npages; + /** @var ?int */ + private $width; + /** @var ?int */ + private $height; /** @var ?string */ private $content; @@ -1513,6 +1519,17 @@ private function link_html_format_info($flags, $suffix) { /** @param string $prop * @param mixed $v */ function set_prop($prop, $v) { + if (($prop === "npages" || $prop === "width" || $prop === "height") + && $this->conf->sversion >= 276) { + assert(is_int($v)); + if ($this->$prop === $v) { + return; + } + $this->_old_prop = $this->_old_prop ?? []; + $this->_old_prop[$prop] = $this->$prop; + $this->$prop = $v; + $v = null; + } $m = $this->metadata(); if (($m->$prop ?? null) !== $v) { $this->_old_prop["metadata"] = $this->_old_prop["metadata"] ?? (object) []; @@ -1587,11 +1604,24 @@ function abort_prop() { $this->_old_prop = null; } + function load_metadata() { + if ($this->paperStorageId > 0) { + $row = Dbl::fetch_first_object($this->conf->dblink, + "select " . $this->conf->document_metadata_query_fields() . " from PaperStorage where paperId=? and paperStorageId=?", + $this->paperId, $this->paperStorageId) + ?? (object) ["infoJson" => null, "npages" => -1, "width" => -1, "height" => -1]; + foreach ((array) $row as $prop => $v) { + $this->$prop = $v; + } + $this->_metadata = null; + } + } + /** @return object */ function metadata() { if ($this->_metadata === null) { if ($this->infoJson === false && $this->paperStorageId > 0) { - $this->infoJson = Dbl::fetch_value($this->conf->dblink, "select infoJson from PaperStorage where paperId=? and paperStorageId=?", $this->paperId, $this->paperStorageId); + $this->load_metadata(); } $this->_metadata = ($this->infoJson ? json_decode($this->infoJson) : null) ?? (object) []; } @@ -1624,13 +1654,22 @@ function archive_listing($max_length = -1) { function npages(CheckFormat $cf = null) { if ($this->mimetype && $this->mimetype !== "application/pdf") { return null; - } else if (($m = $this->metadata()) && isset($m->npages)) { - return $m->npages; - } else { + } + if ($this->npages === null) { + $this->load_metadata(); + } + if ($this->npages < 0 && $this->infoJson) { + $m = $this->metadata(); + if (isset($m->npages) && is_int($m->npages)) { + $this->set_prop("npages", $m->npages); + $this->save_prop(); + } + } + if ($this->npages < 0) { $cf = $cf ?? new CheckFormat($this->conf); $cf->check_document($this); - return $cf->npages; } + return $this->npages >= 0 ? $this->npages : null; } /** @param ?CheckFormat $cf diff --git a/src/paperinfo.php b/src/paperinfo.php index 9081ca4ea1..db01edefef 100644 --- a/src/paperinfo.php +++ b/src/paperinfo.php @@ -1998,7 +1998,7 @@ function load_preferences() { $prow->allReviewerPreference = ""; $prow->_prefs_array = $prow->_pref1_cid = $prow->_pref1 = $prow->_desirability = null; } - $result = $this->conf->qe("select paperId, " . $this->conf->query_all_reviewer_preference() . " from PaperReviewPreference where paperId?a group by paperId", $row_set->paper_ids()); + $result = $this->conf->qe("select paperId, " . $this->conf->all_reviewer_preference_query() . " from PaperReviewPreference where paperId?a group by paperId", $row_set->paper_ids()); while ($result && ($row = $result->fetch_row())) { $prow = $row_set->get((int) $row[0]); $prow->allReviewerPreference = $row[1]; @@ -2210,17 +2210,6 @@ function page_fields() { return $this->conf->options()->page_fields($this); } - /** @return string */ - static function document_query() { - return "paperId, paperStorageId, timestamp, mimetype, sha1, crc32, documentType, filename, infoJson, size, filterType, originalStorageId, inactive"; - } - - /** @return string - * @deprecated */ - static function document_sql() { - return self::document_query(); - } - /** @param int $dtype * @param int $did * @return ?DocumentInfo */ @@ -2266,7 +2255,7 @@ function document($dtype, $did = 0, $full = false) { } if ($this->_document_array === null) { - $result = $this->conf->qe("select " . self::document_query() . " from PaperStorage where paperId=? and inactive=0", $this->paperId); + $result = $this->conf->qe("select " . $this->conf->document_query_fields() . " from PaperStorage where paperId=? and inactive=0", $this->paperId); $this->_document_array = []; while (($di = DocumentInfo::fetch($result, $this->conf, $this))) { $this->_document_array[$di->paperStorageId] = $di; @@ -2274,7 +2263,7 @@ function document($dtype, $did = 0, $full = false) { Dbl::free($result); } if (!array_key_exists($did, $this->_document_array)) { - $result = $this->conf->qe("select " . self::document_query() . " from PaperStorage where paperStorageId=?", $did); + $result = $this->conf->qe("select " . $this->conf->document_query_fields() . " from PaperStorage where paperStorageId=?", $did); $this->_document_array[$did] = DocumentInfo::fetch($result, $this->conf, $this); Dbl::free($result); } @@ -2287,7 +2276,7 @@ function ensure_primary_documents() { foreach ($this->_row_set as $prow) { $psids[] = $prow->finalPaperStorageId <= 0 ? $prow->paperStorageId : $prow->finalPaperStorageId; } - $result = $this->conf->qe("select " . self::document_query() . " from PaperStorage where paperStorageId?a", $psids); + $result = $this->conf->qe("select " . $this->conf->document_query_fields() . " from PaperStorage where paperStorageId?a", $psids); while (($di = DocumentInfo::fetch($result, $this->conf))) { if (($prow = $this->_row_set->get($di->paperId))) { $di->prow = $prow; @@ -2493,7 +2482,7 @@ function load_reviews($always = false) { $prow->_flags = ($prow->_flags & ~self::REVIEW_FLAGS) | self::REVIEW_HAS_FULL; } - $result = $this->conf->qe("select PaperReview.*, " . $this->conf->query_ratings() . " ratingSignature from PaperReview where paperId?a order by paperId, reviewId", $row_set->paper_ids()); + $result = $this->conf->qe("select PaperReview.*, " . $this->conf->rating_signature_query() . " ratingSignature from PaperReview where paperId?a order by paperId, reviewId", $row_set->paper_ids()); while (($rrow = ReviewInfo::fetch($result, $row_set, $this->conf))) { $rrow->prow->_review_array[$rrow->reviewId] = $rrow; } @@ -2686,7 +2675,7 @@ function full_review_by_id($id) { if ($this->_full_review_key === null && ($this->_flags & self::REVIEW_HAS_FULL) === 0) { $this->_full_review_key = "r$id"; - $result = $this->conf->qe("select PaperReview.*, " . $this->conf->query_ratings() . " ratingSignature from PaperReview where paperId=? and reviewId=?", $this->paperId, $id); + $result = $this->conf->qe("select PaperReview.*, " . $this->conf->rating_signature_query() . " ratingSignature from PaperReview where paperId=? and reviewId=?", $this->paperId, $id); $rrow = ReviewInfo::fetch($result, $this, $this->conf); $this->_full_review = $rrow ? [$rrow] : []; Dbl::free($result); @@ -2709,7 +2698,7 @@ function full_reviews_by_user($contact) { $prow->_full_review = []; $prow->_full_review_key = "u$cid"; } - $result = $this->conf->qe("select PaperReview.*, " . $this->conf->query_ratings() . " ratingSignature from PaperReview where paperId?a and contactId=? order by paperId, reviewId", $this->_row_set->paper_ids(), $cid); + $result = $this->conf->qe("select PaperReview.*, " . $this->conf->rating_signature_query() . " ratingSignature from PaperReview where paperId?a and contactId=? order by paperId, reviewId", $this->_row_set->paper_ids(), $cid); while (($rrow = ReviewInfo::fetch($result, $this->_row_set, $this->conf))) { $rrow->prow->_full_review[] = $rrow; } @@ -2728,7 +2717,7 @@ function full_review_by_ordinal($ordinal) { if ($this->_full_review_key === null && ($this->_flags & self::REVIEW_HAS_FULL) === 0) { $this->_full_review_key = "o$ordinal"; - $result = $this->conf->qe("select PaperReview.*, " . $this->conf->query_ratings() . " ratingSignature from PaperReview where paperId=? and reviewOrdinal=?", $this->paperId, $ordinal); + $result = $this->conf->qe("select PaperReview.*, " . $this->conf->rating_signature_query() . " ratingSignature from PaperReview where paperId=? and reviewOrdinal=?", $this->paperId, $ordinal); $rrow = ReviewInfo::fetch($result, $this, $this->conf); $this->_full_review = $rrow ? [$rrow] : []; Dbl::free($result); @@ -2755,7 +2744,7 @@ function full_review_by_ordinal_id($oid) { /** @return ?ReviewInfo */ private function fresh_review_by($key, $value) { - $result = $this->conf->qe("select PaperReview.*, " . $this->conf->query_ratings() . " ratingSignature from PaperReview where paperId=? and {$key}=? order by paperId, reviewId", $this->paperId, $value); + $result = $this->conf->qe("select PaperReview.*, " . $this->conf->rating_signature_query() . " ratingSignature from PaperReview where paperId=? and {$key}=? order by paperId, reviewId", $this->paperId, $value); $rrow = ReviewInfo::fetch($result, $this, $this->conf); Dbl::free($result); return $rrow; @@ -2953,7 +2942,7 @@ function ensure_review_ratings(ReviewInfo $ensure_rrow = null) { if ($ensure_rrow) { $ensure_rrow->ratingSignature = ""; } - $result = $this->conf->qe("select paperId, reviewId, " . $this->conf->query_ratings() . " ratingSignature from PaperReview where paperId?a", $pids); + $result = $this->conf->qe("select paperId, reviewId, " . $this->conf->rating_signature_query() . " ratingSignature from PaperReview where paperId?a", $pids); while (($row = $result->fetch_row())) { $prow = $this->_row_set->get((int) $row[0]); if (($rrow = $prow->_review_array[(int) $row[1]] ?? null)) { diff --git a/src/reviewinfo.php b/src/reviewinfo.php index 82e36cd68d..9e87df0efa 100644 --- a/src/reviewinfo.php +++ b/src/reviewinfo.php @@ -828,7 +828,7 @@ function ensure_ratings() { } else if ($this->prow) { $this->prow->ensure_review_ratings($this); } else { - $result = $this->conf->qe("select " . $this->conf->query_ratings() . " from PaperReview where paperId=? and reviewId=?", $this->paperId, $this->reviewId); + $result = $this->conf->qe("select " . $this->conf->rating_signature_query() . " from PaperReview where paperId=? and reviewId=?", $this->paperId, $this->reviewId); $row = $result->fetch_row(); Dbl::free($result); $this->ratingSignature = $row ? $row[0] : ""; diff --git a/src/schema.sql b/src/schema.sql index d06f54d40e..34022c29be 100644 --- a/src/schema.sql +++ b/src/schema.sql @@ -474,6 +474,9 @@ CREATE TABLE `PaperStorage` ( `filterType` int(3) DEFAULT NULL, `originalStorageId` int(11) DEFAULT NULL, `inactive` tinyint(1) NOT NULL DEFAULT 0, + `npages` int(3) NOT NULL DEFAULT -1, + `width` int(8) NOT NULL DEFAULT -1, + `height` int(8) NOT NULL DEFAULT -1, PRIMARY KEY (`paperId`,`paperStorageId`), UNIQUE KEY `paperStorageId` (`paperStorageId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; @@ -618,7 +621,7 @@ CREATE TABLE `TopicInterest` ( -- Initial settings -- (each setting must be on its own line for createdb.sh) insert into Settings (name, value, data) values - ('allowPaperOption', 275, null), -- schema version + ('allowPaperOption', 276, null), -- schema version ('setupPhase', 1, null), -- initial user is chair ('no_papersub', 1, null), -- no submissions yet ('sub_pcconf', 1, null), -- collect PC conflicts, not collaborators diff --git a/src/updateschema.php b/src/updateschema.php index 1f3c9d1112..cc4a93d77c 100644 --- a/src/updateschema.php +++ b/src/updateschema.php @@ -2642,6 +2642,12 @@ function run() { || $conf->sversion === 274) { $conf->update_schema_version(275); } + if ($conf->sversion === 275 + && $conf->ql_ok("alter table PaperStorage add `npages` int(3) NOT NULL DEFAULT -1") + && $conf->ql_ok("alter table PaperStorage add `width` int(8) NOT NULL DEFAULT -1") + && $conf->ql_ok("alter table PaperStorage add `height` int(8) NOT NULL DEFAULT -1")) { + $conf->update_schema_version(276); + } $conf->ql_ok("delete from Settings where name='__schema_lock'"); Conf::$main = $old_conf_g;