diff --git a/src/Dropdown.php b/src/Dropdown.php index e569b073b37..9edd3d11e5e 100644 --- a/src/Dropdown.php +++ b/src/Dropdown.php @@ -2641,7 +2641,7 @@ public static function getDropdownValue($post, $json = true) */ global $CFG_GLPI, $DB; - // check if asked itemtype is the one originaly requested by the form + // check if asked itemtype is the one originally requested by the form if (!Session::validateIDOR($post)) { return; } diff --git a/src/DropdownVisibility.php b/src/DropdownVisibility.php index 38e149eb788..d6e122cfb6e 100644 --- a/src/DropdownVisibility.php +++ b/src/DropdownVisibility.php @@ -42,4 +42,5 @@ class DropdownVisibility extends CommonDBChild public static $itemtype = 'itemtype'; public static $items_id = 'states_id'; public $dohistory = false; + public static $logs_for_parent = false; } diff --git a/src/Features/State.php b/src/Features/State.php index 8820e740d84..db6d9924c93 100644 --- a/src/Features/State.php +++ b/src/Features/State.php @@ -49,8 +49,72 @@ trait State { - public function isStateVisibile(): bool + /** + * Check if itemtype class is present in configuration array + * + * @return void + */ + protected function checkSetup(): void { - return false; + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + + if (!in_array(get_class($this), $CFG_GLPI['state_types'])) { + trigger_error( + sprintf( + 'Class %s must be present in $CFG_GLPI[\'state_types\']', + get_class($this) + ), + E_USER_ERROR + ); + } + } + + /** + * Get the visibility of the state field for the item + * + * @param int $id State ID + * + * @return bool + */ + public function isStateVisible(int $id): bool + { + $this->checkSetup(); + $dropdownVisibility = new \DropdownVisibility(); + return $dropdownVisibility->getFromDBByCrit([ + 'itemtype' => \State::getType(), + 'items_id' => $id, + 'visible_itemtype' => get_class($this), + 'is_visible' => 1 + ]); + } + + /** + * Get the visibility criteria of the state field to use a filter condition + * + * @return array + */ + public function getVisibilityCriteria(): array + { + $this->checkSetup(); + return [ + 'LEFT JOIN' => [ + \DropdownVisibility::getTable() => [ + 'ON' => [ + \DropdownVisibility::getTable() => 'items_id', + \State::getTable() => 'id', [ + 'AND' => [ + \DropdownVisibility::getTable() . '.itemtype' => \State::getType() + ] + ] + ] + ] + ], + 'WHERE' => [ + \DropdownVisibility::getTable() . '.itemtype' => \State::getType(), + \DropdownVisibility::getTable() . '.visible_itemtype' => get_class($this), + \DropdownVisibility::getTable() . '.is_visible' => 1 + ] + ]; } } diff --git a/src/State.php b/src/State.php index fdbbf03add4..3a17f9d5936 100644 --- a/src/State.php +++ b/src/State.php @@ -349,7 +349,7 @@ public function post_updateItem($history = true) $state_visilibity = new DropdownVisibility(); foreach ($this->getvisibilityFields() as $itemtype => $field) { if (isset($this->input[$field])) { - if ($state_visilibity->getFromDBByCrit(['items_id' => $this->input['id'], 'itemtype' => $itemtype])) { + if ($state_visilibity->getFromDBByCrit(['itemtype' => self::getType(), 'items_id' => $this->input['id'], 'visible_itemtype' => $itemtype])) { $state_visilibity->update([ 'id' => $state_visilibity->fields['id'], 'is_visible' => $this->input[$field] diff --git a/templates/components/form/item_device.html.twig b/templates/components/form/item_device.html.twig index dd709ed614f..2ccb73f9814 100644 --- a/templates/components/form/item_device.html.twig +++ b/templates/components/form/item_device.html.twig @@ -183,7 +183,6 @@ {% endif %} {% if item.isField('states_id') %} - {% set condition = item.getType() in config('state_types') ? item.isStateVisibile() : {} %} {{ fields.dropdownField( 'State', 'states_id', @@ -191,7 +190,7 @@ __('Status'), field_options|merge({ 'entity': item.fields['entities_id'], - 'condition': condition + 'condition': item.getVisibilityCriteria() ?? {} }) ) }} {% endif %} diff --git a/templates/generic_show_form.html.twig b/templates/generic_show_form.html.twig index f16b0605741..df72c98323e 100644 --- a/templates/generic_show_form.html.twig +++ b/templates/generic_show_form.html.twig @@ -98,7 +98,6 @@ {% endif %} {% if item.isField('states_id') %} - {% set condition = item.getType() in config('state_types') ? item.isStateVisibile() : {} %} {{ fields.dropdownField( 'State', 'states_id', @@ -106,7 +105,7 @@ __('Status'), field_options|merge({ 'entity': item.fields['entities_id'], - 'condition': condition + 'condition': item.getVisibilityCriteria() ?? {} }) ) }} {% endif %} diff --git a/tests/functional/State.php b/tests/functional/State.php index ddaa1e1368a..46137c6ed8c 100644 --- a/tests/functional/State.php +++ b/tests/functional/State.php @@ -110,7 +110,7 @@ public function testVisibility() ]); $visibilities = $statevisibility->find(['itemtype' => \State::getType(), 'items_id' => $states_id]); $this->array($visibilities)->hasSize(3); - $visibilities = $statevisibility->find(['states_id' => $states_id, 'is_visible' => 1]); + $visibilities = $statevisibility->find(['itemtype' => \State::getType(), 'items_id' => $states_id, 'is_visible' => 1]); $this->array($visibilities)->hasSize(2); $this->boolean($statevisibility->getFromDBByCrit(['itemtype' => \State::getType(), 'items_id' => $states_id, 'visible_itemtype' => \Computer::getType(), 'is_visible' => 0]))->isTrue(); $this->boolean($statevisibility->getFromDBByCrit(['itemtype' => \State::getType(), 'items_id' => $states_id, 'visible_itemtype' => \Phone::getType(), 'is_visible' => 1]))->isTrue(); @@ -129,7 +129,68 @@ public function testHasFeature() global $CFG_GLPI; foreach ($CFG_GLPI['state_types'] as $itemtype) { - $this->boolean(method_exists($itemtype, 'isStateVisibile'))->isTrue($itemtype . ' misses isStateVisibile() method!'); + $this->boolean(method_exists($itemtype, 'isStateVisible'))->isTrue($itemtype . ' misses isStateVisible() method!'); } } + + public function testIsStateVisible() + { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + + $state = new \State(); + $states_id = $state->add([ + 'name' => 'Test computer and phone', + 'is_visible_computer' => '1' + ]); + $this->integer($states_id)->isGreaterThan(0); + + $itemtype = $CFG_GLPI['state_types'][0]; + + $item = new $itemtype(); + $this->boolean(method_exists($itemtype, 'isStateVisible'))->isTrue($itemtype . ' misses isStateVisible() method!'); + $this->boolean($item->isStateVisible($states_id))->isTrue(); + + unset($CFG_GLPI['state_types'][0]); + $this->boolean(method_exists($itemtype, 'isStateVisible'))->isTrue($itemtype . ' misses isStateVisible() method!'); + + $this->when( + function() use ($item, $states_id) { + $this->boolean($item->isStateVisible($states_id))->isTrue(); + } + ) + ->error() + ->withType(E_USER_ERROR) + ->withMessage('Class Computer must be present in $CFG_GLPI[\'state_types\']') + ->exists(); + } + + public function testGetVisibilityCriteria() + { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + + $itemtype = $CFG_GLPI['state_types'][0]; + + $item = new $itemtype(); + $this->array($item->getVisibilityCriteria())->isIdenticalTo([ + 'LEFT JOIN' => [ + \DropdownVisibility::getTable() => [ + 'ON' => [ + \DropdownVisibility::getTable() => 'items_id', + \State::getTable() => 'id', [ + 'AND' => [ + \DropdownVisibility::getTable() . '.itemtype' => \State::getType() + ] + ] + ] + ] + ], + 'WHERE' => [ + \DropdownVisibility::getTable() . '.itemtype' => \State::getType(), + \DropdownVisibility::getTable() . '.visible_itemtype' => $itemtype, + \DropdownVisibility::getTable() . '.is_visible' => 1 + ] + ]); + } }