Commit Graph

62029 Commits

Author SHA1 Message Date
Tomás Cohen Arazi 44cc4b367e
Bug 42719: [26.05.x] Handle missing CGISESSID in OAuth login (IdP-initiated flow)
When a user initiates login from the IdP (e.g. Okta app tile), they
hit the OAuth endpoint without an existing session cookie. The code
crashed calling ->value on an undefined cookie object.

This patch:
- Removes the premature 'No user session found' guard that blocked
  IdP-initiated flows entirely
- Creates a session on-the-fly for the initial request when no
  cookie exists (IdP-initiated flow)
- On callback, redirects with wrong_csrf_token error instead of
  crashing when the cookie is missing

CSRF protection is preserved: the state token is bound to the
session created in the initial request, and the browser returns
the cookie on callback for validation.

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
(cherry picked from commit cd02922675f42f1c404acaa274d14fd155778941)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-25 09:42:15 -06:00
Tomás Cohen Arazi 417ac6fb03
Bug 42719: [26.05.x] Add regression tests
Add tests for the OAuth/OIDC login endpoint covering:
- IdP-initiated flow (no CGISESSID cookie on initial request)
- Callback without CGISESSID cookie (session lost)
- Normal SP-initiated flow (cookie present)

Tests create a real identity provider in the database and assert:
- Initial request without cookie redirects to the IdP authorize URL
- A CGISESSID cookie is set for the new session
- Callback without cookie returns wrong_csrf_token error (not 500)
- Normal flow with cookie redirects to IdP as expected

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
(cherry picked from commit 4d7869ccb1155cda2be2f0b09933528de2dd9a85)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-25 09:42:14 -06:00
Jonathan Druart 5edd58772f
Bug 43267: [26.05.x] Reports - only send visible records to batch operations from DT view
When opening report results in the new DataTables view, batch
operations should only send visible records. Same as the normal view.

Test plan:
1. Create and run a report that will display more resulsts than fit on
   one page
2. Click "Open in DataTables".
3. Note "Batch operations with X visible records" shows the default
   page size (=20), and open the "Batch operations" dropdown to
   send results to e.g. batch item modification or batch record
   modification.
4. Confirm only the values on the currently visible page are sent, not
   the entire set.
5. Change the DataTable's page, or filter/search within it, and repeat
=> Confirm the count and the sent values update to the number of visible records
6. Confirm the standard (non-DataTables) report view is unaffected.

Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-25 09:42:02 -06:00
Matt Blenkinsop f19d25d60d
Bug 43320: (QA follow-up) Add html filter and fix translatability
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-24 16:01:36 -06:00
Nick Clemens 69904f28ae
Bug 43320: OPAC adjustments
Similar test plan, but on the OPAC

Signed-off-by: Phil Ringnalda <phil@chetcolibrary.org>
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-24 16:01:35 -06:00
Nick Clemens 8bf971217c
Bug 43320: Don't quoted already quoted searches and add feedback
Bug 31213 added a quoted search when no results were found,
this patch builds on that to:
1 - Notify the user when their search is repeated quoted
2 - Not repeat a search when already quoted

To test:
 0 - Set system preferences
     RedirectToSoleResult to 'Don't redirect'
     IntranetAddMastheadLibraryPulldown to Show
     IntranetCatalogSearchPulldown to Show
 1 - Add the sample records to your catalog
 2 - Search for the quoted phrase "happy family big" in the 'title' index
 3 - Note you get a result
 4 - Check the record - the phrase is not found, but the record contains all the terms
 5 - Search for the unquoted phrase: 6:20 man
 6 - Confirm search is quoted and result found
 7 - Apply patch, restart all
 8 - Repeat 5
 9 - Confirm you are now told search was quoted and result found
10 - Repeat 2
11 - Confirm no result found, no notice of repeated search

Signed-off-by: Phil Ringnalda <phil@chetcolibrary.org>
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-24 16:01:35 -06:00
Andrii Nugged 199e65af66
Bug 42605: Add automated tests
Store scalar preference values when saving the acquisition preferences
and clean up the invoice explicitly.

Exercise the rendered receiving behavior for a basket that inherits
AcqCreateItem, one that explicitly overrides it with "ordering", and a
basket that creates items on receiving. Keep the explicit "ordering"
case as a control for behavior that already works without the production
fix.

This changes tests only.

Automated tests:

yarn cypress run --spec \
  t/cypress/integration/Acquisitions/OrderReceivePreferences_spec.ts

Co-Authored-By: Loontik <loontik@nugged.team>
Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-24 16:01:34 -06:00
Andrii Nugged 8a68a3cda7
Bug 42605: Preserve acquisition preference string values
Bug 41563 converted AcqCreateItem and UniqueItemFields to booleans when
adding them to Koha.prefs. Both preferences are strings: AcqCreateItem
controls where items are created, while UniqueItemFields contains a
pipe-separated list.

