PHP 8.0 – 8.5 source compatibility fixes (XmlReader, ReportHtml/Html2pdf, ReportTCPDF, ReporticoSession, default;) - #60
Open
pixilla wants to merge 13 commits into
Conversation
PHP 8.4 deprecated `xml_set_object()` and the use of string method names
as callbacks for `xml_set_*_handler()`. PHP 8.5 additionally deprecated
`xml_parser_free()` (which has been a no-op since PHP 8.0; the parser is
freed automatically when its last reference goes out of scope).
Loading any project xml file currently emits:
Deprecated: Function xml_set_object() is deprecated since 8.4 ...
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 ...
Deprecated: xml_set_character_data_handler(): Passing non-callable strings is deprecated since 8.4 ...
Deprecated: Function xml_parser_free() is deprecated since 8.5 ...
Replace the string callbacks with `[object, methodName]` array callables
(also valid in PHP 7.4+), and remove the now-deprecated `xml_parser_free()`
call. Behavior is unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com>
…up (PHP 8.1)
`$this->currentGroup` is initialised to `false` and is only promoted to an
array by `openGroup()`. When `closeGroup()` is called without a matching
`openGroup()` (a common occurrence during certain report layouts/totals
paths), PHP 8.1+ emits:
Deprecated: Automatic conversion of false to array is deprecated in
src/ReportHtml.php on line 348
Deprecated: Automatic conversion of false to array is deprecated in
src/ReportHtml2pdf.php on line 347
…and the subsequent writes silently mutate `currentGroup` into a one-key
array `[ "endrow" => ... ]`, hiding logic bugs.
Both methods now early-return when `currentGroup` is not yet an array,
preserving the previous effective no-op behaviour without the deprecation.
Co-authored-by: Cursor <cursoragent@cursor.com>
…ignature (PHP 8.0 / 8.2)
PDF report generation currently produces multiple fatal-level deprecations
on PHP 8.2+:
Deprecated: Creation of dynamic property
Reportico\Engine\ReportTCPDF::$column_spacing is deprecated
Deprecated: Creation of dynamic property
Reportico\Engine\ReportTCPDF::$abs_row_right_margin is deprecated
Deprecated: Creation of dynamic property
Reportico\Engine\ReportTCPDF::$abs_col_right_margin is deprecated
Deprecated: Creation of dynamic property
Reportico\Engine\ReportTCPDF::$abs_row_width is deprecated
Deprecated: Creation of dynamic property
Reportico\Engine\ReportTCPDF::$abs_columns_width is deprecated
and one PHP 8.0+ implicit-required-parameter deprecation:
Deprecated: Reportico\Engine\ReportTCPDF::newReportPageLineByStyle():
Optional parameter $txt declared before required parameter $styles
is implicitly treated as a required parameter
This change:
1. Explicitly declares the five properties on the class so PHP 8.2 no-dynamic-properties rule is satisfied. $column_spacing is initialised to 0 to match what the constructor was lazily setting.
2. Removes the unused default = "" from $txt in newReportPageLineByStyle(); the next parameter is a required by-ref parameter, so $txt was already implicitly required and every call site already passes it.
No behaviour change.
Co-authored-by: Cursor <cursoragent@cursor.com>
… (PHP 8.1)
When `session_namespace_key` has not been set yet (e.g. very early in a
fresh-session bootstrap, before initialise(), or when callers reach the
isset helpers from an out-of-order code path), `ReporticoApp::get("session_namespace_key")`
returns null. Indexing `$_SESSION` with that null then triggers, on PHP 8.1+:
Deprecated: Using null as an array offset is deprecated, use an empty
string instead in src/ReporticoSession.php on line 198
The same pattern exists in three helpers:
- existsReporticoSession()
- issetReporticoSessionParam()
- unsetReporticoSessionParam()
In all three the semantic answer when the key is null/empty is the same:
no Reportico namespace exists yet, so existsReporticoSession() and
issetReporticoSessionParam() should return false, and
unsetReporticoSessionParam() should be a no-op.
Add an explicit guard at the top of each helper that returns the
appropriate "namespace does not exist" answer when the key is null or
empty, before any $_SESSION array access. This eliminates the deprecation
without changing observable behaviour.
No callers of these helpers needed updating; they already treat a
"namespace does not exist" return value as the absence of state.
Co-authored-by: Cursor <cursoragent@cursor.com>
PHP has historically accepted both `:` and `;` as the terminator for switch
case/default labels. PHP 8.5 deprecates the `;` form:
Deprecated: Case statements followed by a semicolon (;) are deprecated,
use a colon (:) instead
There are 5 occurrences of `default;` in the codebase. All five are
in switch statements where the `default` arm shares a fall-through body
with a `case "LINE":` arm (chart-engine type dispatch), or guards an
"unhandled tag" fall-through (XmlReader).
Replace `default;` with `default:` at each site. No behaviour change.
Affected files:
- src/XmlReader.php
- src/ChartPchart3.php
- src/ChartPchart.php
- src/ChartJpgraph.php
- dyngraph.php
Co-authored-by: Cursor <cursoragent@cursor.com>
…r (PHP 8.2)
When a report with a DATE criteria is opened, PHP 8.2+ emits multiple
"Creation of dynamic property" deprecations:
Deprecated: Creation of dynamic property
Reportico\Widgets\Criteria::$range_start is deprecated
in src/widgets/Widget.php on line 242
Deprecated: Creation of dynamic property
Reportico\Widgets\DatePicker::$range_name is deprecated
in src/widgets/DatePicker.php on line 228
Deprecated: Creation of dynamic property
Reportico\Widgets\DatePicker::$range_end_raw is deprecated
in src/widgets/DatePicker.php on line 229
Deprecated: Creation of dynamic property
Reportico\Widgets\DatePicker::$range_start_raw is deprecated
in src/widgets/DatePicker.php on line 229
The locations:
- Widget::handleUrlParameters() passes $this->range_start by reference into
ReporticoLocale::convertDateRangeDefaultsToDates() when the engine criteria
is of type DATE. $this is the surrounding widget (typically a Criteria).
- DatePicker::deriveValue() initialises $this->range_name,
$this->range_start_raw and $this->range_end_raw to "" before populating
them from the request.
DateRangePicker and TimeRangePicker already declare the equivalent fields
explicitly; this commit aligns DatePicker (range_name, range_start_raw,
range_end_raw) and adds the single field that Widget::handleUrlParameters()
needs on Criteria (range_start).
No behaviour change.
Co-authored-by: Cursor <cursoragent@cursor.com>
…ll namespace (PHP 8.1) Follow-up to a4c3480 ("guard $_SESSION[null] when namespace key unset"). That commit guarded the three read-only helpers (existsReporticoSession, issetReporticoSessionParam, unsetReporticoSessionParam), which is enough for the originally reported deprecation. Continued testing surfaced that three more sites in the same file still index $_SESSION by a key sourced from ReporticoApp::get("session_namespace_key"), and so can still emit: Deprecated: Using null as an array offset is deprecated, use an empty string instead in src/ReporticoSession.php The remaining sites are: - setReporticoSessionParam(): writes $_SESSION[$namespace][$param]; $namespace falls back to ReporticoApp::get("session_namespace_key") when not passed. - initializeReporticoNamespace(): reads $_SESSION[$namespace] and unsets it; $namespace is reassigned from ReporticoApp::get(...). (getReporticoSessionParam() is already safe because it short-circuits through the now-guarded issetReporticoSessionParam().) Add the same null/"" early-return guard at both sites so the deprecation cannot recur from any other call path. Behaviour is unchanged for callers that already have a valid namespace key. Co-authored-by: Cursor <cursoragent@cursor.com>
Twig 3.5.x triggers deprecations on PHP 8.4+ (implicitly nullable parameters in FilesystemLoader, Environment::getTemplateClass, etc.). Reportico's error handler treats those deprecations as fatal UI errors, which caused a white screen when opening reports that render Twig templates (e.g. Open Jobs criteria PREPARE). Raise the floor to Twig 3.19+ so installs on PHP 8.5 resolve to a current 3.x release with explicit nullable types. Run `composer update twig/twig` after merge to refresh the lockfile. Co-authored-by: Cursor <cursoragent@cursor.com>
… debug echo
PostgreSQL treats double-quoted tokens as identifiers. QueryColumn::getValueDelimiter()
returned '"' for CHAR criteria, so expanded criteria like {wanteddate} became
`... < "2026-05-13"`, which PostgreSQL reads as "column 2026-05-13" and throws
SQLSTATE[42703] — an uncaught PDOException and a white screen on reports such as
Open Jobs (lookup SQL uses the wanteddate criterion).
Use single-quote delimiters when the ADOdb/PDO driver is PostgreSQL.
Also remove a stray `echo $cls` in DatePicker::getCriteriaClause() left from debugging,
which corrupted HTML/ajax responses.
Co-authored-by: Cursor <cursoragent@cursor.com>
Vendor and extension deprecations on PHP 8.x were classified as "Fatal Error" and appended to system_errors, which forces error-rendering paths and can yield blank or broken pages even when the underlying request would succeed. Return early for E_DEPRECATED and E_USER_DEPRECATED so PHP's default handling applies and Reportico does not treat them as blocking report errors. Co-authored-by: Cursor <cursoragent@cursor.com>
…reports
The previous hard cap of 100M is easy to hit on big result sets: assignment
expressions are eval()'d per row (Reportico::assign), and PDF/HTML rendering
buffers additional data. That produced:
Allowed memory size of 104857600 bytes exhausted ... eval()'d code
Default is now 512M. Optional override: set environment variable
REPORTICO_MEMORY_LIMIT (e.g. `768M` or `1G`) before the web/PHP process if a
specific deployment needs more.
Co-authored-by: Cursor <cursoragent@cursor.com>
Large PostgreSQL reports (e.g. Contact Phone Email Sales History) can exceed the previous 90s PHP limit after the SQL completes. Default is now 300s; override with REPORTICO_MAX_EXECUTION_TIME in the environment if needed. Co-authored-by: Cursor <cursoragent@cursor.com>
Harden XmlReader and findFileToInclude when report XML is missing, skip non-.xml files in project menus, pass project/xmlin on criteria execute, and declare TimeRangePicker::$range_name for PHP 8.2. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings Reportico to clean compatibility with PHP 8.0 → 8.5. Each commit is scoped to a single concern with a self-contained message.
Tested on PHP 8.5.1 (MacPorts) against PostgreSQL: admin login, project load, criteria/date-pickers, HTML output, and TCPDF PDF generation.
Base
Targets tag 8.1.0 (
1ee3a05).Highlights
closeGroup()whencurrentGroupis falsenewReportPageLineByStylesignature$_SESSIONaccess when namespace key is unsetCriteria/DatePicker/TimeRangePickerproperties; CriteriaForm passesproject+xmlinon AJAX execute.xmlfiles (e.g..xml.bak.*) in project/admin menusfindFileToInclude()default;→default:(PHP 8.5)E_DEPRECATEDin error handler (vendor/extension noise)Test plan
error_reporting(E_ALL)— no Reportico-core deprecations during PREPARE/EXECUTE.xml.bak.*files present in project folderRelated
Pairs with #59 (switch to upstream
adodb/adodb-php) for a full PHP 8.5 install.ADOdb
ADODB_pdo::$_nestedSQLundeclared-property notice may still appear until ADOdb upstream ships a fix.