From 5ed0313daa576195d5fa13df48d4939255e49cd0 Mon Sep 17 00:00:00 2001 From: "Brian \"Moses\" Hall" Date: Tue, 16 Dec 2025 12:25:08 -0500 Subject: [PATCH 1/8] Add tests `RecordUtils.php` methods `is_fullview` and `is_open_to_no_one`. --- test/RecordUtilsTest.php | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/test/RecordUtilsTest.php b/test/RecordUtilsTest.php index 7dbb9959..1d806aa3 100644 --- a/test/RecordUtilsTest.php +++ b/test/RecordUtilsTest.php @@ -150,6 +150,63 @@ public function test_ht_link_data_from_json_activated_role(): void { $this->assertEquals(true, $data['has_activated_role']); $this->assertEquals('resourceSharing', $data['role_name']); } + + /** + * @covers RecordUtils::is_fullview + */ + public function test_is_fullview(): void { + $utils = new RecordUtils(); + $examples = [ + // Rights fv us? fv non-us? + ['pd', true, true], + ['ic', false, false], + ['op', false, false], + ['orph', false, false], + ['und', false, false], + // umall is obsolete, test is included to demonstrate behavior + ['umall', false, false], + ['ic-world', true, true], + ['nobody', false, false], + ['pdus', true, false], + ['cc-by-3.0', true, true], + // skip the rest of the CC 3.0 rights... + ['orphcand', false, false], + ['cc-zero', true, true], + ['und-world', true, true], + ['icus', false, true], + ['cc-by-4.0', true, true], + // skip the rest of the CC 4.0 rights... + ['pd-pvt', false, false], + ['supp', false, false], + // Degenerate case + ['???', false, false] + ]; + foreach ($examples as $example) { + $this->assertEquals($example[1], $utils->is_fullview($example[0], true)); + $this->assertEquals($example[2], $utils->is_fullview($example[0], false)); + } + } + + /** + * @covers RecordUtils::is_open_to_no_one + */ + public function test_is_open_to_no_one(): void { + $utils = new RecordUtils(); + $examples = [ + // Rights open to no one? + ['pd', false], + ['ic', false], + ['pd-pvt', true], + ['supp', true], + ['nobody', true], + [['pd', 'pd-pvt'], true], + [['pd', 'supp'], true], + [['pd', 'nobody'], true] + ]; + foreach ($examples as $example) { + $this->assertEquals($example[1], $utils->is_open_to_no_one($example[0])); + } + } } ?> From a311eb1779075aa7a9f2ccebdb991a648519bfb0 Mon Sep 17 00:00:00 2001 From: "Brian \"Moses\" Hall" Date: Tue, 16 Dec 2025 12:47:27 -0500 Subject: [PATCH 2/8] Remove support for obsolete "newly open" rights facet and access decisions based on it --- conf/config.ini | 5 ----- services/Record/RecordUtils.php | 19 ------------------- 2 files changed, 24 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index a140489a..2fc29344 100755 --- a/conf/config.ini +++ b/conf/config.ini @@ -4,11 +4,6 @@ ; only for HathiTrust site -[IntoCopyright] -; YYYYMMDDHH -date = 9999999999 - - [Switches] fetchAlephHolings = false onlyHathiHoldings = true diff --git a/services/Record/RecordUtils.php b/services/Record/RecordUtils.php index 2bc2cec1..8b32951a 100644 --- a/services/Record/RecordUtils.php +++ b/services/Record/RecordUtils.php @@ -184,7 +184,6 @@ function record_is_tombstone($rec) { function is_fullview($rcode, $inUSA = null) { - global $configArray; if (!isset($inUSA)) { $session = VFSession::instance(); $inUSA = $session->get('inUSA'); @@ -199,24 +198,6 @@ function is_fullview($rcode, $inUSA = null) { // Assume false $fv = false; - // Newly into copyright? Return true if after the right date - // The munged facet is in Solr.php -- don't forget - // to deal with that, too. - - $todays_date = intval(date("YmdH")); - $copyright_active_date = intval($configArray['IntoCopyright']['date']); - if (is_array($rcode) && - array_search("newly_open", $rcode) && - $todays_date >= $copyright_active_date - ) { - return true; - } else if (is_array($rcode)) { // ditch the newly_open marker - $index = array_search("newly_open", $rcode); - if ($index) { - unset($rcode[$index]); - } - $rcode = $rcode[0]; - } // Public domain? return true if (preg_match('/^(cc|pd)/', $rcode) || preg_match('/world/', $rcode)) { From 4cb979f264208261c3a631744a6bf5d52e414a88 Mon Sep 17 00:00:00 2001 From: "Brian \"Moses\" Hall" Date: Tue, 16 Dec 2025 13:28:41 -0500 Subject: [PATCH 3/8] Handle rights codes as arrays and potential "newly_open"s that could be lurking around. - This fixes a failing playwright test --- services/Record/RecordUtils.php | 7 +++++++ test/RecordUtilsTest.php | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/services/Record/RecordUtils.php b/services/Record/RecordUtils.php index 8b32951a..82811c5e 100644 --- a/services/Record/RecordUtils.php +++ b/services/Record/RecordUtils.php @@ -198,6 +198,13 @@ function is_fullview($rcode, $inUSA = null) { // Assume false $fv = false; + if (is_array($rcode)) { + // Remove any "newly_open"s that could still be lurking around + $rcode = array_diff($rcode, ['newly_open']); + // This could fail if the rights code is somehow just ['newly_open'], + // which probably merits a 500 error. + $rcode = reset($rcode); + } // Public domain? return true if (preg_match('/^(cc|pd)/', $rcode) || preg_match('/world/', $rcode)) { diff --git a/test/RecordUtilsTest.php b/test/RecordUtilsTest.php index 1d806aa3..9a5f3423 100644 --- a/test/RecordUtilsTest.php +++ b/test/RecordUtilsTest.php @@ -178,8 +178,10 @@ public function test_is_fullview(): void { // skip the rest of the CC 4.0 rights... ['pd-pvt', false, false], ['supp', false, false], - // Degenerate case - ['???', false, false] + // Oddball cases + ['???', false, false], + [['newly_open', 'pd'], true, true], + [['pd', 'ic'], true, true] ]; foreach ($examples as $example) { $this->assertEquals($example[1], $utils->is_fullview($example[0], true)); From 83ad61bc5a70a74843ec218019d3255212584ccf Mon Sep 17 00:00:00 2001 From: "Brian \"Moses\" Hall" Date: Tue, 16 Dec 2025 16:21:04 -0500 Subject: [PATCH 4/8] Basic go/no-go tests for `recordnumber` and `htid` Bib API endpoints. --- playwright/test/slow/api.spec.js | 51 +++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/playwright/test/slow/api.spec.js b/playwright/test/slow/api.spec.js index ab53149d..e4c8f7da 100644 --- a/playwright/test/slow/api.spec.js +++ b/playwright/test/slow/api.spec.js @@ -2,6 +2,8 @@ const { test, expect } = require('@playwright/test'); const test_cid = '002312286'; // "Kōkogaku zasshi" arbitrarily chosen const test_truncated_cid = '2312286'; // Truncated version +const test_htid = 'mdp.39015048895836'; // One of the htids on test_cid + test('XML with full CID', async ({ page }) => { const response = await page.goto(`/Record/${test_cid}.xml`); @@ -11,4 +13,51 @@ test('XML with full CID', async ({ page }) => { test('XML with truncated CID', async ({ page }) => { const response = await page.goto(`/Record/${test_truncated_cid}.xml`); await expect(response.ok()).toBeTruthy(); -}); \ No newline at end of file +}); + +// API JSON resonses are of the form +// {records: {cid: {...}, items: [...]} + +test('Bib API catalog record brief', async ({ page }) => { + const response = await page.goto(`/api/volumes/brief/recordnumber/${test_cid}.json`); + expect(response.status()).toBe(200); + expect(response.headers()["content-type"]).toContain('application/json'); + const body = await response.json(); + expect(body.records).toHaveProperty(test_cid); + // No marc-xml property + expect(body.records[test_cid]).not.toHaveProperty("marc-xml"); + expect(body.items.length).toBeGreaterThan(0); +}); + +test('Bib API catalog record full', async ({ page }) => { + const response = await page.goto(`/api/volumes/full/recordnumber/${test_cid}.json`); + expect(response.status()).toBe(200); + expect(response.headers()["content-type"]).toContain('application/json'); + const body = await response.json(); + expect(body.records).toHaveProperty(test_cid); + // Has marc-xml property + expect(body.records[test_cid]).toHaveProperty("marc-xml"); + expect(body.items.length).toBeGreaterThan(0); +}); + +test('Bib API HTID brief', async ({ page }) => { + const response = await page.goto(`/api/volumes/brief/htid/${test_htid}.json`); + expect(response.status()).toBe(200); + expect(response.headers()["content-type"]).toContain('application/json'); + const body = await response.json(); + expect(body.records).toHaveProperty(test_cid); + // No marc-xml property + expect(body.records[test_cid]).not.toHaveProperty("marc-xml"); + expect(body.items.length).toBeGreaterThan(0); +}); + +test('Bib API HTID full', async ({ page }) => { + const response = await page.goto(`/api/volumes/full/htid/${test_htid}.json`); + expect(response.status()).toBe(200); + expect(response.headers()["content-type"]).toContain('application/json'); + const body = await response.json(); + expect(body.records).toHaveProperty(test_cid); + // Has marc-xml property + expect(body.records[test_cid]).toHaveProperty("marc-xml"); + expect(body.items.length).toBeGreaterThan(0); +}); From acc4f70d14dfd089db82977cea665097954c85f4 Mon Sep 17 00:00:00 2001 From: "Brian \"Moses\" Hall" Date: Wed, 17 Dec 2025 10:30:34 -0500 Subject: [PATCH 5/8] Revert Bib API tests -- they will go in a different branch --- playwright/test/slow/api.spec.js | 47 -------------------------------- 1 file changed, 47 deletions(-) diff --git a/playwright/test/slow/api.spec.js b/playwright/test/slow/api.spec.js index e4c8f7da..17c305ea 100644 --- a/playwright/test/slow/api.spec.js +++ b/playwright/test/slow/api.spec.js @@ -14,50 +14,3 @@ test('XML with truncated CID', async ({ page }) => { const response = await page.goto(`/Record/${test_truncated_cid}.xml`); await expect(response.ok()).toBeTruthy(); }); - -// API JSON resonses are of the form -// {records: {cid: {...}, items: [...]} - -test('Bib API catalog record brief', async ({ page }) => { - const response = await page.goto(`/api/volumes/brief/recordnumber/${test_cid}.json`); - expect(response.status()).toBe(200); - expect(response.headers()["content-type"]).toContain('application/json'); - const body = await response.json(); - expect(body.records).toHaveProperty(test_cid); - // No marc-xml property - expect(body.records[test_cid]).not.toHaveProperty("marc-xml"); - expect(body.items.length).toBeGreaterThan(0); -}); - -test('Bib API catalog record full', async ({ page }) => { - const response = await page.goto(`/api/volumes/full/recordnumber/${test_cid}.json`); - expect(response.status()).toBe(200); - expect(response.headers()["content-type"]).toContain('application/json'); - const body = await response.json(); - expect(body.records).toHaveProperty(test_cid); - // Has marc-xml property - expect(body.records[test_cid]).toHaveProperty("marc-xml"); - expect(body.items.length).toBeGreaterThan(0); -}); - -test('Bib API HTID brief', async ({ page }) => { - const response = await page.goto(`/api/volumes/brief/htid/${test_htid}.json`); - expect(response.status()).toBe(200); - expect(response.headers()["content-type"]).toContain('application/json'); - const body = await response.json(); - expect(body.records).toHaveProperty(test_cid); - // No marc-xml property - expect(body.records[test_cid]).not.toHaveProperty("marc-xml"); - expect(body.items.length).toBeGreaterThan(0); -}); - -test('Bib API HTID full', async ({ page }) => { - const response = await page.goto(`/api/volumes/full/htid/${test_htid}.json`); - expect(response.status()).toBe(200); - expect(response.headers()["content-type"]).toContain('application/json'); - const body = await response.json(); - expect(body.records).toHaveProperty(test_cid); - // Has marc-xml property - expect(body.records[test_cid]).toHaveProperty("marc-xml"); - expect(body.items.length).toBeGreaterThan(0); -}); From 68d55626bcec977ce93cdcecea1b425ab21e8a0a Mon Sep 17 00:00:00 2001 From: "Brian \"Moses\" Hall" Date: Wed, 17 Dec 2025 11:00:14 -0500 Subject: [PATCH 6/8] Remove last vestiges of `newly_open` rights flag. --- services/Record/RecordUtils.php | 7 ++---- test/RecordUtilsTest.php | 44 ++++++++++++++++----------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/services/Record/RecordUtils.php b/services/Record/RecordUtils.php index 82811c5e..a370a8b4 100644 --- a/services/Record/RecordUtils.php +++ b/services/Record/RecordUtils.php @@ -199,11 +199,8 @@ function is_fullview($rcode, $inUSA = null) { $fv = false; if (is_array($rcode)) { - // Remove any "newly_open"s that could still be lurking around - $rcode = array_diff($rcode, ['newly_open']); - // This could fail if the rights code is somehow just ['newly_open'], - // which probably merits a 500 error. - $rcode = reset($rcode); + // Empty array? Just use default empty string. + $rcode = empty($rcode) ? '' : reset($rcode); } // Public domain? return true diff --git a/test/RecordUtilsTest.php b/test/RecordUtilsTest.php index 9a5f3423..4bffffdc 100644 --- a/test/RecordUtilsTest.php +++ b/test/RecordUtilsTest.php @@ -157,31 +157,31 @@ public function test_ht_link_data_from_json_activated_role(): void { public function test_is_fullview(): void { $utils = new RecordUtils(); $examples = [ - // Rights fv us? fv non-us? - ['pd', true, true], - ['ic', false, false], - ['op', false, false], - ['orph', false, false], - ['und', false, false], + // Rights fv us? fv non-us? + ['pd', true, true], + ['ic', false, false], + ['op', false, false], + ['orph', false, false], + ['und', false, false], // umall is obsolete, test is included to demonstrate behavior - ['umall', false, false], - ['ic-world', true, true], - ['nobody', false, false], - ['pdus', true, false], - ['cc-by-3.0', true, true], + ['umall', false, false], + ['ic-world', true, true], + ['nobody', false, false], + ['pdus', true, false], + ['cc-by-3.0', true, true], // skip the rest of the CC 3.0 rights... - ['orphcand', false, false], - ['cc-zero', true, true], - ['und-world', true, true], - ['icus', false, true], - ['cc-by-4.0', true, true], + ['orphcand', false, false], + ['cc-zero', true, true], + ['und-world', true, true], + ['icus', false, true], + ['cc-by-4.0', true, true], // skip the rest of the CC 4.0 rights... - ['pd-pvt', false, false], - ['supp', false, false], - // Oddball cases - ['???', false, false], - [['newly_open', 'pd'], true, true], - [['pd', 'ic'], true, true] + ['pd-pvt', false, false], + ['supp', false, false], + // Edge cases + ['???', false, false], + [[], false, false], + [['pd', 'ic'], true, true] ]; foreach ($examples as $example) { $this->assertEquals($example[1], $utils->is_fullview($example[0], true)); From 681e6b84c3730944e6a28a8f24ef3f528c6a1787 Mon Sep 17 00:00:00 2001 From: "Brian \"Moses\" Hall" Date: Fri, 2 Jan 2026 16:17:28 -0500 Subject: [PATCH 7/8] Revert last bits of playwright tests which were moved to a different branch --- playwright/test/slow/api.spec.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/playwright/test/slow/api.spec.js b/playwright/test/slow/api.spec.js index 17c305ea..ab53149d 100644 --- a/playwright/test/slow/api.spec.js +++ b/playwright/test/slow/api.spec.js @@ -2,8 +2,6 @@ const { test, expect } = require('@playwright/test'); const test_cid = '002312286'; // "Kōkogaku zasshi" arbitrarily chosen const test_truncated_cid = '2312286'; // Truncated version -const test_htid = 'mdp.39015048895836'; // One of the htids on test_cid - test('XML with full CID', async ({ page }) => { const response = await page.goto(`/Record/${test_cid}.xml`); @@ -13,4 +11,4 @@ test('XML with full CID', async ({ page }) => { test('XML with truncated CID', async ({ page }) => { const response = await page.goto(`/Record/${test_truncated_cid}.xml`); await expect(response.ok()).toBeTruthy(); -}); +}); \ No newline at end of file From e5f0a7755e1c6b906ed372528b1f406fbb8548b7 Mon Sep 17 00:00:00 2001 From: "Brian \"Moses\" Hall" Date: Tue, 6 Jan 2026 14:24:47 -0500 Subject: [PATCH 8/8] Remove `fulltext_filter_add_jan1_rollover` and one invocation of it from `Solr.php` --- sys/Solr.php | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/sys/Solr.php b/sys/Solr.php index ae53bbc7..85b390b7 100755 --- a/sys/Solr.php +++ b/sys/Solr.php @@ -427,7 +427,6 @@ function filterComponents($ss) { if ($index == "ht_availability" and $oval == 'Full text') { $ft = $this->fulltext_filter_base(); - $ft = $this->fulltext_filter_add_jan1_rollover($ft); $ft = $this->fulltext_filter_add_etas_or_resource_sharing($ft); $rv[] = $ft; } @@ -463,26 +462,6 @@ function fulltext_filter_add_etas_or_resource_sharing($current_ft_filter) { } } - function fulltext_filter_add_jan1_rollover($current_ft_filter) { - // Hack into place a change of the full-text only facet - // for the temporary newly_open rightscode value - // but only on or after the date from config.ini - - global $configArray; - - $todays_date = intval(date("YmdH")); - $copyright_active_date = intval($configArray['IntoCopyright']['date']); - - if ($todays_date >= $copyright_active_date) { - $newly_open = $this->quoteFilterValue('newly_open'); - return "($current_ft_filter OR ht_rightscode:$newly_open)"; - } - else { - return $current_ft_filter; - } - } - - /** * tagIDs($ss) *