When a basket inherits AcqCreateItem=ordering, the boolean value matches
none of the receiving page branches and existing items are hidden. When
items are created on receiving, the numeric UniqueItemFields value also
fails when the page calls split().

Preserve both string values in Koha.prefs. Add a Cypress regression test
which renders orderreceive.pl and verifies the values exposed to
JavaScript.

Test plan:

Before applying the patch:

1. Set AcqCreateItem to "placing an order" and UniqueItemFields to
   "barcode".
2. Create a basket that inherits the system preference. Add an order with one
   item, close the basket, and start receiving it.
3. Confirm that the Items table has no existing item row and no Receive
   checkbox.
4. Set AcqCreateItem to "receiving an order" and open the same order for
   receiving.
5. Confirm that the Items section is empty: no item-entry fields and no Add
   item button are shown.

Apply the patch.

After applying the patch:

1. Set AcqCreateItem back to "placing an order" and open the order for
   receiving again.
2. Confirm that its existing item is listed and has a Receive checkbox.
3. Set AcqCreateItem to "receiving an order" and open the same order again.
4. Confirm that the Items section contains item-entry fields and an Add item
   button.

Co-Authored-By: Loontik <loontik@nugged.team>
Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-24 16:01:26 -06:00
Olivia Reynolds 4a7d08942c
Bug 40668: Don't depend on checkboxes existing in drawCallback
The checkboxes this callback listens to events on are conditionally
rendered, depending on whether the user has permission to edit each
item. When moving from a page with no checkboxes displayed to one with
checkboxes displayed, the checkbox elements may not exist at the time of
this callback, so the listener is not attached and the checkboxes are
inoperable.

This patch fixes this by using a delegated event handler on the row,
which doesn't depend on the checkbox existing at the time.

Test plan:
1.  Enable the system preference EnableItemGroups.
2.  Set up a non-super-librarian patron, with permission to:
    - view the catalogue (catalogue)
    - create update and delete item groups (manage_item_groups)
3.  Place this patron's library in a group by itself, with "limit item
    editing" enabled. The patron should only be able to edit items from
    their own library.
4.  Pick an item in the catalogue, and add at least 40 items to it from
    a library the patron cannot edit items from. Add at least one item
    from the patron's library that they can edit. The 40 items are to
    ensure there is a complete (20 item) page that the patron cannot
    edit anything on.
5.  Create an (empty) item group on this catalogue entry.
6.  Log in as the unprivileged patron and navigate to the holdings view
    for the relevant catalogue entry.
7.  Navigate through the holdings table pages until there is a page with
    no checkboxes.
8.  Navigate to a table page with a checkbox. Select one of the
    checkboxes, and verify no actions appear at the top of table, even
    though you should have permission to add this item to a group.
9.  Apply this patch, and hard refresh to load the new JavaScript.
10. Repeat steps 6-8, verifying the checkbox now appears correctly.
11. Verify you can add the item to an item group using the now-appearing
    action.

Sponsored-by: Open Fifth
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:46 -06:00
Jennifer Sutton 6b7bd06697
Bug 30759: Add hint about the data that is sent via the Google Books API to OPACSuggestionAutoFill
Add information about the data that is sent to Google if the
OPACSuggestionAutoFill system preference is enabled.

Test plan:
1. Go to Administration > System preferences.
2. Search for the OPACSuggestionAutoFill system preference.
3. Note that there is no note about the data that is sent to
   Google if the system prference is enabled.
4. Apply the patch.
5. Refresh the page.
6. There is now a note about the data that is sent to Google.
7. Check that it reads well and makes ense.

Sponsored-by: Catalyst IT
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:46 -06:00
Owen Leonard 38e48ae236
Bug 43177: Use archived link for Bridge Material Type Icon Set
This patch updates the About page in the section for the Bridge Material
Type Icon Set. The link is updated to use the last valid saved version
on the Internet Archive.

Sponsored-by: Athens County Public Libraries
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:45 -06:00
Pedro Amorim cf5fbc98ec
Bug 43091: (RM follow-up) Give the OPAC self-renewal island a Pinia store
hydrate() only installs Pinia for an island when its config.stores is
non-empty. patron-self-renewal kept config: {} after islands-opac.ts
was split out, so it never got one.

http-client.js's post() calls submitting(), which needs Pinia's
useMainStore(). With none active, it throws before fetch() runs -
get() skips submitting() by default, so only the actual renewal
submission failed.

