Bugfix Issue 1591 Missing Pagination Config Empty LengthMenu - sebiboga/testlink-upgraded GitHub Wiki
Bug fix — Issue #1591: missing $tlCfg->gui->…->pagination config broke the DataTables page-size menu
Three legacy Dashio list screens render a DataTables page-size control ("Show N entries")
from the PHP configuration tree $tlCfg->gui->{section}->pagination->length. config.inc.php
defined that subtree for only five sections, so the remaining screens dereferenced a missing
stdClass child. Every page load therefore:
- wrote three
E_WARNINGrows to theeventstable (Event Viewer noise), and - emitted
"lengthMenu": [ ]into the page, so the page-size<select>was rendered with a single blank option — the control was unusable.
Affected legacy entry points (still reachable by URL/bookmark):
| Screen | cfg_section |
Emitted before the fix |
|---|---|---|
lib/issuetrackers/issueTrackerView.php |
issueTrackerView |
"lengthMenu": [ ], |
lib/platforms/platformsView.php |
platformsView |
lengthMenu: [], |
lib/codetrackers/codeTrackerView.php |
codeTrackerView |
"lengthMenu": [ 20 ], (single option) |
The modern screens the ASIDE menu now links
(/gui/templates/issuetracker/issuetrackerView.html,
/gui/templates/codetracker/codetrackerView.html,
/gui/templates/reqmgrsystems/reqMgrSystemView.html,
/gui/templates/platforms/platformsView.html, wired in lib/functions/common.php:1918-1926)
are not affected: they hardcode pageLength: 25 and use the DataTables default length menu.
lib/reqmgrsystems/reqMgrSystemView.php is not affected either — that template has no
DataTables include at all, so it has no pagination config to read.
- TestLink 2.0.1, PHP built-in server on
http://localhost:8082(docroot = repository root), MariaDB127.0.0.1:3306, db/user/passwordtestlink. - The database is freshly imported on every run and contains no list data, so the fixtures were recreated:
INSERT INTO issuetrackers (name,type,cfg) VALUES ('Bugzilla Demo',1,'{"uribase":"http://localhost:9999/","uriview":"bz.cgi?id=%bugid%"}');
INSERT INTO codetrackers (name,type,cfg) VALUES ('Git Demo',1,'{"uribase":"http://localhost:9999/g","uriview":"%commitid%"}');
INSERT INTO testprojects (id,prefix,api_key) VALUES (1,'TL','aaaa…1111');
INSERT INTO platforms (name,testproject_id,notes,enable_on_design,enable_on_execution,is_open)
VALUES ('Linux',1,'demo',1,1,1);- Login:
admin/admin. Browser checks run in headless Chrome.
Two different configuration mechanisms exist in TestLink and were being conflated:
-
PHP config tree —
$tlCfg->gui->{section}->pagination->{enabled,length}inconfig.inc.php, holding a JS length-menu string such as'[20, 40, 60, -1], [20, 40, 60, "All"]'. -
Smarty
{config_load}data —pagination_lengthingui/templates/conf/input_dimensions.conf, injected as#pagination_length#, holding a bare scalar (20).
They are not interchangeable: the .conf scalar ends up as lengthMenu: [20] (a single page
size), the config-tree string ends up as a full two-array DataTables menu.
gui/templates/dashio/include/DataTables.inc.tpl:102 interpolates whatever it receives verbatim:
"lengthMenu": [ {$DataTablesLengthMenu} ],
The call sites split as follows:
| Template | Reads | Config present? |
|---|---|---|
projectView.tpl:48, planView.tpl:40, buildView.tpl:41, keywordsView.tpl:45, usersAssign.tpl:112
|
$tlCfg->gui->…->pagination->length |
yes (config.inc.php:658-684) |
platformsView.tpl:51, issueTrackerView.tpl:27
|
$tlCfg->gui->…->pagination->length |
no → the bug |
codeTrackerView.tpl:26 |
#pagination_length# |
.conf only → single-option menu |
Chain for issueTrackerView.tpl:27 ($cfg_section set at line 9 from the template name):
$tlCfg->gui->issueTrackerView -> null (E_WARNING 1: Undefined property: stdClass::$issueTrackerView)
->pagination -> null (E_WARNING 2: Attempt to read property "pagination" on null)
->length -> null (E_WARNING 3: Attempt to read property "length" on null)
$ll is empty, so DataTables.inc.tpl:102 renders "lengthMenu": [ ].
The regression source is the dashio porting of these two templates: they were copied from
projectView.tpl (which reads the config tree) without carrying the matching config.inc.php
block along. It is pre-existing and independent of #1584.
config.inc.php — the three missing blocks were added at the end of the pagination section,
using exactly the shape and the same length string as the five existing ones:
$tlCfg->gui->issueTrackerView = new stdClass();
$tlCfg->gui->issueTrackerView->pagination = new stdClass();
$tlCfg->gui->issueTrackerView->pagination->enabled = true;
$tlCfg->gui->issueTrackerView->pagination->length = '[20, 40, 60, -1], [20, 40, 60, "All"]';
$tlCfg->gui->codeTrackerView = new stdClass();
$tlCfg->gui->codeTrackerView->pagination = new stdClass();
$tlCfg->gui->codeTrackerView->pagination->enabled = true;
$tlCfg->gui->codeTrackerView->pagination->length = '[20, 40, 60, -1], [20, 40, 60, "All"]';
$tlCfg->gui->platformsView = new stdClass();
$tlCfg->gui->platformsView->pagination = new stdClass();
$tlCfg->gui->platformsView->pagination->enabled = true;
$tlCfg->gui->platformsView->pagination->length = '[20, 40, 60, -1], [20, 40, 60, "All"]';gui/templates/dashio/codetrackers/codeTrackerView.tpl:26 — one line, so the Code Tracker list
behaves like its sibling list screens instead of offering a single page size:
- {$ll = #pagination_length#}
+ {$ll = $tlCfg->gui->{$cfg_section}->pagination->length}reqMgrSystemView.tpl is deliberately unchanged — it includes no DataTables, so adding a
config block for it would be dead configuration.
- The config tree is the mechanism TestLink already uses for the five other list sections, is discoverable in one place, and fixes the root cause (missing configuration) rather than masking the symptom.
- The alternative — a Smarty-side guard such as
{if isset($tlCfg->gui->{$cfg_section}->pagination->length)}…{else}$ll=#pagination_length#{/if}— still has to evaluate the dynamic property expression, keeps the error-prone null walk in the template layer, and hides the real defect behind a silent fallback. - Aligning
codeTrackerViewwith the config tree is what makes the reported expectation ("the page-length control offers the configured options") true on all three listed screens.
docs/Bugfix-Issue-1580-Codetracker-Warnings.md:70-72 rejected exactly this shape as an
alternative ("Add a fabricated $tlCfg->gui->codeTrackerView object: this duplicates
configuration state and would hide the mismatch between the loaded Smarty configuration and the
template access path"). #1580 was right that the two mechanisms must not be mixed silently, and
its change ({$ll = #pagination_length#}) did silence the warnings.
This issue changes that decision, for two measured reasons:
-
pagination_lengthininput_dimensions.confis a bare scalar (20), socodeTrackerViewended up with"lengthMenu": [ 20 ]— a page-size control with exactly one unusable choice, unlike its five sibling list screens..confcannot express a length menu; the config tree can. - Leaving
codeTrackerViewon the.confscalar would have kept the very mismatch #1580 warned about: two sources of truth for the same setting, of which one (pagination_length=20) is now unread by these templates and the other silently defaults to20for the sections that have no conf section at all (rolesView.tpl:33,planMilestonesView.tpl:35— they fall back to the unnamed default section,input_dimensions.conf:51).
So the config block is added and the template is pointed at it, which keeps the warnings fixed
(verified) and removes the duplicate source of truth for this screen. The pagination_length
entries in input_dimensions.conf are intentionally left in place: #pagination_length# still has
five live readers, and removing keys would break custom templates in the wild.
The ->pagination->enabled = true lines are kept although these three templates do not test
enabled, because all five pre-existing blocks define it and dropping it would make the section
inconsistent for anyone gating on it later.
| Screen |
lengthMenu before |
after |
<select> options after |
|---|---|---|---|
issueTrackerView |
[ ] |
[ [20, 40, 60, -1], [20, 40, 60, "All"] ] |
20 / 40 / 60 / All |
platformsView |
[] |
[[20, 40, 60, -1], [20, 40, 60, "All"]] |
20 / 40 / 60 / All |
codeTrackerView |
[ 20 ] |
[ [20, 40, 60, -1], [20, 40, 60, "All"] ] |
20 / 40 / 60 / All |
-
eventsafter reloading the three screens: noUndefined property/Attempt to read propertyrows remain (previously 3 per screen). - Browser console on
issueTrackerView: no errors, no warnings. Selecting40really changes the page length (DataTable().page.len()= 40). - Read-only path (
codetracker_view-only user, i.e. withoutcodetracker_management): the screen still returns 200 and now offers the same four options; measured in the browser as{"opts":["20","40","60","All"],"headers":["Code Tracker","Type","Environment","delete"],"pageLen":20}, console clean,eventsgained only the AUDIT login row. - Regression of the pre-existing consumers:
planViewstill renders[20, 40, 60, -1], [20, 40, 60, "All"],keywordsViewstill renders[40, 60, 80, -1], [40, 60, 80, "All"]; a direct config dump shows the five original blocks unchanged and all eight sections resolving. - Every
pagination->read in the repository (15 call sites indashioandtl-classic) now maps to a section defined inconfig.inc.php; no call site is left dereferencing a missing section. - Empty list (
DELETE FROM codetrackers/DELETE FROM platforms): both screens still return HTTP 200 and log nothing. - Full suite:
tmp/TLU_Test_Cases.md→ Regression — Issue #1591, 12/12 PASS plus the read-only pass above.
issueTrackerView with the length <select> populated (20 / 40 / 60 / All) instead of the
previous single blank option:
![]()
| File | Purpose |
|---|---|
config.inc.php |
+15 lines: issueTrackerView, codeTrackerView, platformsView pagination blocks |
gui/templates/dashio/codetrackers/codeTrackerView.tpl |
1 line: read the length menu from the config tree instead of the bare .conf scalar |
docs/screenshots/issue-1591-issueTrackerView-lengthMenu-fixed.png |
browser evidence |
docs/Bugfix-Issue-1591-Missing-Pagination-Config-Empty-LengthMenu.md |
this page |
CHANGELOG |
2.0.1 [KEY BUGFIX] entry for #1591 |
tmp/TLU_Test_Cases.md |
regression suite (local file, gitignored per AGENTS.md rule 9) |
- #1582 / #1584 / #1585 — sibling read-only delete-cell contract defects in the same list templates.
- #1590 —
testproject_alt_deletelabel key missing inissueTrackerView.tpl:81(same template, separate E_WARNING, still open). - #1592 / #1593 — warnings found while testing this fix, both in the
reqMgrSystemViewlegacy path (tproject_idarray key, missingcontoursoapInterface.class.php).