From 615d0afd10f777ee0f3c10422145d6c6c84cf483 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Wed, 3 Dec 2025 09:14:37 +0100 Subject: [PATCH 1/6] Declare parameters that are null by default as nullable Implicitly nullable parameters are deprecated since PHP-8.4 --- application/clicommands/ProcessCommand.php | 2 +- application/controllers/ProcessController.php | 4 ++-- application/forms/AddNodeForm.php | 2 +- application/forms/DeleteNodeForm.php | 2 +- application/forms/EditNodeForm.php | 2 +- application/forms/MoveNodeForm.php | 2 +- library/Businessprocess/Metadata.php | 4 ++-- library/Businessprocess/Modification/ProcessChanges.php | 6 +++--- library/Businessprocess/Monitoring/DataView/HostStatus.php | 2 +- .../Businessprocess/Monitoring/DataView/ServiceStatus.php | 2 +- library/Businessprocess/Node.php | 4 ++-- library/Businessprocess/Renderer/Renderer.php | 2 +- library/Businessprocess/Renderer/TreeRenderer.php | 6 +++--- library/Businessprocess/Web/Form/FormLoader.php | 2 +- library/Businessprocess/Web/Form/QuickBaseForm.php | 2 +- library/Businessprocess/Web/Form/QuickForm.php | 2 +- 16 files changed, 23 insertions(+), 23 deletions(-) diff --git a/application/clicommands/ProcessCommand.php b/application/clicommands/ProcessCommand.php index c343c38..4bf09ed 100644 --- a/application/clicommands/ProcessCommand.php +++ b/application/clicommands/ProcessCommand.php @@ -185,7 +185,7 @@ class ProcessCommand extends Command } } - protected function renderProblemTree($tree, $useColors = false, $depth = 0, BpNode $parent = null) + protected function renderProblemTree($tree, $useColors = false, $depth = 0, ?BpNode $parent = null) { $output = ''; diff --git a/application/controllers/ProcessController.php b/application/controllers/ProcessController.php index 329b258..c12f024 100644 --- a/application/controllers/ProcessController.php +++ b/application/controllers/ProcessController.php @@ -264,7 +264,7 @@ class ProcessController extends Controller $bp->applySimulation($simulation); } - protected function loadActionForm(BpConfig $bp, Node $node = null) + protected function loadActionForm(BpConfig $bp, ?Node $node = null) { $action = $this->params->get('action'); $form = null; @@ -720,7 +720,7 @@ class ProcessController extends Controller return $tabs; } - protected function handleFormatRequest(BpConfig $bp, BpNode $node = null) + protected function handleFormatRequest(BpConfig $bp, ?BpNode $node = null) { $desiredContentType = $this->getRequest()->getHeader('Accept'); if ($desiredContentType === 'application/json') { diff --git a/application/forms/AddNodeForm.php b/application/forms/AddNodeForm.php index 0e1aa0f..394a8d4 100644 --- a/application/forms/AddNodeForm.php +++ b/application/forms/AddNodeForm.php @@ -73,7 +73,7 @@ class AddNodeForm extends CompatForm * * @return $this */ - public function setParentNode(BpNode $node = null): self + public function setParentNode(?BpNode $node = null): self { $this->parent = $node; diff --git a/application/forms/DeleteNodeForm.php b/application/forms/DeleteNodeForm.php index 7021506..2cb5e0e 100644 --- a/application/forms/DeleteNodeForm.php +++ b/application/forms/DeleteNodeForm.php @@ -84,7 +84,7 @@ class DeleteNodeForm extends BpConfigBaseForm * @param BpNode|null $node * @return $this */ - public function setParentNode(BpNode $node = null) + public function setParentNode(?BpNode $node = null) { $this->parentNode = $node; return $this; diff --git a/application/forms/EditNodeForm.php b/application/forms/EditNodeForm.php index bd1592b..1ff938a 100644 --- a/application/forms/EditNodeForm.php +++ b/application/forms/EditNodeForm.php @@ -76,7 +76,7 @@ class EditNodeForm extends CompatForm * * @return $this */ - public function setParentNode(BpNode $node = null): self + public function setParentNode(?BpNode $node = null): self { $this->parent = $node; diff --git a/application/forms/MoveNodeForm.php b/application/forms/MoveNodeForm.php index 0467e51..a56f15e 100644 --- a/application/forms/MoveNodeForm.php +++ b/application/forms/MoveNodeForm.php @@ -110,7 +110,7 @@ class MoveNodeForm extends BpConfigBaseForm * @param BpNode|null $node * @return $this */ - public function setParentNode(BpNode $node = null) + public function setParentNode(?BpNode $node = null) { $this->parentNode = $node; return $this; diff --git a/library/Businessprocess/Metadata.php b/library/Businessprocess/Metadata.php index b640fb8..c3492c1 100644 --- a/library/Businessprocess/Metadata.php +++ b/library/Businessprocess/Metadata.php @@ -112,7 +112,7 @@ class Metadata return Auth::getInstance(); } - public function canModify(Auth $auth = null) + public function canModify(?Auth $auth = null) { if ($auth === null) { if (Icinga::app()->isCli()) { @@ -128,7 +128,7 @@ class Metadata ); } - public function canRead(Auth $auth = null) + public function canRead(?Auth $auth = null) { if ($auth === null) { if (Icinga::app()->isCli()) { diff --git a/library/Businessprocess/Modification/ProcessChanges.php b/library/Businessprocess/Modification/ProcessChanges.php index 9257558..bec06b7 100644 --- a/library/Businessprocess/Modification/ProcessChanges.php +++ b/library/Businessprocess/Modification/ProcessChanges.php @@ -69,12 +69,12 @@ class ProcessChanges } /** - * @param Node $node + * @param ?Node $node * @param $properties * * @return $this */ - public function addChildrenToNode($children, Node $node = null) + public function addChildrenToNode($children, ?Node $node = null) { $action = new NodeAddChildrenAction($node); $action->setChildren($children); @@ -88,7 +88,7 @@ class ProcessChanges * * @return $this */ - public function createNode($nodeName, $properties, Node $parent = null) + public function createNode($nodeName, $properties, ?Node $parent = null) { $action = new NodeCreateAction($nodeName); $action->setProperties($properties); diff --git a/library/Businessprocess/Monitoring/DataView/HostStatus.php b/library/Businessprocess/Monitoring/DataView/HostStatus.php index edc1814..3c22aa0 100644 --- a/library/Businessprocess/Monitoring/DataView/HostStatus.php +++ b/library/Businessprocess/Monitoring/DataView/HostStatus.php @@ -7,7 +7,7 @@ use Icinga\Module\Businessprocess\Monitoring\Backend\Ido\Query\HostStatusQuery; class HostStatus extends \Icinga\Module\Monitoring\DataView\Hoststatus { - public function __construct(ConnectionInterface $connection, array $columns = null) + public function __construct(ConnectionInterface $connection, ?array $columns = null) { parent::__construct($connection, $columns); diff --git a/library/Businessprocess/Monitoring/DataView/ServiceStatus.php b/library/Businessprocess/Monitoring/DataView/ServiceStatus.php index f3a9c3c..33a2221 100644 --- a/library/Businessprocess/Monitoring/DataView/ServiceStatus.php +++ b/library/Businessprocess/Monitoring/DataView/ServiceStatus.php @@ -7,7 +7,7 @@ use Icinga\Module\Businessprocess\Monitoring\Backend\Ido\Query\ServiceStatusQuer class ServiceStatus extends \Icinga\Module\Monitoring\DataView\Servicestatus { - public function __construct(ConnectionInterface $connection, array $columns = null) + public function __construct(ConnectionInterface $connection, ?array $columns = null) { parent::__construct($connection, $columns); diff --git a/library/Businessprocess/Node.php b/library/Businessprocess/Node.php index 1b899a7..da2d706 100644 --- a/library/Businessprocess/Node.php +++ b/library/Businessprocess/Node.php @@ -536,12 +536,12 @@ abstract class Node /** * Export the node to array * - * @param array $parent The node's parent. Used to construct the path to the node + * @param ?array $parent The node's parent. Used to construct the path to the node * @param bool $flat If false, children will be added to the array key children, else the array will be flat * * @return array */ - public function toArray(array $parent = null, $flat = false) + public function toArray(?array $parent = null, $flat = false) { $data = [ 'name' => $this->getAlias(), diff --git a/library/Businessprocess/Renderer/Renderer.php b/library/Businessprocess/Renderer/Renderer.php index d7551ab..13c300c 100644 --- a/library/Businessprocess/Renderer/Renderer.php +++ b/library/Businessprocess/Renderer/Renderer.php @@ -47,7 +47,7 @@ abstract class Renderer extends HtmlDocument * @param BpConfig $config * @param BpNode|null $parent */ - public function __construct(BpConfig $config, BpNode $parent = null) + public function __construct(BpConfig $config, ?BpNode $parent = null) { $this->config = $config; $this->parent = $parent; diff --git a/library/Businessprocess/Renderer/TreeRenderer.php b/library/Businessprocess/Renderer/TreeRenderer.php index ed25e00..1b4aae7 100644 --- a/library/Businessprocess/Renderer/TreeRenderer.php +++ b/library/Businessprocess/Renderer/TreeRenderer.php @@ -112,11 +112,11 @@ class TreeRenderer extends Renderer /** * @param Node $node - * @param array $path - * @param BpNode $parent + * @param ?array $path + * @param ?BpNode $parent * @return BaseHtmlElement[] */ - public function getNodeIcons(Node $node, array $path = null, BpNode $parent = null) + public function getNodeIcons(Node $node, ?array $path = null, ?BpNode $parent = null) { $icons = []; if (empty($path) && $node instanceof BpNode) { diff --git a/library/Businessprocess/Web/Form/FormLoader.php b/library/Businessprocess/Web/Form/FormLoader.php index 0cc5389..86e90cf 100644 --- a/library/Businessprocess/Web/Form/FormLoader.php +++ b/library/Businessprocess/Web/Form/FormLoader.php @@ -8,7 +8,7 @@ use Icinga\Exception\ProgrammingError; class FormLoader { - public static function load($name, Module $module = null) + public static function load($name, ?Module $module = null) { if ($module === null) { $basedir = Icinga::app()->getApplicationDir('forms'); diff --git a/library/Businessprocess/Web/Form/QuickBaseForm.php b/library/Businessprocess/Web/Form/QuickBaseForm.php index 6a60d69..b5d8961 100644 --- a/library/Businessprocess/Web/Form/QuickBaseForm.php +++ b/library/Businessprocess/Web/Form/QuickBaseForm.php @@ -140,7 +140,7 @@ abstract class QuickBaseForm extends Zend_Form implements ValidHtml return $this; } - protected function loadForm($name, Module $module = null) + protected function loadForm($name, ?Module $module = null) { if ($module === null) { $module = $this->icingaModule; diff --git a/library/Businessprocess/Web/Form/QuickForm.php b/library/Businessprocess/Web/Form/QuickForm.php index 5326da3..2420678 100644 --- a/library/Businessprocess/Web/Form/QuickForm.php +++ b/library/Businessprocess/Web/Form/QuickForm.php @@ -325,7 +325,7 @@ abstract class QuickForm extends QuickBaseForm return $this; } - public function handleRequest(Request $request = null) + public function handleRequest(?Request $request = null) { if ($request === null) { $request = $this->getRequest(); From 0e119943499af0dd2a049c2367506a9093097d1c Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Wed, 3 Dec 2025 09:43:08 +0100 Subject: [PATCH 2/6] Explicitly set the escape parameter of fputcsv() Relying on the default value is deprecated since PHP-8.4 --- application/controllers/ProcessController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/controllers/ProcessController.php b/application/controllers/ProcessController.php index c12f024..5644d16 100644 --- a/application/controllers/ProcessController.php +++ b/application/controllers/ProcessController.php @@ -747,7 +747,7 @@ class ProcessController extends Controller case 'csv': $csv = fopen('php://temp', 'w'); - fputcsv($csv, ['Path', 'Name', 'State', 'Since', 'In_Downtime']); + fputcsv($csv, ['Path', 'Name', 'State', 'Since', 'In_Downtime'], escape: '\\'); foreach ($node !== null ? $node->toArray(null, true) : $bp->toArray(true) as $node) { $data = [$node['path'], $node['name']]; @@ -764,7 +764,7 @@ class ProcessController extends Controller $data[] = $node['in_downtime']; } - fputcsv($csv, $data); + fputcsv($csv, $data, escape: '\\'); } $response = $this->getResponse(); From 400ad694972134521e9eebffbc5cfe1fe173701b Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Thu, 4 Dec 2025 15:08:59 +0100 Subject: [PATCH 3/6] Replace null as array key with an empty string Using null as an array key is deprecated in PHP-8.5, an empty string can be used for identical behavior. This includes values that are passed to ZendForm::addDisplayGroup as elements, as they will be used as array keys. --- application/forms/BpConfigForm.php | 2 +- application/forms/SimulationForm.php | 2 +- library/Businessprocess/BpConfig.php | 2 +- library/Businessprocess/Web/Form/QuickBaseForm.php | 2 +- library/Businessprocess/Web/Form/QuickForm.php | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/application/forms/BpConfigForm.php b/application/forms/BpConfigForm.php index 0e9a5b3..a11d59b 100644 --- a/application/forms/BpConfigForm.php +++ b/application/forms/BpConfigForm.php @@ -66,7 +66,7 @@ class BpConfigForm extends BpConfigBaseForm . ' this process should be retrieved from' ), 'multiOptions' => array( - null => $this->translate('Use the configured default backend'), + '' => $this->translate('Use the configured default backend'), ) + $this->listAvailableBackends() )); } diff --git a/application/forms/SimulationForm.php b/application/forms/SimulationForm.php index cabd859..88a08fc 100644 --- a/application/forms/SimulationForm.php +++ b/application/forms/SimulationForm.php @@ -127,7 +127,7 @@ class SimulationForm extends BpConfigBaseForm protected function enumStateNames() { $states = array( - null => sprintf( + '' => sprintf( $this->translate('Use current state (%s)'), $this->translate($this->node->getStateName()) ) diff --git a/library/Businessprocess/BpConfig.php b/library/Businessprocess/BpConfig.php index f0b3584..2aae1aa 100644 --- a/library/Businessprocess/BpConfig.php +++ b/library/Businessprocess/BpConfig.php @@ -605,7 +605,7 @@ class BpConfig public function listInvolvedConfigs(&$configs = null) { if ($configs === null) { - $configs[$this->getName()] = $this; + $configs[$this->getName() ?? ''] = $this; } foreach ($this->importedNodes as $node) { diff --git a/library/Businessprocess/Web/Form/QuickBaseForm.php b/library/Businessprocess/Web/Form/QuickBaseForm.php index b5d8961..0e889f7 100644 --- a/library/Businessprocess/Web/Form/QuickBaseForm.php +++ b/library/Businessprocess/Web/Form/QuickBaseForm.php @@ -116,7 +116,7 @@ abstract class QuickBaseForm extends Zend_Form implements ValidHtml $nullLabel = $this->translate('- please choose -'); } - return array(null => $nullLabel) + $enum; + return array('' => $nullLabel) + $enum; } protected function handleOptions($options = null) diff --git a/library/Businessprocess/Web/Form/QuickForm.php b/library/Businessprocess/Web/Form/QuickForm.php index 2420678..96a84cd 100644 --- a/library/Businessprocess/Web/Form/QuickForm.php +++ b/library/Businessprocess/Web/Form/QuickForm.php @@ -131,8 +131,8 @@ abstract class QuickForm extends QuickBaseForm ); $grp = array( - $this->submitButtonName, - $this->deleteButtonName + $this->submitButtonName ?? '', + $this->deleteButtonName ?? '' ); $this->addDisplayGroup($grp, 'buttons', array( 'decorators' => array( From 71f0ea38780d2fd90c18bfa2c49fde6f0107906b Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Wed, 10 Dec 2025 09:25:50 +0100 Subject: [PATCH 4/6] Mark uploaded_file element as required Explictly set the required attribute of the uploaded_file element of BpUploadForm to true. previously the resulting-html element was not required and submitting the form caused null being passed. This is necessary because this class does not extend the Web\Form, and the Zend_Form does not mark the elment as required. --- application/forms/BpUploadForm.php | 1 + 1 file changed, 1 insertion(+) diff --git a/application/forms/BpUploadForm.php b/application/forms/BpUploadForm.php index 9327981..130872c 100644 --- a/application/forms/BpUploadForm.php +++ b/application/forms/BpUploadForm.php @@ -142,6 +142,7 @@ class BpUploadForm extends BpConfigBaseForm /** @var \Zend_Form_Element_File $el */ $el = $this->getElement('uploaded_file'); $el->setValueDisabled(true); + $el->setAttrib('required', true); $this->setSubmitLabel( $this->translate('Next') From 5bba8ba0ec11e3c36cf3ca5fc6141e69b3fc898e Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Fri, 9 Jan 2026 08:23:54 +0100 Subject: [PATCH 5/6] Only add display groups for defined buttons Elements passed to ZendForm::addDisplayGroup will be used as array keys, if they are null that causes a deprecation warning since PHP-8.5. To avoid this all null values are removed. --- library/Businessprocess/Web/Form/QuickForm.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/Businessprocess/Web/Form/QuickForm.php b/library/Businessprocess/Web/Form/QuickForm.php index 96a84cd..61af62f 100644 --- a/library/Businessprocess/Web/Form/QuickForm.php +++ b/library/Businessprocess/Web/Form/QuickForm.php @@ -130,9 +130,10 @@ abstract class QuickForm extends QuickBaseForm ) ); - $grp = array( - $this->submitButtonName ?? '', - $this->deleteButtonName ?? '' + // Add display group for defined buttons only + $grp = array_filter( + [$this->submitButtonName, $this->deleteButtonName], + fn($x) => $x !== null ); $this->addDisplayGroup($grp, 'buttons', array( 'decorators' => array( From b153a51cb644e05d0cafb36033372ccd116ed406 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Fri, 9 Jan 2026 08:35:49 +0100 Subject: [PATCH 6/6] Set BpConifg::name by a constructor argument with default A bug was caused by BpConfig::getName returning null, because the result was used as an array key, which is deprecated since PHP-8.5. To avoid any further issues the constructor now ensures the name is always set. --- library/Businessprocess/BpConfig.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/Businessprocess/BpConfig.php b/library/Businessprocess/BpConfig.php index 2aae1aa..0a54d31 100644 --- a/library/Businessprocess/BpConfig.php +++ b/library/Businessprocess/BpConfig.php @@ -133,8 +133,9 @@ class BpConfig /** @var bool Whether the config is faulty */ protected $isFaulty = false; - public function __construct() + public function __construct(string $name = 'dummy') { + $this->setName($name); } /** @@ -605,7 +606,7 @@ class BpConfig public function listInvolvedConfigs(&$configs = null) { if ($configs === null) { - $configs[$this->getName() ?? ''] = $this; + $configs[$this->getName()] = $this; } foreach ($this->importedNodes as $node) {