Test plan:
prove t/cypress/integration/Islands/SelfRenewal.ts

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:44 -06:00
Paul Derscheid daa731ca20
Bug 43091: Clean the OPAC Vue dist directory in js:clean
js:clean predates the OPAC islands build (bug 26355) and only removes
the intranet and Cypress dist directories, so stale chunks survive in
koha-tmpl/opac-tmpl/bootstrap/js/vue/dist/ across rebuilds.

- add the OPAC Vue dist directory to js:clean

Test plan:
1. yarn js:build, then apply this patch series and yarn js:clean
2. ls koha-tmpl/opac-tmpl/bootstrap/js/vue/dist/
   => empty, no stale staff-only chunks remain
3. yarn js:build
   => only islands.esm.js and a patron-self-renewal chunk are emitted

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:44 -06:00
Paul Derscheid 485a7038e9
Bug 43091: Stop emitting staff-only Vue islands into the OPAC dist
Both islands builds share modules/islands.ts, which hardcodes every
island. The OPAC compilation therefore emits staff-only lazy chunks
(acquisitions-menu, vendor-menu, admin-menu) into
koha-tmpl/opac-tmpl/bootstrap/js/vue/dist/, and the OPAC islands.esm.js
bundles the staff Pinia stores.

- split modules/islands.ts into shared machinery and per-application
  entry points (islands-intranet.ts, islands-opac.ts)
- declare each application's islands as a Map literal and feed it
  through registerIsland(), the same path plugin islands take
- pass store definitions into hydrate() instead of importing every
  store in the shared module
- keep the full plugin import surface (registerIsland, hydrate, Vue
  re-exports) on both entries via star re-exports
- point the rspack islands entries at the per-application modules

Test plan:
1. yarn build
2. ls koha-tmpl/opac-tmpl/bootstrap/js/vue/dist/
   => only islands.esm.js and a patron-self-renewal chunk are emitted
3. ls koha-tmpl/intranet-tmpl/prog/js/vue/dist/
   => acquisitions-menu, vendor-menu and admin-menu chunks are still
   present
4. In the staff interface, visit pages using the acquisitions, vendor
   and admin menu islands and verify they render
5. Enable self-renewal for a patron's category and put the patron
   inside the availability window, e.g.:
   UPDATE categories SET self_renewal_enabled = 1
     WHERE categorycode =
     (SELECT categorycode FROM borrowers WHERE userid = 'koha');
   UPDATE borrowers
     SET dateexpiry = DATE_ADD(CURDATE(), INTERVAL 7 DAY),
     debarred = NULL WHERE userid = 'koha';
6. Log into the OPAC as that patron and open 'your summary'
   => the patron-self-renewal chunk loads from
   /opac-tmpl/bootstrap/js/vue/dist/ and the self-renewal modal
   completes successfully

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:43 -06:00
Martin Renvoize 72bb057ecf
Bug 43088: Reuse _current_directory() instead of duplicating pwd() calls
_change_directory(), _list_files() and _is_connected() each called
$self->{connection}->pwd directly for their log payloads/connectivity
check, duplicating exactly what _current_directory() now provides as a
proper, documented internal accessor. Route them through it instead -
no behaviour change, just removing the duplication now that the
wrapper exists.

Test plan:
1. prove -r t/db_dependent/Koha/File/
   => All tests successful (32 tests), including the existing
      current_directory() and list_files()/change_directory() coverage.
2. koha-qa.pl -v 2 --more-tests
   => [PASS], no critic/pod warnings.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:43 -06:00
Martin Renvoize 04c67b7276
Bug 43088: Add a consistent current_directory() accessor to Koha::File::Transport
FTP, Local and SFTP list_files() were unified to return the same flat
shape, but consumers still had no portable way to ask a transport for
its current remote directory - the underlying libraries' own methods
of that name don't agree on what "cwd" means. Net::SFTP::Foreign's
cwd() is a pure read-only accessor, but Net::FTP's cwd() is a mutator:
called with no argument it defaults to "/", issues a real CWD command,
and returns a boolean rather than a path.

The koha-plugin-transport-browser plugin discovered this the hard way:
it read $transport->{connection}->cwd directly to capture the initial
working directory, which happened to work for SFTP but silently reset
the FTP connection to root and captured "1" (a boolean) as the "path"
on every request, breaking directory navigation for FTP transports.

Add a public current_directory() method to the Koha::File::Transport
base class, following the same connect-on-demand pattern as
list_files()/upload_file()/etc, with a _current_directory() hook each
subclass implements using its own real read-only accessor: pwd() for
FTP, cwd() for SFTP, and the tracked {current_directory} (falling back
to download_directory) for Local. Consumers should use this instead of
reaching into transport internals.

