diff --git a/app/Helpers/export_helper.php b/app/Helpers/export_helper.php index 96e969e08..d2645d09c 100644 --- a/app/Helpers/export_helper.php +++ b/app/Helpers/export_helper.php @@ -1,5 +1,7 @@ SetFont('DejaVuSans', 'B', EXPORT_PDF_FONT_SIZE); - - foreach ($this->exportHeaderValues as $index => $value) { - $width = $this->exportColumnWidths[$index]; - $text = exportPdfTruncateCellText($this, $value, $width); - $this->Cell($width, EXPORT_PDF_ROW_HEIGHT, $text, 1, 0, 'C'); - } - $this->Ln(); - - $this->SetFont('DejaVuSans', '', EXPORT_PDF_FONT_SIZE); - } -} - // Columns rendered centered rather than left-aligned. const EXPORT_PDF_CENTERED_COLUMNS = ['category', 'cost_price', 'unit_price', 'quantity', 'tax_percents']; diff --git a/app/Language/en/Common.php b/app/Language/en/Common.php index 7c56f705e..188222d00 100644 --- a/app/Language/en/Common.php +++ b/app/Language/en/Common.php @@ -28,6 +28,7 @@ return [ 'export_all' => 'Export All', 'export_page' => 'Export Page', 'export_scope_toggle' => 'Export all rows or current page only', + 'export_xlsx_disabled_tooltip' => 'ext-zip is required in PHP for Excel export', 'fields_required_message' => 'Fields in red are required', 'fields_required_message_unique' => '', 'first_name' => 'First Name', diff --git a/app/Libraries/ExportPdfWriter.php b/app/Libraries/ExportPdfWriter.php new file mode 100644 index 000000000..2ad382e00 --- /dev/null +++ b/app/Libraries/ExportPdfWriter.php @@ -0,0 +1,29 @@ +SetFont('DejaVuSans', 'B', EXPORT_PDF_FONT_SIZE); + + foreach ($this->exportHeaderValues as $index => $value) { + $width = $this->exportColumnWidths[$index]; + $text = exportPdfTruncateCellText($this, $value, $width); + $this->Cell($width, EXPORT_PDF_ROW_HEIGHT, $text, 1, 0, 'C'); + } + $this->Ln(); + + $this->SetFont('DejaVuSans', '', EXPORT_PDF_FONT_SIZE); + } +} diff --git a/app/Views/configs/system_info.php b/app/Views/configs/system_info.php index 22c4447cc..fb12e2285 100644 --- a/app/Views/configs/system_info.php +++ b/app/Views/configs/system_info.php @@ -28,7 +28,8 @@ use Config\OSPOS; echo "» Multibyte String: ", extension_loaded('mbstring') ? '✓ Enabled' : '✗ Disabled', '
'; echo "» cURL: ", extension_loaded('curl') ? '✓ Enabled' : '✗ Disabled', '
'; echo "» JSON: ", extension_loaded('json') ? '✓ Enabled' : '✗ Disabled', '
'; - echo "» XML: ", extension_loaded('xml') ? '✓ Enabled' : '✗ Disabled', '

'; + echo "» XML: ", extension_loaded('xml') ? '✓ Enabled' : '✗ Disabled', '
'; + echo "» Zip: ", extension_loaded('zip') ? '✓ Enabled' : '✗ Disabled', '

