Skip to content

Commit

Permalink
Add the ability to implement a specific logic when a capacity is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
cedric-anne committed Dec 3, 2024
1 parent fc473e3 commit cda2d12
Show file tree
Hide file tree
Showing 25 changed files with 169 additions and 252 deletions.
48 changes: 0 additions & 48 deletions .phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -2473,12 +2473,6 @@
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/Asset.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between Glpi\\\\Asset\\\\AssetDefinition and Glpi\\\\Asset\\\\AssetDefinition will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/Asset.php',
];
$ignoreErrors[] = [
'message' => '#^Method Glpi\\\\Asset\\\\Asset\\:\\:getById\\(\\) should return static\\(Glpi\\\\Asset\\\\Asset\\)\\|false but returns object\\.$#',
'identifier' => 'return.type',
Expand All @@ -2503,24 +2497,12 @@
'count' => 2,
'path' => __DIR__ . '/src/Glpi/Asset/AssetDefinitionManager.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between Glpi\\\\Asset\\\\AssetDefinition and Glpi\\\\Asset\\\\AssetDefinition will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/AssetModel.php',
];
$ignoreErrors[] = [
'message' => '#^Method Glpi\\\\Asset\\\\AssetModel\\:\\:getById\\(\\) should return static\\(Glpi\\\\Asset\\\\AssetModel\\)\\|false but returns Glpi\\\\Asset\\\\AssetModel\\.$#',
'identifier' => 'return.type',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/AssetModel.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between Glpi\\\\Asset\\\\AssetDefinition and Glpi\\\\Asset\\\\AssetDefinition will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/AssetType.php',
];
$ignoreErrors[] = [
'message' => '#^Method Glpi\\\\Asset\\\\AssetType\\:\\:getById\\(\\) should return static\\(Glpi\\\\Asset\\\\AssetType\\)\\|false but returns Glpi\\\\Asset\\\\AssetType\\.$#',
'identifier' => 'return.type',
Expand All @@ -2545,30 +2527,6 @@
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/Capacity/CapacityInterface.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between Glpi\\\\Asset\\\\AssetDefinition and Glpi\\\\Asset\\\\AssetDefinition will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/RuleDictionaryModel.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between Glpi\\\\Asset\\\\AssetDefinition and Glpi\\\\Asset\\\\AssetDefinition will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/RuleDictionaryModelCollection.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between Glpi\\\\Asset\\\\AssetDefinition and Glpi\\\\Asset\\\\AssetDefinition will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/RuleDictionaryType.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between Glpi\\\\Asset\\\\AssetDefinition and Glpi\\\\Asset\\\\AssetDefinition will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Asset/RuleDictionaryTypeCollection.php',
];
$ignoreErrors[] = [
'message' => '#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#',
'identifier' => 'function.alreadyNarrowedType',
Expand Down Expand Up @@ -2953,12 +2911,6 @@
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Debug/ProfilerSection.php',
];
$ignoreErrors[] = [
'message' => '#^Instanceof between Glpi\\\\Dropdown\\\\DropdownDefinition and Glpi\\\\Dropdown\\\\DropdownDefinition will always evaluate to true\\.$#',
'identifier' => 'instanceof.alwaysTrue',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Dropdown/Dropdown.php',
];
$ignoreErrors[] = [
'message' => '#^Method Glpi\\\\Dropdown\\\\Dropdown\\:\\:getById\\(\\) should return static\\(Glpi\\\\Dropdown\\\\Dropdown\\)\\|false but returns object\\.$#',
'identifier' => 'return.type',
Expand Down
30 changes: 0 additions & 30 deletions phpunit/DbTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -397,20 +397,6 @@ protected function initAssetDefinition(
$this->callPrivateMethod($definition, 'getDecodedProfilesField')
);

// Clear definition cache
$rc = new ReflectionClass(\Glpi\CustomObject\AbstractDefinitionManager::class);
$rc->getProperty('definitions_data')->setValue(\Glpi\Asset\AssetDefinitionManager::getInstance(), []);

$manager = \Glpi\Asset\AssetDefinitionManager::getInstance();
$this->callPrivateMethod($manager, 'loadConcreteClass', $definition);
$this->callPrivateMethod($manager, 'loadConcreteModelClass', $definition);
$this->callPrivateMethod($manager, 'loadConcreteTypeClass', $definition);
$this->callPrivateMethod($manager, 'loadConcreteModelDictionaryCollectionClass', $definition);
$this->callPrivateMethod($manager, 'loadConcreteModelDictionaryClass', $definition);
$this->callPrivateMethod($manager, 'loadConcreteTypeDictionaryCollectionClass', $definition);
$this->callPrivateMethod($manager, 'loadConcreteTypeDictionaryClass', $definition);
$this->callPrivateMethod($manager, 'boostrapConcreteClass', $definition);

return $definition;
}

Expand Down Expand Up @@ -472,14 +458,6 @@ protected function enableCapacity(
$this->callPrivateMethod($definition, 'getDecodedCapacitiesField')
);

// Force boostrap to trigger methods such as "onClassBootstrap"
$manager = AssetDefinitionManager::getInstance();
$this->callPrivateMethod(
$manager,
'boostrapConcreteClass',
$definition
);

return $definition;
}

Expand Down Expand Up @@ -520,14 +498,6 @@ protected function disableCapacity(
$this->callPrivateMethod($definition, 'getDecodedCapacitiesField')
);

// Force boostrap to trigger methods such as "onClassBootstrap"
$manager = AssetDefinitionManager::getInstance();
$this->callPrivateMethod(
$manager,
'boostrapConcreteClass',
$definition
);