Test plan:
1. prove t/db_dependent/Koha/File/Transport.t
        t/db_dependent/Koha/File/Transport/FTP.t
        t/db_dependent/Koha/File/Transport/Local.t
        t/db_dependent/Koha/File/Transport/SFTP.t
   => All tests successful, including the new current_directory()
      tests subtest in each transport test file, which mock the
      underlying libraries (Net::FTP / Net::SFTP::Foreign) to assert
      each backend reads its own real read-only accessor.
2. koha-qa.pl -v 2 --more-tests
   => [PASS] for all four changed modules, no critic/pod warnings.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:42 -06:00
Martin Renvoize f901ad6d67
Bug 43078: Exclude '.' and '..' entries from SFTP file listings
The FTP and Local transports both explicitly filter out '.' and '..'
pseudo-entries when listing a directory, but the SFTP transport never
did - it relied on the assumption that Net::SFTP::Foreign's ls() already
excludes them. It doesn't: ls() returns exactly whatever entries the
remote server includes in its SSH_FXP_READDIR response, with no default
filtering. Whether '.'/'..' show up therefore depends entirely on the
remote SFTP server implementation, producing inconsistent results between
otherwise identically configured SFTP accounts.

Test plan:
1. prove t/db_dependent/Koha/File/Transport/SFTP.t
   => fails before this patch (listing includes '.' and '..')
   => passes after this patch
2. prove -r t/db_dependent/Koha/File/Transport/ t/db_dependent/Koha/File/Transports.t
   => all still pass

Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:42 -06:00
Martin Renvoize 4f39b08db6
Bug 43078: Include longname and perms keys in FTP's NLST fallback listing
The MLSD path, SFTP, and Local always return all six documented
list_files() keys (filename, longname, size, perms, mtime, type) - undef
where the value is unknown, but the key always present. The NLST
fallback path (servers without MLSD support) only set filename, size,
mtime and type, omitting longname and perms entirely rather than
setting them to undef.

Functionally harmless for consumers reading $file->{perms} (Perl
returns undef for a missing hash key too), but it breaks the "same flat
shape" contract this bug established, and would trip up any consumer
using exists() instead of defined() to check for a key.

Test plan:
1. prove t/db_dependent/Koha/File/Transport/FTP.t
   => All tests successful, including the new assertion that longname
      and perms keys are present (as undef) on the NLST fallback path.
2. koha-qa.pl -v 2 --more-tests
   => [PASS], no critic/pod warnings.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:41 -06:00
Martin Renvoize 2f1eb2db84
Bug 43078: Unify file transport list_files() across FTP, Local and SFTP
Net::SFTP::Foreign's ls() returned file metadata with size, permissions
and modification time nested inside a Net::SFTP::Foreign::Attributes
object, while FTP and Local returned flat hash keys and silently
dropped directories. Callers of list_files() needed backend-specific
parsing to get at file metadata or to know a directory even existed,
defeating the purpose of the shared transport API.

All three transports now return the same flat hashref shape per entry:
filename, longname, size, perms, mtime, type ('file'/'directory'/
'other'). Directories are included everywhere; '.' and '..' remain
excluded everywhere. FTP's MLSD path prefers the UNIX.mode fact for
exact Unix permissions, falling back to an approximation from the RFC
3659 perm capability fact when UNIX.mode isn't available, and parses
the modify fact into mtime; its NLST fallback (servers without MLSD)
probes each entry with SIZE/MDTM to recover size, mtime and a
best-effort type.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:41 -06:00
Owen Leonard c9b1c20c6f
Bug 43192: Cast escape_str(obj) arg to string to use escapeHtml func
The escape_str function in the OPAC requires the argument to be a string,
and will throw a fatal error if passed a Number. This is because
String.prototype.escapeHtml is created by Koha and is not a JS standard.
This patch converts the object to a string before applying escapeHtml.

To test, apply the patch and log in to the OPAC.

- If necessary, add a list.
- Search for records in the catalog and add one or more of the results
  to your new list.
- Go to Lists -> Your lists.
- In the list of your lists, click the "Delete" link for the list you
  added records to.
  - You should see a confirmation modal, "Are you sure you want to
   delete this list?" showing the name of the list and the number of
   items on it.
  - Clicking "Yes, delete" should delete the list.

Sponsored-by: Athens County Public Libraries
Signed-off-by: Roman Dolny <roman.dolny@jezuici.pl>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:40 -06:00
David Nind 1c4f539c73
Bug 43173: Update the terminology for the log viewer - "cardnumber" to "card number"
Update the log viewer to change "Modify cardnumber" to
"Modify card number", as per the terminology guidelines
https://wiki.koha-community.org/wiki/Terminology#C

Test plan:
1. Edit a patron and change their card number under the library
   management section.
2. Go to Tools > Additional tools > Log viewer.
3. Note under the actions section that there is an action:
   Modify cardnumber
4. Click "Submit" to see the log viewer results.
5. Note that there is an entry for the patron card number change
   with the action: "Modify cardnumber".
