ownPagination set recordsFiltered on json.data instead of json, causing
DataTables to display "NaN total entries". Remove the artificial 5000
mechanism, propagate real counts from plugins that provide them, and
fall back to actual result counts for those that don't. Also removes a
dead drawCallback overwritten before it could fire.
Test plan:
1) Install this test version of the unpaywall plugin:
https://github.com/openfifth/koha-plugin-ill-avail-unpaywall/releases/tag/test
2) Enable ILLModule and ILLCheckAvailability
3) Configure the plugin and add any emaill address
4) Create a new ILL request:
<staff_url>/cgi-bin/koha/ill/ill-requests.pl?method=create&backend=Standard
5) Enter '42' for cardnumber, any library, and any DOI e.g. '123'.
6) Verify that pagination works as expected
Before patch, pagination controls dont show and the following label is shown:
No entries to show (filtered from NaN total entries)
Signed-off-by: Edith Speller <Edith.Speller@ukhsa.gov.uk>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This patch adds a maxlength attribute to a few form fields in the MARC
order accounts entry form. Text inputs should now allow the user the
enter more characters than the db will accept.
To test, apply the patch and enable the MarcOrderingAutomation system
preference if necessary.
- Go to Administration -> MARC order accounts -> New account.
- Test these inputs to confirm that you can't enter more characters than
their maxlengths:
- Description (250)
- Match field (10)
- Match value (50)
- Basket name field (10)
Sponsored-by: Athens County Public Libraries
Signed-off-by: Roman Dolny <roman.dolny@jezuici.pl>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The default message in the "Self-renewal failure message" field
(Administration > Patrons and circulation > Patron categories >
Account expiry and self-renewal) uses incorrect terminology.
Test plan:
1. Go to Administration > Patrons and circulation > Patron categories.
2. Click on a patron category.
3. Scroll down to the "Self-renewal failure message" field (in the
Account expiry and self-renewal section).
4. Note the text says "...your local branch...".
5. Apply the patch.
6. Reload the page.
7. Note that the text now says "...your library...".
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Bug 41604 made every page do a bit more work when it loads. This
Selenium test didn't wait for that work to finish before typing into
the search box, so sometimes it searched too early and got the wrong
results.
This adds a short wait after each page load so the test only searches
once the page is actually ready.
Introduced by: Bug 41604: Save user decision per column when visibility changes
Test plan:
prove t/db_dependent/selenium/patrons_search.t
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
If we define visibility_condition we must have implemented
bKohaColumnsUseNames correctly.
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Example: supplier_report on the basket page
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
- Modify column-visibility.dt event handler to store the visibility
preference of the user
- Improve _dt_force_visibility() to correctly pick the correctly visibility value depending
on visibility_condition, is_hidden, and the user preference
- Add _dt_get_expected_column_visibility() to guess what's the expected visibility
- Force boolean true/false (vs 1/0) using !!
- Rely on a global variable kohaTableUserChoices to store the user
choice. It will be part of the state and store in localStorage.
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
If a column must be displayed but was hidden before
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
There are 3 other places where we force the visibility of columns. They
must als use this new visibility_condition flag, so they are all using
it.
Test plan:
The 3 tables are:
1. basket with the columns edifact, modify, cancel
2. hold history with the column itemtype
3. batch edit patron with the columns checkbox, password expiration,
protected
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
We want to hide column if:
* the feature is not accessible (pref disabled or insufficient
permissions)
or
* the column is hidden in the settings
or
* the column has been hidden by the user
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Bug 41314 caused a regression, making it impossible to hide the Checkin column in the issues table in the patron's circulation page.
To recreate:
1. Hide the checkin column by default in circulation issues-table
1.1. Go to Administration > Table settings > Circulation tab > Jump to page : circulation > Table id: issues-table
1.2. Check 'Is hidden by default' for 'checkin'
1.3. Click 'Save'
2. logout and login
3. Checkout an item to a patron
3.1. In the search bar, set to Checkout, search for Henry
3.2. In the checkout field, enter the barcode 39999000010114 and press enter
--> In the table of issues, Checkin column is visible, it should be hidden by default
4. Apply the patch
5. Repeat step 2, 3
--> In the table of issues, Checkin column is not visible
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jason Robb <jrobb@sekls.org>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
To test:
1 - In Koha testing docker record 369 has invalid xml, otherwise corrupt a record like:
sudo koha-mysql kohadev
UPDATE biblio_metadata SET metadata = UpdateXML(metadata, '//datafield[@tag="040"]/subfield[@code="c"]',CONCAT('<subfield code',CHAR(27),'="c">OSt</subfield>')) WHERE
biblionumber=438;
2 - View the record in the staff client - note bad metadata message
http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=438
3 - Click 'Edit'
4 - Error 500, in logs:
Invalid data, cannot decode metadata object
5 - Apply patch, restart all
6 - Reload record and click edit
7 - Success! Message about bad metadata, but can edit/save
Signed-off-by: Phil Ringnalda <phil@chetcolibrary.org>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The outer SELECT hardcoded unitprice_tax_included while the inner
subquery selects the field returned by FieldsForCalculatingFundValues.
With CalculateFundValuesIncludingTax disabled the derived table only
exposes unitprice_tax_excluded, so spent.pl dies with:
Unknown column 'unitprice_tax_included' in 'field list'
To test:
1. Set CalculateFundValuesIncludingTax to 'Exclude'
2. View spent.pl for a fund with received orders
3. Observe error 500
4. Apply patch, restart_all
5. Reload, page renders correctly
6. Set CalculateFundValuesIncludingTax back to 'Include'
7. Reload, page still renders correctly
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
To test:
1 - Have some received orders and some invoice adjustments
2 - View spent.pl for a fund
3 - Apply patch, restart_all
4 - Reload
5 - Confirm the display has not changed
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The previous patch hides the 'Account credit' option in the refund modal
when the accountline has no borrowernumber, but that is a UI convenience
only. A crafted POST (or a stale page) could still submit
refund_type=AC against an anonymous accountline, which would create a
REFUND credit with no patron to attach it to and leave the register
unbalanced because the payout branch is skipped.
Add a server-side guard in pos/register.pl that refuses the operation
and surfaces a new error_refund_anonymous_ac flag, rendered in
pos/register.tt in the same style as the other refund errors.
Test plan:
1. Apply the patch
2. Log in as a user with cash_management/anonymous_refund permission
3. Record an anonymous sale against a register
4. Using the browser devtools (or curl), POST to pos/register.pl with
op=cud-refund, refund_type=AC and the accountline id of the sale
5. => Confirm the request is rejected and the
"Account credit refunds are not available for anonymous transactions"
message is shown
6. => Confirm no REFUND accountline was created and the register
balance is unchanged
7. Repeat the POST with refund_type=CASH (or any non-AC type) and
confirm the refund + payout are created normally
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
When processing a refund through the POS register with refund type 'AC'
(Account Credit), the system was incorrectly creating both a REFUND credit
and a PAYOUT debit with payment_type = 'AC'.
When 'AC' is selected, the refund should remain as a credit on the patron's
account without creating a payout. This behavior was already correct in the
member account refund workflow (members/boraccount.pl) but was missing
from the POS refund workflow.
This patch:
1. Adds the same check to pos/register.pl that exists in members/boraccount.pl
to skip payout creation when refund_type is 'AC', making both workflows
consistent.
2. Fixes the JavaScript in register.tt to properly hide the 'AC' option for
anonymous transactions. The original check only tested for empty string,
but borrowernumber can be undefined/null, which needs to be handled.
Test plan:
Part 1: Test patron transaction refund with Account Credit (AC)
1. Find or create a test patron
2. On the patron's Accounting tab, manually add a charge (e.g., Manual fee)
3. Pay the fee off from the patron's Accounting tab
4. Navigate to Point of Sale > Transaction History
5. Find the payment transaction you just created
6. Click "Issue refund" on the payment line item
7. Verify that "Account credit" appears as an option in the "Transaction type"
dropdown
8. Select "Account credit" as the transaction type
9. Enter the refund amount and click "Confirm"
10. Navigate back to the patron's Accounting tab
11. Verify that a REFUND credit appears on their account
12. Verify that NO PAYOUT debit was created
13. Verify the credit remains on the patron's account (positive balance)
Part 2: Test patron transaction refund with Cash payout
16. Using the same patron, create another manual fee and payment
17. Navigate to Point of Sale > Transaction History
18. Click "Issue refund" on the new payment
19. Select "Cash" (or another payment type) as the transaction type
20. Enter the refund amount and click "Confirm"
21. Navigate back to the patron's Accounting tab
22. Verify both a REFUND credit and a PAYOUT debit appear
23. Verify the PAYOUT has the correct payment_type (e.g., CASH)
Part 3: Test anonymous transaction (no Account Credit option)
24. Navigate to Point of Sale
25. Add an item to sell and complete the payment
27. Navigate to Point of Sale > Transaction History
28. Find the anonymous payment you just created
29. Click "Issue refund" on the payment line item
30. Verify that "Account credit" does NOT appear in the "Transaction type"
dropdown (only payment types like Cash, Check, etc. should appear)
31. This confirms anonymous transactions cannot have account credits since
there's no patron account to credit
Expected results:
- Patron transactions show "Account credit" option in refund dropdown
- Anonymous transactions do NOT show "Account credit" option
- AC refunds create only REFUND credit (no PAYOUT debit)
- Non-AC refunds create both REFUND credit and PAYOUT debit
- Run: prove t/db_dependent/Koha/Cash/Register/Cashup.t
Signed-off-by: Laura Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Bug 40866 introduced JSON logging for HOLDS CREATE but stored null for
'confirmations' and 'forced' when no overrides were present. This patch
mirrors the earlier change to CIRCULATION ISSUE by defaulting them to
empty arrays, keeping the two log streams structurally identical and
simplifying reporting queries.
Changes:
C4/Reserves.pm:
- Default confirmations/forced to [] in the AddReserve log payload.
t/db_dependent/Reserves.t:
- Update the Bug 40866 subtest to assert the empty-array defaults on
normal holds, and fix a 'my $log_data' redeclaration.
tools/viewlog.pl:
- Extend the CSV export JSON-decode block to also cover HOLDS logs,
guarding the item lookup on itemnumber being present (HOLDS payloads
may lack one) and filling the CSV item columns from the decoded
payload. The legacy bare-itemnumber fallback is restricted to
CIRCULATION so a legacy HOLDS hold_id is not mistaken for an
itemnumber.
koha-tmpl/intranet-tmpl/prog/js/viewlog.js:
- Extend the info column override rendering (renderCircInfo) to HOLDS
entries so forced/confirmations arrays display translated, exactly as
they do for CIRCULATION. The log viewer moved to an ajax datatable in
bug 29016, so this replaces the earlier json_found change to
viewlog.pl/viewlog.tt.
misc/maintenance/migrate_action_logs_to_json.pl:
- Extended to handle legacy pre-Bug 40866 HOLDS CREATE logs where info
is a bare hold_id, recovering branchcode / biblionumber / itemnumber
from old_reserves / reserves.
- Uses the same keyset-pagination pattern as the circulation loop so
rows are not skipped under --commit.
Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This patch updates offline circulation and ILL checkouts to properly
record their nature in circulation logs as forced transactions.
Offline circulation (process_koc.pl):
- Offline transactions have already occurred without access to normal
circulation checks
- Now marks these as forced with 'OFFLINE_CIRCULATION' override code
- This helps identify historical transactions that bypassed checks
ILL checkouts (Koha/ILL/Request.pm):
- ILL checkouts are system-initiated and may bypass certain restrictions
by design
- Now marks these as forced with 'ILL_CHECKOUT' override code
- This helps track and report on ILL circulation activity separately
Display updates (action-logs.inc):
- Added translation strings for both new override codes:
- OFFLINE_CIRCULATION: "Offline circulation checkout"
- ILL_CHECKOUT: "ILL system checkout"
- These will now display properly in Tools > Log viewer
This ensures these special checkout types are properly identified in
reporting and analysis, making it easier to understand the context
of historical transactions.
Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This patch adds an out-of-band migration script to convert legacy
CIRCULATION ISSUE action logs from the old itemnumber-only format
to the new consistent JSON format.
The script:
- Finds all CIRCULATION ISSUE logs where info is just an itemnumber
- Converts them to JSON format with the standard structure
- Attempts to recover issue_id and branchcode from old_issues/issues
- Runs in dry-run mode by default (--commit flag to actually update)
- Processes in batches to handle large databases safely
- Includes verbose mode for detailed output
Usage:
perl misc/maintenance/migrate_action_logs_to_json.pl --help
perl misc/maintenance/migrate_action_logs_to_json.pl --verbose
perl misc/maintenance/migrate_action_logs_to_json.pl --commit
This is designed as an out-of-band maintenance script rather than
an atomic update because:
1. May be expensive on large databases with many log entries
2. Migration is optional - display code handles both formats
3. Can be run during off-peak hours at admin's discretion
Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Previously, CIRCULATION ISSUE logs would store just the itemnumber when
there were no confirmations or forced overrides, but would store a full
JSON structure when overrides were present. This inconsistency makes
reporting difficult as queries need to handle both formats.
This patch changes AddIssue to always store logs in JSON format,
matching the pattern already used in AddRenewal. The JSON structure
now consistently includes:
- issue: issue_id
- branchcode: branchcode
- itemnumber: itemnumber
- confirmations: array of confirmation codes (empty array if none)
- forced: array of forced override codes (empty array if none)
Benefits:
- Consistent data format simplifies reporting and analysis
- Matches existing RENEWAL logging pattern
- Display code (tools/viewlog.pl) already handles both formats,
so backward compatibility is maintained
Test plan:
1. prove t/db_dependent/Circulation.t
2. Perform a normal checkout - verify action log contains JSON
3. Perform a checkout with overrides - verify confirmations/forced
are populated in the JSON
4. Check Tools > Log viewer - both types should display correctly
Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Note: this requires a command line access to the test machine
TEST PLAN:
1 - Anywhere on the computer running koha, run following command:
mkdir tmp
echo '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body><p>Тетрис — это классика!</p></body></html>' > tmp/tmp.html
echo '* { color: red };' > tmp.css
./misc/cronjobs/printoverdues.sh tmp tmp.css
2 - Open the pdf in tmp/tmp.pdf, notice it is broken
3 - Apply patch
4 - Rerun ./misc/cronjobs/printoverdues.sh tmp tmp.css
5 - Open the pdf in tmp/tmp.pdf, notice it is now displaying properly, notice the css property still applies
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The previous two commits on this bug fixed two ordering assumptions in
the RETRY loop of _allocateWithTransportCostMatrix(): resetting $inf at
the start of each attempt, and splicing unallocated task indices out of
@requests in descending order (removing a lower index first would shift
the position of any higher index still waiting to be removed).
This is a third instance of the same underlying problem, a few lines
earlier in the loop that compacts the working cost matrix $m before
that splice runs. @unallocated is built by iterating over agents (item
rows), pushing the column index Munkres assigned to each row that
turned out infeasible - and Munkres' row-to-column assignment is a
permutation, not a monotonic function of the row index, so
@unallocated is no more reliably sorted here than it was for the
splice.
That compaction loop scans matrix columns in ascending order and
advances a single pointer into @unallocated, expecting to meet each
entry in that same ascending order. When @unallocated arrives out of
order, the pointer never catches up: columns that should have been
dropped are left in place, and the columns after them are never
shifted left to fill the gap. From that point on, $m no longer lines
up with @requests, which *is* correctly reduced by the splice - so on
the next retry pass a hold's transport cost gets evaluated using a
different hold's matrix row. Depending on the exact misalignment, this
can silently drop a fillable hold from the queue while a genuinely
available item sits unused, or fill a hold via the wrong-cost item.
It didn't show up in the "many holds" regression test added earlier on
this bug, because that test's transport cost matrix is uniform (every
disabled pair costs the same); this defect only surfaces once the
columns competing for a scarce item have distinct costs.
Sort @unallocated once, ascending, and use that copy for the
compaction pass; reverse it for the splice, which needs descending
order.
Test plan:
1. Run the new t/db_dependent/HoldsQueue/RetryAllocationOrdering.t -
it calls _allocateWithTransportCostMatrix() directly with a small
hand-built scarce transport cost matrix and a pinned srand() (the
specific item-to-branch permutation needed to trigger the bug
depends on the shuffle() inside the routine). Reverting just this
patch makes 3 of its 6 subtests fail: the L2 pickup hold is dropped
even though an available item could have filled it.
2. Run t/db_dependent/HoldsQueue/TransportCostOptimizations.t to
confirm no regression in the existing retry-loop coverage.
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
* The representation of the value "infinity" must be reset to -1 at the
start of each allocation attempt.
* Unallocated items must be spliced out from the candidate arrays in
reverse index order.
Test plan:
1. Run the unit tests in
t/db_dependent/HoldsQueue/TransportCostOptimizations.t
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
InstallPlugins forces every discovered plugin class to be deleted and
re-required from disk on every call, so plugin_methods reflects the
.pm file as it currently exists rather than whatever was already
loaded into a long-lived Plack worker. That deletion used
Symbol::delete_package, which clears the target package's whole
symbol table -- including any already-loaded packages nested under it
(e.g. a REST API controller a plugin bundles alongside itself, such as
Koha/Plugin/Foo/Controller.pm). Those nested classes keep their own
%INC entry, so they are never re-required afterwards and are left
permanently blanked out for the rest of the worker's life.
This was caught when running
`prove -r t/db_dependent/Koha/Plugins/ t/db_dependent/Koha/REST/Plugin/`
on top of the original patch. Tests fail several files that have nothing
to do with the bug being fixed (Biblio_and_Items_plugin_hooks.t,
Holds_hooks.t, TemplateIncludePathHook.t, REST/Plugin/PluginRoutes.t),
because Koha::Plugin::Test::Controller (a bundled test-fixture
controller living in t/lib/plugins/Koha/Plugin/Test/Controller.pm)
gets its symbol table wiped as collateral damage every time
Koha::Plugin::Test is reloaded.
_forget_plugin_class() replaces the delete_package call with the same
technique used by the CPAN module Class::Unload (not added as a
dependency here, just the technique): only clear the target class's
own symbols and reset its @ISA, explicitly leaving any nested package
entries in its symbol table alone. Module::Pluggable discovers bundled
nested classes as their own entries in the plugin list regardless, so
they still get reloaded correctly on their own turn.
I also annotate the no strict 'refs' block added by the previous commit
with a '## no critic' justification, as flagged by koha-qa.pl.
Test plan:
1. Confirm the bug exists without this patch:
a) git checkout <previous commit> (drop this commit, keeping the
first 3 commits of the bug applied)
b) Inside KTD:
prove -r t/db_dependent/Koha/Plugins/ t/db_dependent/Koha/REST/Plugin/
c) Observe failing files unrelated to this bug's own tests:
Biblio_and_Items_plugin_hooks.t, Holds_hooks.t,
TemplateIncludePathHook.t and REST/Plugin/PluginRoutes.t.
2. Confirm the fix:
a) Re-apply this commit
b) Re-run the same command from 1(b) -- all tests now pass
3. Confirm the original bug this branch set out to fix is still fixed,
both via the manual UI steps from the first commit's test plan
(install Batch Permission Modifier Plugin 1.3.1, upload 1.4.1 over
it via Tools > Plugins, confirm the renamed method takes effect
without restarting Plack) and via:
prove t/db_dependent/Koha/Plugins/Plugins.t
(see the 'InstallPlugins() reloads stale symbol tables tests'
subtest)
4. Confirm QA tooling is clean:
koha-qa.pl -c 4
=> PASS for Koha/Plugins.pm and all touched test files, no critic
or tidiness failures.
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
When a plugin is upgraded in place (by uploading a new version over
the old one), the list of methods Koha knows about for that plugin
can get out of date. For example, if a plugin used to have a "tool"
method and the new version renames it to "admin", the staff interface
can still show the old "Run tool" link, and clicking it produces an
error saying the plugin has no "tool" method.
This happens because the plugin upload runs inside a long-lived
Plack worker that has already loaded the old version of the plugin
in memory. When Koha scans the plugin to record its methods, Perl
has no reason to re-read the file from disk, so the scan sees the
old method list and stores that in the plugin_methods table. The
plugin code on disk is new, but the record of what methods it has
is stale.
This patch forces Koha to throw away the in-memory copy of each
plugin and reload it from disk before scanning, so the recorded
list of methods matches the plugin that is actually installed.
Test Plan:
1) Install the Batch Permission Modifier Plugin version 1.3.1
(this version exposes a "tool" method)
2) Go to Tools > Plugins and confirm the plugin row shows
"Run tool" in its actions menu
3) Upload Batch Permission Modifier Plugin version 1.4.1 over
the top of 1.3.1 (this version exposes "admin" instead of
"tool")
4) Reload the Plugins page
5) Note the plugin still shows "Run tool" in its actions menu
6) Click "Run tool"
7) Note the error: the plugin has no "tool" method!
8) Apply this patch
9) Restart all the things!
10) Uninstall the plugin
11) Repeat steps 1-4
12) Note that "Run tool" is gone and "Run admin tool" appears
in its place
13) Click "Run admin tool" and confirm it loads without error!
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
1. Go to the staff interface.
2. Go to Tools > Additional contents.
3. Select the Record display customizations tab/category.
4. Add a new Record display customization, or edit an existing one.
5. Click Cancel.
6. Confirm you are returned to:
/cgi-bin/koha/tools/additional-contents.pl?category=record_display
7. Confirm you are not returned to the HTML customizations category.
8. Repeat with another Additional content category, such as Pages, and
confirm its Cancel behavior is unchanged.
9. Sign off and have a great day! :D
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Before applying this patch, to reproduce the issue:
1. Set system preference OpacResetPassword to 'not allowed'
2. Set system preference OpacPasswordChange to 'Don't allow'
3. Set preference opacuserlogin to 'Allow'
4. Navigate to OPAC
5. Observe no "Forgot your password?" link on the OPAC main page
6. Set system preference OpacResetPassword to 'allowed'
7. Observe no "Forgot your password?" link on the OPAC main page
8. Set system preference OpacPasswordChange 'Allow'
9. Observe "Forgot your password?" link is present on the OPAC main page.
Instead, it should be already present when OpacResetPassword is allowed.
To test this patch:
1. Apply this patch
2. Set system preference OpacResetPassword to 'not allowed'
3. Set system preference OpacPasswordChange to 'Don't allow'
4. Set preference opacuserlogin to 'Allow'
5. Navigate to OPAC
6. Observe no "Forgot your password?" link on the OPAC main page
7. Set system preference OpacResetPassword to 'allowed'
8. Observe "Forgot your password?" link is present
Signed-off-by: Bo Gustavsson <bosse@gustavsson.one>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This patch fixes the terminology in the FineNoRenewals system preference
description to use the term 'charges' instead of 'fines'.
To test:
1. Apply patch
2. Go to Administration > System preferences
3. Search for FineNoRenewals
4. Make sure the description is gramatically correct and doesn't have
contain typos
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>
The administration sidebar menu has an incorrect link for MARC ordering
accounts. Clicking the link takes you to EDI accounts. This patch fixes
it.
To test, apply the patch and run 'yarn build'
- Go to Administration -> Libraries (for example)
- In the sidebar menu, click the MARC ordering accounts link.
- You should be taken to the MARC ordering accounts page.
Sponsored-by: Athens County Public Libraries
Signed-off-by: Roman Dolny <roman.dolny@jezuici.pl>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
"Title" column of Checkout history export contains too much
informations, making the export file hard to read and understand.
Test plan :
1 - Connect on OPAC
2 - Go to "Your account"
3 - Go to "Checkout history"
4 - Click on "CSV"
5 - Open file
6 - Notice that the "title" column is too long and contains ratings
informations
7 - Go back on OPAC
8 - Click on "Copy"
9 - Copy to a .txt file
10 - Notice the same problem as the CSV export
11 - Apply patch
12 - Repeat previous instructions
13 - Notice that the "title" column contains only the title
Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Laura_Escamilla <laura.escamilla@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The warnings look like:
[2026/05/08 15:02:42] [32918] [WARN] Variable "@messages" is not available at /usr/share/koha/intranet/cgi-bin/acqui/basket.pl line 698.
[2026/05/08 15:02:42] [32918] [WARN] Variable "$op" is not available at /usr/share/koha/intranet/cgi-bin/acqui/basket.pl line 704.
Note in the fix, we are switching to the "our" keyword. When we declare
things with "our", and we run this under plack, those variables and
values persist across multiple requests! Due to this behavior we always
need to reinitialize anything that uses "our" unless we specifically
want that behavior ( like caching ).
Test plan:
1) Send an EDI order, note the warnings in the logs
2) Apply this patch
3) Restart all the things!
4) Send another EDI order, note the warnings are gone!
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
[FAIL] t/db_dependent/Koha/Plugins/C3.t
FAIL file_permissions
File must have the exec flag
FAIL test_no_warnings
'use Test::NoWarnings' must be present in this test file.
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
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>
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>
This prevents an 'Uncaught TypeError: can't access property "DataTable", table is undefined' when a patron has no items checked out yet and is visiting opac-readingrecord.
The code now checks if table is defined before accessing its properties.
Testplan:
a) log in in opac, open dev console
b) go to /cgi-bin/koha/opac-readingrecord.pl
c) without patch applied the error above occurs
d) apply patch and reload opac-readingrecord.pl, there should not be any error now
e) check out an item in staff to that patron and check that the table on opac-readingrecord.pl is diplayed
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Since bug 36085, the protected flag in a patron account was removed from
the patron creation form, regardless of if the user is a superlibrarian.
- Hoist $logged_in_user lookup before the edit_form block
- Move superlibrarian capability checks after the block so they apply
to all operations including patron creation
To test:
1. Sign in as a superlibrarian
2. Go to Patrons > New patron > choose any category
3. Without this patch: the "Protected" yes/no field is missing
from the "Library management" section
4. Apply this patch
5. Repeat step 2
- The "Protected" yes/no field is now visible
6. Create the patron with Protected set to "Yes"
7. Confirm the patron is saved as protected
8. Sign in as a non-superlibrarian with edit_borrowers permission
9. Repeat step 2
- The "Protected" field should still be hidden
10. Edit an existing patron as superlibrarian
- The "Protected" field is visible and functional
11. Edit an existing patron as non-superlibrarian
- The "Protected" field is hidden
12. Sign off
Signed-off-by: Caroline Cyr La Rose <caroline.cyr-la-rose@inlibro.com>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 9ad474c994b7e7b9f90821da35e030be98b8d58d)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 0974071966a2e2ad52931a7f12d7440d6a7deb5c)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
The custom/authorized-value status branch concatenated row.status
directly into a class="..." attribute string. escape_str() only
escapes &, <, > (not quotes), so a status code containing a double
quote could still break out of the attribute.
Build the status <span> via DOM APIs instead, the same way the
reason field was fixed: fixed statuses get a hardcoded class, and
the free-form status code goes into a data-status attribute via
dataset, which the DOM escapes safely regardless of content.
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 7ec92d492576215296bbee42669bcf6ed81c7626)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>