-
Notifications
You must be signed in to change notification settings - Fork 393
Add vufind_sort option to [Loans] in Folio.ini #5109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from 6 commits
8a8ae3f
6092db7
0d1b0ae
a7db085
3c4749b
b45c4d2
70ebcc1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -236,18 +236,46 @@ in_transit[] = "Open - Awaiting delivery" | |
| ; the system will attempt to reconcile the global page size config there with the | ||
| ; available options defined here. | ||
| page_size[] = 50 | ||
| ; Sort options | ||
| ; Note: When choosing a sort, ensure that you select | ||
|
|
||
| ; Sort options available in the "Checked Out Items" screen. | ||
| ; These will be passed through to the FOLIO API as sortby parameters | ||
| ; unless configured as a key in the vufind_sort option to be used | ||
| ; to sort the items after they are returned from the API. | ||
| ; | ||
| ; This should be filled out as: sort[FOLIO_SORTBY_PARAM] or sort[VUFIND_SORT_KEY] | ||
| ; with the value being the display label. | ||
| ; For example to use FOLIO API sort, sort[itemId/sort.ascending] will pass | ||
| ; the value 'itemId/sort.ascending' to the sortby parameter of the FOLIO API. | ||
| ; To use the VuFind sort, sort[title] will check the vufind_sort[] for a key of title | ||
| ; and sort by that option's value. | ||
| ; | ||
| ; Note: When choosing a FOLIO sort parameter, ensure that you choose | ||
| ; field(s) that will return the records in a consistent order so that | ||
| ; when paginating, will get all of the records in the same order for | ||
| ; when paginating you will get all of the records in the same order for | ||
| ; every page of results without possibly having duplicates appear or missing items. | ||
| ; For example, using just dueDate will cause problems if there are more than | ||
| ; your page_size of items due on the same day since the order is not guaranteed to be | ||
| ; the same for non-unique values. | ||
| ;sort[dueDate/sort.ascending itemId/sort.ascending] = sort_due_date_asc | ||
| ;sort[dueDate/sort.descending itemId/sort.ascending] = sort_due_date_desc | ||
| sort[dueDate/sort.ascending itemId/sort.ascending] = sort_due_date_asc | ||
| sort[dueDate/sort.descending itemId/sort.ascending] = sort_due_date_desc | ||
| ;sort[title] = sort_title | ||
|
|
||
| ; This optional setting sorts the results using a natural sort algorithm on the | ||
| ; specified field of the VuFind checked out items output, which can be useful when FOLIO's | ||
| ; native sort does not allow sorting on the desired field. | ||
| ; If used, the key here should match the key used in the sort[] option and the value should | ||
| ; be the field within the check out items output to sort by. | ||
| ; For example, if you have sort[title] = sort_title then you could set vufind_sort[title] = "title" | ||
| ; to create a sort option by the "title" field with a display label of sort_title. | ||
| ; See the formatTransactionItem function for a full list of the available fields. | ||
| ; Note that it will have performance implications since it will have to pull all loans, | ||
| ; sort them, then slice the results down to the page size instead of | ||
| ; only querying FOLIO for the current page size of results. For most users with loans | ||
| ; spanning only one or two pages this will not have a significant impact. | ||
| ;vufind_sort[title] = "title" | ||
|
|
||
| ; Default sort (note: this must be defined in the sort[] options above to be applied!) | ||
| ;default_sort="dueDate/sort.ascending itemId/sort.ascending" | ||
| default_sort="dueDate/sort.ascending itemId/sort.ascending" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same question here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
|
|
||
| [CourseReserves] | ||
| ; If set to true, the course number will be prefixed on the course name; if false, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -40,6 +40,7 @@ | |||||
| use VuFindHttp\HttpServiceAwareInterface as HttpServiceAwareInterface; | ||||||
|
|
||||||
| use function array_key_exists; | ||||||
| use function array_slice; | ||||||
| use function count; | ||||||
| use function in_array; | ||||||
| use function is_callable; | ||||||
|
|
@@ -1144,19 +1145,32 @@ protected function formatHoldingItem( | |||||
| * @return array | ||||||
| */ | ||||||
| protected function sortHoldings(array $holdings, string $sortField): array | ||||||
| { | ||||||
| return $this->sortArray($holdings, $sortField); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Given an array and a sort field, sort the array. | ||||||
| * | ||||||
| * @param array $data Array to sort | ||||||
| * @param string $sortField Sort field | ||||||
| * | ||||||
| * @return array | ||||||
| */ | ||||||
| protected function sortArray(array $data, string $sortField): array | ||||||
|
demiankatz marked this conversation as resolved.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we do this anywhere else? If so, I wonder if a trait would make sense. But I didn't check, so maybe that's a premature suggestion. :-)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There isn't anywhere else in the code that currently does a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, no sense in overengineering this prematurely. I just thought there might be another similar function somewhere else. Thanks for confirming that there is not! :-) |
||||||
| { | ||||||
| usort( | ||||||
| $holdings, | ||||||
| $data, | ||||||
| function ($a, $b) use ($sortField) { | ||||||
| return strnatcasecmp($a[$sortField], $b[$sortField]); | ||||||
| } | ||||||
| ); | ||||||
| // Renumber the re-sorted batch: | ||||||
| $nbCount = count($holdings); | ||||||
| $nbCount = count($data); | ||||||
| for ($nbIndex = 0; $nbIndex < $nbCount; $nbIndex++) { | ||||||
| $holdings[$nbIndex]['number'] = $nbIndex + 1; | ||||||
| $data[$nbIndex]['number'] = $nbIndex + 1; | ||||||
| } | ||||||
| return $holdings; | ||||||
| return $data; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
|
|
@@ -1829,53 +1843,90 @@ public function getMyTransactions($patron, $params = []) | |||||
| $limit = $params['limit'] ?? 1000; | ||||||
| $offset = isset($params['page']) ? ($params['page'] - 1) * $limit : 0; | ||||||
|
|
||||||
| $requestedSort = $params['sort'] ?? ''; | ||||||
| $vufindSortMap = $this->config['Loans']['vufind_sort'] ?? []; | ||||||
| $localSortField = $vufindSortMap[$requestedSort] ?? null; | ||||||
|
|
||||||
| $query = 'userId==' . $patron['id'] . ' and status.name==Open'; | ||||||
| if (isset($params['sort'])) { | ||||||
| $query .= ' sortby ' . $this->escapeCql($params['sort']); | ||||||
| } | ||||||
| $resultPage = $this->getResultPage('/circulation/loans', compact('query'), $offset, $limit); | ||||||
| $transactions = []; | ||||||
| foreach ($resultPage->loans ?? [] as $trans) { | ||||||
| $dueStatus = false; | ||||||
| $date = $this->getDateTimeFromString($trans->dueDate); | ||||||
| $dueDateTimestamp = $date->getTimestamp(); | ||||||
|
|
||||||
| $now = time(); | ||||||
| if ($now > $dueDateTimestamp) { | ||||||
| $dueStatus = 'overdue'; | ||||||
| } elseif ($now > $dueDateTimestamp - (1 * 24 * 60 * 60)) { | ||||||
| $dueStatus = 'due'; | ||||||
| $count = null; | ||||||
|
|
||||||
| // Fetch data from FOLIO, only pass sort to API if it is NOT handled locally by VuFind | ||||||
| if ($localSortField) { | ||||||
| $rawItems = $this->getPagedResults('loans', '/circulation/loans', compact('query')); | ||||||
| } else { | ||||||
| if (!empty($requestedSort)) { | ||||||
| $query .= ' sortby ' . $this->escapeCql($requestedSort); | ||||||
| } | ||||||
| $transactions[] = [ | ||||||
| 'duedate' => | ||||||
| $this->dateConverter->convertToDisplayDate( | ||||||
| 'U', | ||||||
| $dueDateTimestamp | ||||||
| ), | ||||||
| 'dueTime' => | ||||||
| $this->dateConverter->convertToDisplayTime( | ||||||
| 'U', | ||||||
| $dueDateTimestamp | ||||||
| ), | ||||||
| 'dueStatus' => $dueStatus, | ||||||
| 'id' => $this->getBibId($trans->item->instanceId), | ||||||
| 'item_id' => $trans->item->id, | ||||||
| 'barcode' => $trans->item->barcode, | ||||||
| 'renew' => $trans->renewalCount ?? 0, | ||||||
| 'renewable' => true, | ||||||
| 'title' => $trans->item->title, | ||||||
| ]; | ||||||
| $result = $this->getResultPage('/circulation/loans', compact('query'), $offset, $limit); | ||||||
| $rawItems = $result->loans ?? []; | ||||||
| } | ||||||
| // If we have a full page or have applied an offset, we need to look up the total count of transactions: | ||||||
|
|
||||||
| // Format the transaction results | ||||||
| foreach ($rawItems as $trans) { | ||||||
| $transactions[] = $this->formatTransactionItem($trans); | ||||||
| } | ||||||
|
|
||||||
| // If we have a full page, have applied an offset, or are not using a vufind_sort option, | ||||||
| // we need to look up the total count of transactions: | ||||||
| $count = count($transactions); | ||||||
| if ($offset > 0 || $count >= $limit) { | ||||||
| if (!$localSortField && ($offset > 0 || $count >= $limit)) { | ||||||
| // We could use the count in the result page, but that may be an estimate; | ||||||
| // safer to do a separate lookup to be sure we have the right number! | ||||||
| $count = $this->getResultCount('/circulation/loans', compact('query')); | ||||||
| } | ||||||
|
|
||||||
| // Apply local sorted if requested | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| if ($localSortField) { | ||||||
| $transactions = $this->sortArray($transactions, $localSortField); | ||||||
| $transactions = array_slice($transactions, $offset, $limit); | ||||||
| } | ||||||
|
|
||||||
| return ['count' => $count, 'records' => $transactions]; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Support method for getMyTransactions to parse a single | ||||||
| * transaction result. | ||||||
| * | ||||||
| * @param array $transaction An single transaction | ||||||
| * array from getMyTransactions | ||||||
| * | ||||||
| * @return string The FOLIO loan ID for this loan | ||||||
| */ | ||||||
| protected function formatTransactionItem($transaction) | ||||||
| { | ||||||
| $dueStatus = false; | ||||||
| $date = $this->getDateTimeFromString($transaction->dueDate); | ||||||
| $dueDateTimestamp = $date->getTimestamp(); | ||||||
|
|
||||||
| $now = time(); | ||||||
| if ($now > $dueDateTimestamp) { | ||||||
| $dueStatus = 'overdue'; | ||||||
| } elseif ($now > $dueDateTimestamp - (1 * 24 * 60 * 60)) { | ||||||
| $dueStatus = 'due'; | ||||||
| } | ||||||
| return [ | ||||||
| 'duedate' => | ||||||
| $this->dateConverter->convertToDisplayDate( | ||||||
| 'U', | ||||||
| $dueDateTimestamp | ||||||
| ), | ||||||
| 'dueTime' => | ||||||
| $this->dateConverter->convertToDisplayTime( | ||||||
| 'U', | ||||||
| $dueDateTimestamp | ||||||
| ), | ||||||
| 'dueStatus' => $dueStatus, | ||||||
| 'id' => $this->getBibId($transaction->item->instanceId), | ||||||
| 'item_id' => $transaction->item->id, | ||||||
| 'barcode' => $transaction->item->barcode, | ||||||
| 'renew' => $transaction->renewalCount ?? 0, | ||||||
| 'renewable' => true, | ||||||
| 'title' => $transaction->item->title, | ||||||
| ]; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Get FOLIO loan IDs for use in renewMyItems. | ||||||
| * | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was it a conscious choice to uncomment the previously commented-out defaults?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. That was unintentional. I just pushed a commit to undo that change.