6. Apply the patch.
7. Refresh the log viewer page.
8. Note that "Modify cardnumber" is now "Modify card number"
   in both places.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Gretchen <maxeinergl@gcc.edu>
Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:40 -06:00
Jonathan Druart cadb36fcaf
Bug 43168: Add a test
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:39 -06:00
Nick Clemens c277de2e70
Bug 43168: Check if there are errors, not if variable defined
$errors is an array ref returned from a blank array variable

if( $errors ){ #this will be true

if( scalar @$errors ){ #only true when array has members

To test:
1 - tail -f /var/log/koha/kohadev/intranet-error.log
2 - Stage a marc file
3 - Note the error:
==> /var/log/koha/kohadev/intranet-error.log <==
[2026/07/23 19:11:37] [WARN] The following error(s) occurred during ISO2709 record import:
ERROR:  Koha::ImportBatch::try {...}  /kohadevbox/koha/Koha/ImportBatch.pm (105)
4 - Apply patch
5 - Restart all
6 - Stage a file
7 - No error!

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:39 -06:00
David Cook 8dda84df37
Bug 43159: Restore localisation of PERL5LIB and KOHA_HOME
This change localises PERL5LIB and KOHA_HOME,
which means that any changes made to PERL5LIB or KOHA_HOME
within _do_instance() in koha-plack are confined to the specific
instance being worked on in that function.

See Bugzilla for steps on how to reproduce the problem.

Test plan:
- Apply the patch
- sudo vi debian/scripts/koha-plack

Within _do_instance after PERL5LIB is set, add the following:
echo $PERL5LIB

- sudo koha-create --request-db test1
- sudo ./debian/scripts/koha-plack --restart test1 test1 test1 test1
- Note that now PERL5LIB stays constant:

/usr/share/koha/lib:/usr/share/koha/installer:/usr/share/koha/lib/installer

- git restore debian/scripts/koha-plack

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:38 -06:00
Laura_Escamilla 2baaa00a31
Bug 43134: Add missing colons to OPAC advanced search section headings
To test :
1. Apply the patch
2. Go to the OPAC advanced search page http://kohadev.mydnsname.org:8080/cgi-bin/koha/opac-search.pl
3. Click More options
4. Notice that all section titles now use colons
   - "Search for:" = colon
   - "Limit to any of the following:" = colon
   - "Location and availability:" = colon
   - "Sort by:" = colon
   - "Publication range" = colon
   - "Language" = colon
   - "Audience" = colon
   - "Content" = colon
   - "Format" = colon
   - "Additional content types..." = colon
5. Sign off and have an incredible day! :)

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:38 -06:00
Kyle M Hall b9156c1feb
Bug 43103: Switch OR chains to INs for batch item modification and patron deletion
Three searches pass large ID lists:
* Koha::BackgroundJob::BatchUpdateItem passes every itemnumber of the
  batch, and batch item modifications can cover tens of thousands of
  items
* Koha::Items::batch_update does the same with the modified
  itemnumbers when collecting biblionumbers for reindexing
* Koha::Patrons::filter_by_safe_to_delete does it with the
  borrowernumbers found safe to delete ( unlikely to approach
  the same numbers as items/bibs, but still good to fix )

This patch switches all three to IN. The lists are still passed as
values, but the query stays a flat IN list the optimizer handles well
instead of a chain of ORs that can't be optimized.

Test Plan:
1) Apply this patch
2) prove t/db_dependent/Koha/Items/BatchUpdate.t
3) prove t/db_dependent/Koha/Patrons.t
4) Note all tests pass!

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:37 -06:00
Martin Renvoize b07514bcfb
Bug 43082: Fix flaky object filter test in action_logs.t
The default `_match=contains` matching builds a LIKE query even on
integer columns, so a plain `?object=42` also matches object values
like 420 or 142. The test's dynamically-assigned patron borrowernumber
(auto_increment, never reset by transaction rollback) could drift into
a value containing "42" as a substring, intermittently inflating the
match count in CI. Add `_match=exact` since the test's intent is an
exact object id match.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:37 -06:00
Jonathan Druart 06eafc0d60
Bug 43053: Simplify code, only 1 return statement
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:36 -06:00
Matt Blenkinsop db56e2f581
Bug 43053: Fix display of vendor payment methods
Test plan:
1) Add multiple vendor payment method authorised values
2) Create a vendor and add multiple payment methods
3) Click to edit, the payment method will be displaying one option of a "|" concatenated string
4) Apply patch and run yarn js:build
5) Hard refresh the browser, the payment methods should now display correctly
6) Edit the payment methods and save, the saved changes should be correctly displayed on the vendor details page
7) Add a new vendor with multiple payment methods, it should save correctly

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:36 -06:00
Jonathan Druart a077c111a8
Bug 43053: Add a Cypress test
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:35 -06:00
Matt Blenkinsop 65210cf55a
Bug 42827: Restore values to the Items expected column in parcels.pl
Test plan:
1. Create an order with multiple items and receive the order in full
2. From the vendor record, click Receive shipments
3. You should be in parcels.pl and the table should show your shipments
4. The Items expected column will show 0 even though you ordered multiple items
5. Apply patch and restart_all
6. Refresh the page, the column should now show a value

Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:35 -06:00
Owen Leonard 07691a589a
Bug 41116: (follow-up) Fix template variable filter
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:34 -06:00
Owen Leonard 5ba8ab39ab
Bug 41116: (follow-up) Some more fixes for consistency
- There was a mix of "patronphone" and "patron-phone" and I fixed it to
  standardize on "patron-phone" (and patron-email) which I find easier
  to read.