'; ?> diff --git a/app/Views/partial/lang_lines.php b/app/Views/partial/lang_lines.php index c82b11aba..9b657aa23 100644 --- a/app/Views/partial/lang_lines.php +++ b/app/Views/partial/lang_lines.php @@ -6,7 +6,8 @@ 'common_close': "", 'common_export_all': "", 'common_export_page': "", - 'common_export_scope_toggle': "" + 'common_export_scope_toggle': "", + 'common_export_xlsx_disabled_tooltip': "" }; $.extend(lang, { @@ -16,4 +17,6 @@ }); })(window.lang = window.lang || {}, jQuery); + + window.ospos_ext_zip_enabled = ; diff --git a/docs/BUILD.md b/docs/BUILD.md index 95c71c46b..c5e693099 100644 --- a/docs/BUILD.md +++ b/docs/BUILD.md @@ -32,6 +32,8 @@ That's all there is to it. Note: If you receive messages similar to 'codeigniter4/framework v4.3.1 requires ext-intl', this is an indicator that you do not have intl enabled in php.ini +Note: If you receive messages similar to 'openspout/openspout requires ext-zip', enable the `zip` extension in php.ini. It is only needed for Excel/XLSX export; the rest of the application builds and runs fine without it, but Excel export will be disabled at runtime. + After the build tasks are complete, if you have the database set up and a preconfigured copy of .env, just drop the .env file into the root of the working folder. You should be ready to go. If you do not have an existing (and upgraded) database, then you will need to continue from this point forward with the standard installation instructions, but at this point you have a runnable version of OSPOS. diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 8b41f5ed1..72b2fd58e 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -1,6 +1,6 @@ ## Server Requirements -- PHP version `8.2.35` to `8.4.27` are supported (minimum patch levels required for CVE-2026-109618 / CVE-2026-109619 security fixes). PHP version `≤ 8.1` is NOT supported. Please note that PHP needs to have the extensions `php-json`, `php-gd`, `php-bcmath`, `php-intl`, `php-openssl`, `php-mbstring`, `php-curl` and `php-xml` installed and enabled. An unstable master build can be downloaded in the releases section. +- PHP version `8.2.35` to `8.4.27` are supported (minimum patch levels required for CVE-2026-109618 / CVE-2026-109619 security fixes). PHP version `≤ 8.1` is NOT supported. Please note that PHP needs to have the extensions `php-json`, `php-gd`, `php-bcmath`, `php-intl`, `php-openssl`, `php-mbstring`, `php-curl`, `php-xml` and `php-zip` installed and enabled. `php-zip` is required for Excel/XLSX export; without it the application still runs normally, but the Excel export option is disabled. An unstable master build can be downloaded in the releases section. - MySQL `5.7` is supported, also MariaDB replacement `10.x` is supported and might offer better performance. - Apache `2.4` is supported. Nginx should work fine too, see [wiki page here](https://github.com/opensourcepos/opensourcepos/wiki/Local-Deployment-using-LEMP). - Raspberry PI based installations proved to work, see [wiki page here](). diff --git a/public/js/manage_tables.js b/public/js/manage_tables.js index 2edb50568..472275ae4 100644 --- a/public/js/manage_tables.js +++ b/public/js/manage_tables.js @@ -273,9 +273,29 @@ toggle_column_visibility(); init_export_all_toggle(); init_export_all_intercept(); + init_xlsx_export_gate(); dialog_support.init("button.modal-dlg"); }; + const init_xlsx_export_gate = function () { + if (window.ospos_ext_zip_enabled) { + return; + } + + const $xlsxItem = $('.export [data-type="xlsx"], .export[data-type="xlsx"]'); + + $xlsxItem + .addClass('disabled') + .attr('aria-disabled', 'true') + .attr('title', lang.line('common_export_xlsx_disabled_tooltip')) + .off('click') + .on('click', function(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + }) + .tooltip({ container: 'body' }); + }; + let export_all_enabled = false; const init_export_all_intercept = function () { diff --git a/public/js/report_tables.js b/public/js/report_tables.js index 673d4690e..d3b4943ac 100644 --- a/public/js/report_tables.js +++ b/public/js/report_tables.js @@ -62,9 +62,29 @@ const report_export_toggle = (function () { }, true); }; + const init_xlsx_export_gate = function () { + if (window.ospos_ext_zip_enabled) { + return; + } + + const $xlsxItem = $('.export [data-type="xlsx"], .export[data-type="xlsx"]'); + + $xlsxItem + .addClass('disabled') + .attr('aria-disabled', 'true') + .attr('title', lang.line('common_export_xlsx_disabled_tooltip')) + .off('click') + .on('click', function(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + }) + .tooltip({ container: 'body' }); + }; + const init = function () { init_export_all_toggle(); init_export_all_intercept(); + init_xlsx_export_gate(); }; return { init }; diff --git a/tests/Helpers/export_helperTest.php b/tests/Helpers/export_helperTest.php index 9ab20f9a9..dd8a2350a 100644 --- a/tests/Helpers/export_helperTest.php +++ b/tests/Helpers/export_helperTest.php @@ -1,5 +1,7 @@