return $definition;
}
}
9 changes: 5 additions & 4 deletions src/Glpi/Asset/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ abstract class Asset extends CommonDBTM
use \Glpi\Features\Inventoriable;

/**
* Asset definition.
* Asset definition system name.
*
* Must be defined here to make PHPStan happy (see https://github.com/phpstan/phpstan/issues/8808).
* Must be defined by child class too to ensure that assigning a value to this property will affect
* each child classe independently.
*/
protected static AssetDefinition $definition;
protected static string $definition_system_name;

final public function __construct()
{
Expand All @@ -84,11 +84,12 @@ final public function __construct()
*/
public static function getDefinition(): AssetDefinition
{
if (!(static::$definition instanceof AssetDefinition)) {
$definition = AssetDefinitionManager::getInstance()->getDefinition(static::$definition_system_name);
if (!($definition instanceof AssetDefinition)) {
throw new \RuntimeException('Asset definition is expected to be defined in concrete class.');
}

return static::$definition;
return $definition;
}

public static function getDefinitionClass(): string
Expand Down
79 changes: 56 additions & 23 deletions src/Glpi/Asset/AssetDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
* http://glpi-project.org
*
* @copyright 2015-2024 Teclib' and contributors.
* @copyright 2003-2014 by the INDEPNET Development Team.
* @licence https://www.gnu.org/licenses/gpl-3.0.html
*
* ---------------------------------------------------------------------
Expand Down Expand Up @@ -36,13 +35,8 @@
namespace Glpi\Asset;

use CommonGLPI;
use Dropdown;
use Gettext\Languages\Category as Language_Category;
use Gettext\Languages\CldrData as Language_CldrData;
use Gettext\Languages\Language;
use Glpi\Application\View\TemplateRenderer;
use Glpi\Asset\Capacity\CapacityInterface;
use Glpi\Asset\CustomFieldType\TypeInterface;
use Glpi\CustomObject\AbstractDefinition;
use Glpi\DBAL\QueryExpression;
use Glpi\DBAL\QueryFunction;
Expand Down Expand Up @@ -308,6 +302,14 @@ protected function prepareInput(array $input): array|bool

public function post_addItem()
{
parent::post_addItem();

// Trigger the `onCapacityEnabled` hooks.
$added_capacities = @json_decode($this->fields['capacities']);
foreach ($added_capacities as $capacity_classname) {
$this->onCapacityEnabled($capacity_classname);
}

// Add default display preferences for the new asset definition
$prefs = [
4, // Name
Expand All @@ -326,14 +328,13 @@ public function post_addItem()
'users_id' => 0,
]);
}

parent::post_addItem();
}

public function post_updateItem($history = true)
{
parent::post_updateItem();

if (in_array('capacities', $this->updates)) {
// When capabilities are removed, trigger the cleaning of data related to this capacity.
$new_capacities = @json_decode($this->fields['capacities']);
$old_capacities = @json_decode($this->oldvalues['capacities']);

Expand All @@ -354,28 +355,25 @@ public function post_updateItem($history = true)
return;
}

$removed_capacities = array_diff($old_capacities, $new_capacities);
$rights_to_remove = [];
foreach ($removed_capacities as $capacity_classname) {
$capacity = AssetDefinitionManager::getInstance()->getCapacity($capacity_classname);
if ($capacity === null) {
// can be null if provided by a plugin that is no longer active
continue;
}
$capacity->onCapacityDisabled($this->getAssetClassName());
array_push($rights_to_remove, ...$capacity->getSpecificRights());
$added_capacities = array_diff($new_capacities, $old_capacities);
foreach ($added_capacities as $capacity_classname) {
$this->onCapacityEnabled($capacity_classname);
}

if (count($rights_to_remove) > 0) {
$this->cleanRights($rights_to_remove);
$removed_capacities = array_diff($old_capacities, $new_capacities);
foreach ($removed_capacities as $capacity_classname) {
$this->onCapacityDisabled($capacity_classname);
}
}

parent::post_updateItem();
}

public function cleanDBonPurge()
{
$capacities = $this->getDecodedCapacitiesField();
foreach ($capacities as $capacity_classname) {
$this->onCapacityDisabled($capacity_classname);
}

$related_classes = [
$this->getAssetClassName(),
$this->getAssetModelClassName(),
Expand All @@ -391,6 +389,41 @@ public function cleanDBonPurge()
}
}

/**
* Handle the activation of a capacity.
*
* @phpstan-param class-string<\Glpi\Asset\Capacity\CapacityInterface> $capacity_classname
*/
private function onCapacityEnabled(string $capacity_classname): void
{
$capacity = AssetDefinitionManager::getInstance()->getCapacity($capacity_classname);
if ($capacity === null) {
// can be null if provided by a plugin that is no longer active
return;
}
$capacity->onCapacityEnabled($this->getAssetClassName());
}

/**
* Handle the deactivation of a capacity.
*
* @phpstan-param class-string<\Glpi\Asset\Capacity\CapacityInterface> $capacity_classname
*/
private function onCapacityDisabled(string $capacity_classname): void
{
$capacity = AssetDefinitionManager::getInstance()->getCapacity($capacity_classname);
if ($capacity === null) {
// can be null if provided by a plugin that is no longer active
return;
}
$capacity->onCapacityDisabled($this->getAssetClassName());

$rights_to_remove = $capacity->getSpecificRights();
if (count($rights_to_remove) > 0) {
$this->cleanRights($rights_to_remove);
}
}

public function rawSearchOptions()
{
$search_options = parent::rawSearchOptions();
Expand Down
Loading

0 comments on commit cda2d12

Please sign in to comment.