- I made similar changes to the branchtransfers template
- Corrected the TT filter on mailto links from "html" to "uri"

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:34 -06:00
Andrew Fuerste Henry bf451c7fe9
Bug 41116: Standardize selectors in patron contact information in hold found modals
This patch modifies both hold-found-modal and hold-found1. It adds a
class to the patron phone number. For patron email, it changes the
existing id to a class, expands the selector to include the bullet
point in hold-found-modal, and standardizes the name (changing from
"#boreamil' to ".patronemail").

To test:
1 - have a patron with both a phone number and an email address
2 - create a hold for your patron
3 - check an item in to fill your hold, triggering the hold-found-modal
4 - inspect the patron contact info, confirm there is no class on the
    phone number
5 - confirm there is an id on the patron email but it does not include
    the bullet point and is inconsistent with the names of other classes
    in the modal
6 - click Confirm Hold
7 - check your item in again, triggering the hold-found1 modal
8 - confirm there is no class on the patron phone number
9 - confirm there is an id on the patron email with an inconsistent
    name
10 - revert the waiting status of your hold
11 - apply patch, restart_all
12 - check your item in again, triggering hold-found-modal
13 - confirm the patron phone now has a class, .patronphone
14 - confirm the patron email now has a class, .patronemail, that the
     class includes the bullet point, and that the #boremail id has been
     removed
15 - click Confirm Hold
16 - check your item in again, triggering hold-found1 modal
17 - confirm the patron phone now has a class, .patronphone
18 - confirm the patron email now has a class, .patronemail, and that
     the #boremail id has been removed

Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:33 -06:00
Jan Kissig d95de3d3c3
Bug 40201: Add addidtional fields to subscription search on serials home
This patch adds additional fields (table subscription, searchable) to the subscription search form on serials home.

To test (ktd):
a) create some additional fields in Admin -> Additional fields -> Serials subscriptions. Make sure the 'Searchable' checkbox is checked.
b) go to serials home: More -> Serials
c) Check that the form is missing the additional fields just defined.
d) apply patch and call restart_all
e) reload serials home and check that the search form is now extended with the additional fields

Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:33 -06:00
Chris Nighswonger 17d3a9ca1c
Bug 41717: Bump PDF::Reuse and PDF::Reuse::Barcode versions
PDF::Reuse 0.43 fixes a TTFont/docProxy lifecycle bug that caused
prEnd() to crash when TrueType fonts were used.

PDF::Reuse::Barcode 0.09 is the current stable release.

Testing plan:

- Start ktd, note older perl modules versions under About Koha
- Apply patch
- ktd --shell
- sudo cpan -i PDF:Reuse; sudo cpan -i PDF:Reuse:Barcode
- Let cpan auto set itself up (not sure if sudo is needed above)
- `restart_all`
- Revisit About Koha; module versions should be 0.43 & 0.09 respectively

Signed-off-by: Eric Phetteplace <ephetteplace@cca.edu>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:32 -06:00
Andrii Nugged ca098dd521
Bug 42845: Add ILL config endpoint for Vue app
The ILL Vue app currently reads ILLModule and ILLPartnerCode through the system preferences service. That service requires parameters/manage_sysprefs, so a staff user with ILL permissions but without system preference administration permissions cannot load the ILL module.

Add an ILL-specific /ill/config REST endpoint protected by the ill permission, and switch the ILL Vue app to load its configuration from that endpoint. This follows the module-specific configuration endpoint pattern introduced by bug 33606 for the same manage_sysprefs problem in the ERM Vue app.

Security/compatibility considerations: the endpoint returns only allow-listed, non-secret ILL configuration values needed by the ILL Vue app. It does not expose the generic system preferences API, and /api/v1/sysprefs remains restricted to parameters/manage_sysprefs.

