diff --git a/module/VuFind/src/VuFind/RecordDriver/Feature/VersionAwareTrait.php b/module/VuFind/src/VuFind/RecordDriver/Feature/VersionAwareTrait.php index e2fe3a3108d..f0299795567 100644 --- a/module/VuFind/src/VuFind/RecordDriver/Feature/VersionAwareTrait.php +++ b/module/VuFind/src/VuFind/RecordDriver/Feature/VersionAwareTrait.php @@ -31,7 +31,8 @@ namespace VuFind\RecordDriver\Feature; -use VuFindSearch\Command\WorkExpressionsCommand; +use VuFindSearch\Command\SearchCommand; +use VuFindSearch\Query\WorkKeysQuery; /** * Logic for record versions support. @@ -70,7 +71,7 @@ public function getOtherVersionCount() } if (!isset($this->otherVersionsCount)) { - if (!$this->tryMethod('getWorkKeys')) { + if (!($keys = $this->tryMethod('getWorkKeys'))) { if (!($this instanceof VersionAwareInterface)) { throw new \Exception( 'VersionAwareTrait requires VersionAwareInterface' @@ -79,13 +80,11 @@ public function getOtherVersionCount() return false; } - $params = new \VuFindSearch\ParamBag(); - $params->add('rows', 0); - $command = new WorkExpressionsCommand( + $command = new SearchCommand( $this->getSourceIdentifier(), - $this->getUniqueID(), - false, - $params + new WorkKeysQuery($this->getUniqueID(), false, $keys), + 0, + 0 ); $results = $this->searchService->invoke($command)->getResult(); $this->otherVersionsCount = $results->getTotal(); @@ -104,23 +103,18 @@ public function getOtherVersionCount() */ public function getVersions($includeSelf = false, $count = 20, $offset = 0) { - if (null === $this->searchService || !$this->getWorkKeys()) { + if (null === $this->searchService || !($keys = $this->getWorkKeys())) { return false; } if (!isset($this->otherVersions)) { - $params = new \VuFindSearch\ParamBag(); - $params->add('rows', $count); - $params->add('start', $offset); - $command = new WorkExpressionsCommand( + $command = new SearchCommand( $this->getSourceIdentifier(), - $this->getUniqueID(), - $includeSelf, - $params + new WorkKeysQuery($this->getUniqueID(), false, $keys), + $offset, + $count ); - $this->otherVersions = $this->searchService->invoke( - $command - )->getResult(); + $this->otherVersions = $this->searchService->invoke($command)->getResult(); } return $this->otherVersions; } diff --git a/module/VuFind/src/VuFind/Search/QueryAdapter.php b/module/VuFind/src/VuFind/Search/QueryAdapter.php index 1184ee1cf3b..d18cf4dcf70 100644 --- a/module/VuFind/src/VuFind/Search/QueryAdapter.php +++ b/module/VuFind/src/VuFind/Search/QueryAdapter.php @@ -65,7 +65,7 @@ public static function deminify(array $search) $type = $search['s'] ?? null; if ('w' === $type) { // WorkKeysQuery - return new WorkKeysQuery($search['l'], $search['i']); + return new WorkKeysQuery($search['l'], $search['i'], $search['k'] ?? []); } // Use array_key_exists since null is also valid if ('b' === $type || array_key_exists('l', $search)) { @@ -271,6 +271,7 @@ public static function minify(AbstractQuery $query, $topLevel = true) return [ 'l' => $query->getId(), 'i' => $query->getIncludeSelf(), + 'k' => $query->getWorkKeys(), 's' => 'w', ]; } diff --git a/module/VuFind/tests/fixtures/searches/workkeys/min b/module/VuFind/tests/fixtures/searches/workkeys/min index b56110db3c9..da999c52f42 100644 --- a/module/VuFind/tests/fixtures/searches/workkeys/min +++ b/module/VuFind/tests/fixtures/searches/workkeys/min @@ -1 +1 @@ -a:3:{s:1:"l";s:2:"id";s:1:"i";b:1;s:1:"s";s:1:"w";} \ No newline at end of file +a:4:{s:1:"l";s:2:"id";s:1:"i";b:1;s:1:"k";a:2:{i:0;s:6:"AT foo";i:1;s:6:"UT bar";}s:1:"s";s:1:"w";} \ No newline at end of file diff --git a/module/VuFind/tests/fixtures/searches/workkeys/query b/module/VuFind/tests/fixtures/searches/workkeys/query index 1eec6e8ee38..4c609d7afff 100644 Binary files a/module/VuFind/tests/fixtures/searches/workkeys/query and b/module/VuFind/tests/fixtures/searches/workkeys/query differ diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php index 7137037a68d..7ff6156dca5 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php @@ -40,7 +40,6 @@ use VuFindSearch\Feature\RandomInterface; use VuFindSearch\Feature\RetrieveBatchInterface; use VuFindSearch\Feature\SimilarInterface; -use VuFindSearch\Feature\WorkExpressionsInterface; use VuFindSearch\ParamBag; use VuFindSearch\Query\AbstractQuery; use VuFindSearch\Query\WorkKeysQuery; @@ -64,8 +63,7 @@ class Backend extends AbstractBackend implements RetrieveBatchInterface, RandomInterface, ExtraRequestDetailsInterface, - GetIdsInterface, - WorkExpressionsInterface + GetIdsInterface { /** * Limit for records per query in a batch retrieval. @@ -137,7 +135,7 @@ public function search( ParamBag $params = null ) { if ($query instanceof WorkKeysQuery) { - return $this->workExpressions($query->getId(), $query->getIncludeSelf(), $params); + return $this->workKeysSearch($query, $offset, $limit, $params); } $json = $this->rawJsonSearch($query, $offset, $limit, $params); $collection = $this->createRecordCollection($json); @@ -418,46 +416,6 @@ public function alphabeticBrowse( return $this->deserialize($response); } - /** - * Return work expressions. - * - * @param string $id Id of record to compare with - * @param array $includeSelf Whether to include the record to compare with in the results - * @param ParamBag $defaultParams Search backend parameters - * - * @return RecordCollectionInterface - */ - public function workExpressions( - string $id, - bool $includeSelf, - ParamBag $defaultParams = null - ): RecordCollectionInterface { - $recordResponse = $this->connector->retrieve($id); - $recordCollection = $this->createRecordCollection($recordResponse); - $record = $recordCollection->first(); - if (!$record || !($workKeys = $record->getWorkKeys())) { - return $this->createRecordCollection('{}'); - } - - $params = $defaultParams ? clone $defaultParams - : new \VuFindSearch\ParamBag(); - $this->injectResponseWriter($params); - $params->set('q', "{!terms f=work_keys_str_mv separator=\"\u{001f}\"}" . implode("\u{001f}", $workKeys)); - if (!$includeSelf) { - $params->add('fq', sprintf('-id:"%s"', addcslashes($id, '"'))); - } - if (!$params->hasParam('rows')) { - $params->add('rows', 100); - } - if (!$params->hasParam('sort')) { - $params->add('sort', 'publishDateSort desc, title_sort asc'); - } - $response = $this->connector->search($params); - $collection = $this->createRecordCollection($response); - $this->injectSourceIdentifier($collection); - return $collection; - } - /** * Write a document to Solr. Return an array of details about the updated index. * @@ -664,4 +622,50 @@ protected function injectResponseWriter(ParamBag $params) $params->set('wt', ['json']); $params->set('json.nl', ['arrarr']); } + + /** + * Return work expressions. + * + * @param WorkKeysQuery $query Search query + * @param int $offset Search offset + * @param int $limit Search limit + * @param ParamBag $defaultParams Search backend parameters + * + * @return RecordCollectionInterface + */ + protected function workKeysSearch( + WorkKeysQuery $query, + int $offset, + int $limit, + ParamBag $defaultParams = null + ): RecordCollectionInterface { + $id = $query->getId(); + if ('' === $id) { + throw new BackendException('Record ID empty in work keys query'); + } + if (!($workKeys = $query->getWorkKeys())) { + $recordResponse = $this->connector->retrieve($id); + $recordCollection = $this->createRecordCollection($recordResponse); + $record = $recordCollection->first(); + if (!$record || !($workKeys = $record->tryMethod('getWorkKeys'))) { + return $this->createRecordCollection('{}'); + } + } + + $params = $defaultParams ? clone $defaultParams : new \VuFindSearch\ParamBag(); + $this->injectResponseWriter($params); + $params->set('q', "{!terms f=work_keys_str_mv separator=\"\u{001f}\"}" . implode("\u{001f}", $workKeys)); + if (!$query->getIncludeSelf()) { + $params->add('fq', sprintf('-id:"%s"', addcslashes($id, '"'))); + } + $params->set('rows', $limit); + $params->set('start', $offset); + if (!$params->hasParam('sort')) { + $params->add('sort', 'publishDateSort desc, title_sort asc'); + } + $response = $this->connector->search($params); + $collection = $this->createRecordCollection($response); + $this->injectSourceIdentifier($collection); + return $collection; + } } diff --git a/module/VuFindSearch/src/VuFindSearch/Command/WorkExpressionsCommand.php b/module/VuFindSearch/src/VuFindSearch/Command/WorkExpressionsCommand.php deleted file mode 100644 index 0ff5433e64a..00000000000 --- a/module/VuFindSearch/src/VuFindSearch/Command/WorkExpressionsCommand.php +++ /dev/null @@ -1,105 +0,0 @@ - - * @author Aleksi Peebles - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org - */ - -namespace VuFindSearch\Command; - -use VuFindSearch\Command\Feature\RecordIdentifierTrait; -use VuFindSearch\Feature\WorkExpressionsInterface; -use VuFindSearch\ParamBag; - -/** - * Return work expressions command. - * - * @category VuFind - * @package Search - * @author Ere Maijala - * @author Aleksi Peebles - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org - */ -class WorkExpressionsCommand extends CallMethodCommand -{ - use RecordIdentifierTrait; - - /** - * Whether to include the record to compare with in the results - * - * @var bool - */ - protected $includeSelf; - - /** - * WorkExpressionsCommand constructor. - * - * @param string $backendId Search backend identifier - * @param string $id Identifier of record to compare with - * @param bool $includeSelf Whether to include the record to compare with in the results - * @param ?ParamBag $params Search backend parameters - */ - public function __construct( - string $backendId, - string $id, - bool $includeSelf, - ?ParamBag $params = null - ) { - $this->id = $id; - $this->includeSelf = $includeSelf; - parent::__construct( - $backendId, - WorkExpressionsInterface::class, - 'workExpressions', - $params - ); - } - - /** - * Return search backend interface method arguments. - * - * @return array - */ - public function getArguments(): array - { - return [ - $this->getRecordIdentifier(), - $this->getIncludeSelf(), - $this->getSearchParameters(), - ]; - } - - /** - * Return "include self" setting. - * - * @return bool - */ - public function getIncludeSelf(): bool - { - return $this->includeSelf; - } -} diff --git a/module/VuFindSearch/src/VuFindSearch/Feature/WorkExpressionsInterface.php b/module/VuFindSearch/src/VuFindSearch/Feature/WorkExpressionsInterface.php deleted file mode 100644 index 42b4fe99275..00000000000 --- a/module/VuFindSearch/src/VuFindSearch/Feature/WorkExpressionsInterface.php +++ /dev/null @@ -1,60 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org - */ - -namespace VuFindSearch\Feature; - -use VuFindSearch\ParamBag; -use VuFindSearch\Response\RecordCollectionInterface; - -/** - * Work expressions feature interface definition. - * - * @category VuFind - * @package Search - * @author Ere Maijala - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org - */ -interface WorkExpressionsInterface -{ - /** - * Return work expressions. - * - * @param string $id Id of record to compare with - * @param array $includeSelf Whether to include the record to compare with in the results - * @param ParamBag $defaultParams Search backend parameters - * - * @return RecordCollectionInterface - */ - public function workExpressions( - string $id, - bool $includeSelf, - ParamBag $defaultParams = null - ): RecordCollectionInterface; -} diff --git a/module/VuFindSearch/src/VuFindSearch/Query/WorkKeysQuery.php b/module/VuFindSearch/src/VuFindSearch/Query/WorkKeysQuery.php index a0e3396edf6..234f1124e81 100644 --- a/module/VuFindSearch/src/VuFindSearch/Query/WorkKeysQuery.php +++ b/module/VuFindSearch/src/VuFindSearch/Query/WorkKeysQuery.php @@ -54,16 +54,25 @@ class WorkKeysQuery extends AbstractQuery */ protected $includeSelf; + /** + * Work keys + * + * @var array + */ + protected $workKeys; + /** * Constructor. * * @param ?string $id Record ID - * @param boo $includeSelf Whether to include the record to compare with in the results + * @param bool $includeSelf Whether to include the record to compare with in the results + * @param array $workKeys Work keys to use */ - public function __construct(?string $id, bool $includeSelf) + public function __construct(?string $id, bool $includeSelf, array $workKeys = []) { $this->id = $id; $this->includeSelf = $includeSelf; + $this->workKeys = $workKeys; } /** @@ -110,6 +119,28 @@ public function setIncludeSelf(bool $includeSelf): void $this->includeSelf = $includeSelf; } + /** + * Return work keys + * + * @return array + */ + public function getWorkKeys(): array + { + return $this->workKeys; + } + + /** + * Set work keys + * + * @param array $workKeys Work keys + * + * @return void + */ + public function setWorkKeys(array $workKeys): void + { + $this->workKeys = $workKeys; + } + /** * Does the query contain the specified term? An optional normalizer can be * provided to allow for fuzzier matching. diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Command/WorkExpressionsCommandTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Command/WorkExpressionsCommandTest.php deleted file mode 100644 index 47045b76ed4..00000000000 --- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Command/WorkExpressionsCommandTest.php +++ /dev/null @@ -1,76 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org - */ - -namespace VuFindTest\Command; - -use PHPUnit\Framework\TestCase; -use VuFindSearch\Backend\Solr\Response\Json\RecordCollection; -use VuFindSearch\Command\WorkExpressionsCommand; - -/** - * Unit tests for WorkExpressionsCommand. - * - * @category VuFind - * @package Search - * @author Demian Katz - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org - */ -class WorkExpressionsCommandTest extends TestCase -{ - /** - * Test that the command works as expected with both parameters provided - * - * @return void - */ - public function testBasicUsageOfCommand(): void - { - $params = new \VuFindSearch\ParamBag([]); - $backendId = 'bar'; - $backend = $this - ->getMockBuilder(\VuFindSearch\Backend\Solr\Backend::class) - ->disableOriginalConstructor()->getMock(); - $backend->expects($this->once())->method('getIdentifier') - ->will($this->returnValue($backendId)); - $result = new RecordCollection([]); - $backend->expects($this->once())->method('workExpressions') - ->with( - $this->equalTo('id'), - $this->equalTo(true), - $this->equalTo($params) - )->willReturn($result); // not a realistic value! - $command = new WorkExpressionsCommand( - $backendId, - 'id', - true, - $params - ); - $this->assertEquals($result, $command->execute($backend)->getResult()); - } -}