Bugfix Issue 649 CodeTrackerInterface Empty Root Xml False Failure - sebiboga/testlink-upgraded GitHub Wiki
Issue 649 โ codeTrackerInterface truthiness check falsely treats empty-root XML config as parse failure
Issue: #649
Branch: fix/issue-649 ยท Commits: cb7238aa3 (fix), 0aead081a (regression suite)
Status: FIXED & VERIFIED (2026-08-23)
Symptom
A code tracker saved with a valid but childless-root config (<codetracker></codetracker>,
savable since the #432 identity-check fix) produced a spurious ERROR on every interface
instantiation and left the integration disconnected:
setCfg() returned: false โ valid XML reported as failure
connected flag: false
events table:
id=1 log_level=1(ERROR) source=GUI :: codeTrackerInterface::setCfg - Failure loading XML STRING
id=2 log_level=1(ERROR) source=GUI :: codeTrackerInterface::setCfg - Failure loading XML STRING
Note no libxml error text was appended โ because there WAS no parse error.
Root cause chain
lib/codetrackerintegration/codeTrackerInterface.class.php:105โ$this->cfg = simplexml_load_string($xmlCfg);:106โif (!$this->cfg)used TRUTHINESS. PHP casts a SimpleXMLElement wrapping a childless root element to boolean FALSE (measured:(bool)$x === false,$x === false === false). A SUCCESSFUL parse entered the failure branch.:107-113โ$msg = "...Failure loading XML STRING"set with zero libxml errors.:121-124โ!($retval = is_null($msg))โ returnsfalseโtLog(...,'ERROR').- Constructor
:60-69โ else branch sets$this->connected = false; every code-integration lookup viatlCodeTracker::getInterfaceObject()runs disconnected.
Why now: #432 fixed only the save-time validator tlCodeTracker::checkXMLCfg
(lib/functions/tlCodeTracker.class.php:694, $cfg === false). Empty-root configs became
savable, making this runtime-side copy of the same latent 1.9.20 pattern reachable for the
first time. #432 exposed it; it did not introduce it.
Blast radius
- Direct: every concrete subclass constructor โ currently
stashrestInterface(the only subclass ofcodeTrackerInterface). All entry points throughtlCodeTracker::getInterfaceObject():execSetResults.php:753,scriptAdd.php:303,scriptDelete.php:121,archiveData.php:199,print.inc.php:2369, plus BFF paths. - Same-pattern siblings found during investigation, filed separately as #650:
issueTrackerInterface.class.php:117,reqMgrSystemInterface.class.php:81.
Approach โ mirror the proven identity check
Chosen fix (one condition + comment):
// was: if (!$this->cfg)
if ($this->cfg === false)
Identity comparison is the ONLY change that distinguishes "parse failed"
(simplexml_load_string returns literal false) from "parsed object that happens to be
falsey" (childless root). Rejected alternatives: is_null($this->cfg) (wrong โ never null),
wrapping in try/catch only (libxml failures return false rather than throwing), or
suppressing the log at handler level (hides real failures).
Post-fix behavior for <codetracker></codetracker>: parse succeeds โ connect() silently
skips (no credentials configured โ by design) โ no events written.
Files changed
| File | Change |
|---|---|
lib/codetrackerintegration/codeTrackerInterface.class.php |
:106 truthiness โ $this->cfg === false (+ explanatory comment) |
tmp/TLU_Test_Cases.md |
Suite 649 regression entry (5 cases incl. pre-fix repro) |
Verification (regression matrix, CLI against live DB)
| Case | cfg | setCfg() | connected | new events |
|---|---|---|---|---|
| R1 | <codetracker></codetracker> |
true (was false) | false (silent credential skip โ by design) | NO bogus ERROR; 3 WARNINGs from unguarded stashrest property reads โ pre-existing class filed as #651 |
| R2 | full config with children | true | false* | none โ unchanged (*unreachable host fails cleanly) |
| R3 | <codetracker< malformed |
false (correctly) | false | ERROR WITH libxml detail text โ |
Suite 649: 5/5 PASS (tmp/TLU_Test_Cases.md).
Related issues
- #650 โ identical truthiness pattern in issue-tracker and reqmgr sibling interfaces (FIXED).
- #651 โ unguarded cfg property reads (
stashrestInterface.class.php:47/99/100) warn for incomplete configs; pre-existing, surfaced by this fix's verification matrix (open).