Regression test coverage: the new API test verifies that a staff user with the ill permission can read /ill/config, that a staff user without the ill permission cannot read it, and that the same ILL-only user still cannot access /api/v1/sysprefs.

Test plan:

1. prove -I. -It/lib t/db_dependent/api/v1/ill_config.t

2. prove -I. -It/lib t/db_dependent/api/v1/ill_users.t

Signed-off-by: David Nind <david@davidnind.com>

Amended-by: Jonathan Druart
chmod +x t/db_dependent/api/v1/ill_config.t

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 14:21:26 -06:00
David Cook 2a8adb8b63
Bug 43401: (QA follow-up) tweak rspack.config.js comment and fix Makefile.PL
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:35 -06:00
Paul Derscheid e95ef486c2
Bug 43401: (follow-up) Note the Makefile.PL coupling in rspack.config.js
- Add a file-level comment reminding that every shipped output.path needs a
  matching 'NONE' target-map entry and cp step in Makefile.PL

Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:34 -06:00
Lucas Gass 7e9beb0bb0
Bug 43401: Send compiled js vue for the OPAC to the right dir
The OPAC vue bundle (koha-tmpl/opac-tmpl/bootstrap/js/vue/dist) was not
handled like its intranet counterpart in Makefile.PL: exclude it from the
generic target map and copy it explicitly into blib in move_compiled_js.

Test plan:
1. In a KTD shell, from the koha checkout:
     perl Makefile.PL
   (accept the defaults, 'standard' install mode is fine)
2. make -n move_compiled_js | grep 'js/vue/dist'
   => without this patch only the intranet cp line is printed;
      with it there is also a line copying
      koha-tmpl/opac-tmpl/bootstrap/js/vue/dist into
      blib/OPAC_TMPL_DIR/bootstrap/js/vue/
3. make
4. ls blib/INTRANET_TMPL_DIR/prog/js/vue/dist blib/OPAC_TMPL_DIR/bootstrap/js/vue/dist
   => both directories exist and contain the compiled bundles
      (e.g. islands.esm.js); no vue/dist directory is left anywhere
      else under blib.
5. git clean -xdf blib pm_to_blib Makefile Makefile.old && git checkout -- . to
   clean up.

Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:34 -06:00
Aleisha Amohia a32e722060
Bug 35729: Normalize ISBNs as ISBN-13 if cannot fallback to ISBN-10
ISBNs beginning with 979 do not have an ISBN-10 version, and need to be normalized to an ISBN-13 format. All others, if valid, can safely be normalized to ISBN-10 format (current behaviour).

To set up

1. Download the attached sample records with 979 ISBNs
2. Log into the staff interface and go to Cataloguing
3. Go to Stage MARC records for import and upload the sample MARC file
4. Stage and import the biblio records
5. Once imported, open the detail pages for some of the records
6. In another tab, do a catalogue search and open the detail pages for ISBN-10 records, for example biblionumbers 6 and 54

To test

1. Apply the patch and restart services
2. Log into the staff interface and go to Koha Administration, Global system preferences, Enhanced Content tab
3. Cycle through each cover image service, enabled by the system preferences
4. With each cover image service is enabled, refresh the record detail pages you have open. The ISBN-10 records should CONTINUE to show their cover images. The newly imported ISBN-13 records should NOW show their cover images.
5. Confirm tests pass: t/db_dependent/Koha.t

testing with ISBN 9798885795692 should return this image from Amazon: https://images-na.ssl-images-amazon.com/images/P/9798885795692.01.LZZZZZZZ.jpg
testing with ISBN 9798876536914 should return this image from Amazon: https://images-na.ssl-images-amazon.com/images/P/9798876536914.01.LZZZZZZZ.jpg

Sponsored-by: Horowhenua Libraries Trust
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:33 -06:00
Pedro Amorim 4ac8795e95
Bug 42973: (RM follow-up) Update tests number
Because of bug 42866
prove t/db_dependent/Koha/AdditionalContents.t

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:33 -06:00
Laura_Escamilla eeb73bd789
Bug 42973: Unit test
Added a unit test to confirm that search_for_display orders manually positioned news first, followed by unnumbered news by publication date descending.

Test passes:

prove t/db_dependent/Koha/AdditionalContents.t

Signed-off-by: Gretchen Maxeiner <MaxeinerGL@gcc.edu>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:32 -06:00
Laura_Escamilla 2c29581606
Bug 42973: Restore manual ordering for news
To test:
1. Create four OPAC news items:

   - "Pinned news item" with "Appear in position" = 1 and an older publication date.

   - "Newest unnumbered news item" with no position and the newest publication date.

   - "Middle unnumbered news item" with no position and an intermediate publication date.

   - "Oldest unnumbered news item" with no position and the oldest publication date.

2. View the OPAC main page.

3. Confirm the news items are ordered by publication date, with the newest item first.

Apply the patch.

4. Reload the OPAC main page.

5. Confirm the manually positioned news item appears first.

6. Confirm the remaining news items are ordered by publication date descending.

7. Confirm news items without an "Appear in position" value continue to display newest first.

8. Sign off and have a wonderful day!

Signed-off-by: Gretchen Maxeiner <MaxeinerGL@gcc.edu>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:31 -06:00
Jan Kissig a859898aba
Bug 41681: (follow-up) Fix record number count when broken records are processed
When running the script bulkmarcimport.pl, the number of MARC records reported at the end of the execution does not match the actual number of records processed from the input file.

This patch fixes 3 issues
- broken (invalid) records from batch get now counted (record_number)
- when using the number param (n) to limit the number of records to be processed valid and invalid records get counted
- when using th offset param (o) the scipt errored when broken records were part of the offset.

To test:

1. Download the MARC file with the broken record
2. Run the following import commands and compare the counted import numbers:
  a) all records
     perl misc/migration_tools/bulkmarcimport.pl -b -v -m MARCXML --file 2_records_1st_broken.xml
     1 MARC records done in 0.0421221256256104 seconds
  b) limit to 1 record in total
     perl misc/migration_tools/bulkmarcimport.pl -b -v -n 1 -m MARCXML --file 2_records_1st_broken.xml
     1 MARC records done in 0.0420489311218262 seconds
  c) limit to 1 record  offset 1 record
     perl misc/migration_tools/bulkmarcimport.pl -b -v -n 1 -o 1 -m MARCXML --file 2_records_1st_broken.xml
     :2: parser error : Opening and ending tag mismatch: leader2 line 2 and leader
  <leader2>00216nam a22001097a 4500</leader>

3. Apply the patch
4. Repeat steps in 2 and compare the results
  a) 2 MARC records done in 0.0405838489532471 seconds
  b) 1 MARC records done in 0.00948596000671387 seconds  *
  c) 1 MARC records done in 0.0294840335845947 seconds

*though this one was skipped

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:31 -06:00
Hammat Wele 237d7166d0
Bug 41681: bulkmarcimport.pl reports an incorrect number of MARC records processed
When running the script bulkmarcimport.pl, the number of MARC records reported at the end of the execution does not match the actual number of records processed from the input file.

To test:

1. Download the joined MARC file containing 5 records.
2. Run the import command:
   ./misc/migration_tools/bulkmarcimport.pl -b --file=marc_file.mrc
3. Check the final script report
   ==> 11 MARC records done in 0.566349983215332 seconds
   Expected output should show 5 records
4. Apply the patch
5. Repeat step 2, 3
   ==> The correct number is shown

Signed-off-by: Janusz Kaczmarek <januszop@gmail.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:30 -06:00
Jonathan Druart 05840d64af
Bug 42632: Fix "Manage bundle" after filters are shown/hidden
If "Show/Hide filters" link is clicked, the "Manage bundle" buttons do not longer work.

Test plan:
Edit a record, set leader 7=collection
In the holding list click "Manage bundle"
Click "Show filters"
Click one of the "Manage bundle" button
=> Without this patch nothing happens
=> With this patch applied the table displays the nested table with the
bundle details

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Anni <anni.maki-mantila@turku.fi>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:30 -06:00
Jonathan Druart 32a6c63872
Bug 42396: Adjust 'use' statements
Always include the plural version, not the singular one (the plural
imports the singular)

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:29 -06:00
Olivia Reynolds 2acaf4360a
Bug 42396: Remove C4::Stats::UpdateStats and delete module
This patch replaces all calls to C4::Stats::UpdateStats with the wrapped
function from the Koha namespace. As this is the last function in C4::Stats, the
module is also deleted.

Several tests depended on transitive includes to Koha::Statistics through
C4::Stats. I've identified uses of that module by searching, and added the
necessary use in each case. I've run `prove -r t xt` with this patch applied and
didn't hit any relevant errors.

Test plan:
1. Inspect the patch, and verify each changed call maintains the same parameters.
2. Apply patch.
3. Prove the following files:
   - t/db_dependent/Accounts.t
   - t/db_dependent/Circulation.t
   - t/db_dependent/Koha/Account.t
   - t/db_dependent/Koha/ILL/Request.t
   - t/db_dependent/Koha/Item.t
   - t/db_dependent/Koha/Pseudonymization.t
   - t/db_dependent/Koha/Recalls.t

Sponsored-by: Open Fifth

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:29 -06:00
Lari Taskula 7412a3e38d
Bug 42298: Automatic renewals should only respect the "No automatic renewals before" rule
To test:
1. prove t/db_dependent/Circulation.t
2. Observe success

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-09-14 09:08:28 -06:00