diff --git a/front/computermodel.form.php b/front/computermodel.form.php
new file mode 100644
index 00000000..5a3409cb
--- /dev/null
+++ b/front/computermodel.form.php
@@ -0,0 +1,53 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+use Glpi\Exception\Http\NotFoundHttpException;
+use GlpiPlugin\Carbon\ComputerModel;
+
+include(__DIR__ . '/../../../inc/includes.php');
+
+if (!Plugin::isPluginActive('carbon')) {
+ throw new NotFoundHttpException();
+}
+
+Session::checkRight('config', UPDATE);
+
+$item = new ComputerModel();
+
+if (isset($_POST['update'])) {
+ // Add a new Form
+ Session::checkRight('entity', UPDATE);
+ $item->update($_POST);
+ Html::back();
+}
+
+Html::back();
diff --git a/front/embodiedimpact.form.php b/front/embodiedimpact.form.php
index b588851c..24a1ba6a 100644
--- a/front/embodiedimpact.form.php
+++ b/front/embodiedimpact.form.php
@@ -32,9 +32,7 @@
use Glpi\Event;
use Glpi\Exception\Http\NotFoundHttpException;
-use GlpiPlugin\Carbon\Config;
use GlpiPlugin\Carbon\EmbodiedImpact;
-use GlpiPlugin\Carbon\Impact\Embodied\AbstractEmbodiedImpact;
use GlpiPlugin\Carbon\Impact\Embodied\Engine;
include(__DIR__ . '/../../../inc/includes.php');
diff --git a/front/monitormodel.form.php b/front/monitormodel.form.php
new file mode 100644
index 00000000..01ecccd8
--- /dev/null
+++ b/front/monitormodel.form.php
@@ -0,0 +1,54 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+use Glpi\Exception\Http\NotFoundHttpException;
+use GlpiPlugin\Carbon\MonitorModel;
+
+include(__DIR__ . '/../../../inc/includes.php');
+
+if (!Plugin::isPluginActive('carbon')) {
+ throw new NotFoundHttpException();
+}
+
+
+Session::checkRight('config', UPDATE);
+
+$item = new MonitorModel();
+
+if (isset($_POST['update'])) {
+ // Add a new Form
+ Session::checkRight('entity', UPDATE);
+ $item->update($_POST);
+ Html::back();
+}
+
+Html::back();
diff --git a/front/networkequipmentmodel.form.php b/front/networkequipmentmodel.form.php
new file mode 100644
index 00000000..ff13a764
--- /dev/null
+++ b/front/networkequipmentmodel.form.php
@@ -0,0 +1,54 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+use Glpi\Exception\Http\NotFoundHttpException;
+use GlpiPlugin\Carbon\NetworkEquipmentModel;
+
+include(__DIR__ . '/../../../inc/includes.php');
+
+if (!Plugin::isPluginActive('carbon')) {
+ throw new NotFoundHttpException();
+}
+
+
+Session::checkRight('config', UPDATE);
+
+$item = new NetworkEquipmentModel();
+
+if (isset($_POST['update'])) {
+ // Add a new Form
+ Session::checkRight('entity', UPDATE);
+ $item->update($_POST);
+ Html::back();
+}
+
+Html::back();
diff --git a/install/mysql/plugin_carbon_empty.sql b/install/mysql/plugin_carbon_empty.sql
index 31bc8fd9..da2f1360 100644
--- a/install/mysql/plugin_carbon_empty.sql
+++ b/install/mysql/plugin_carbon_empty.sql
@@ -89,6 +89,22 @@ CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_sources_zones` (
UNIQUE KEY `unicity` (`plugin_carbon_sources_id`, `plugin_carbon_zones_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_computermodels` (
+ `id` int unsigned NOT NULL AUTO_INCREMENT,
+ `computermodels_id` int unsigned NOT NULL DEFAULT '0',
+ `gwp` int DEFAULT '0' COMMENT '(unit gCO2eq) Global warming potential',
+ `gwp_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `gwp_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ `adp` int DEFAULT '0' COMMENT '(unit gSbEq) Abiotic depletion potential',
+ `adp_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `adp_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ `pe` int DEFAULT '0' COMMENT '(unit J) Primary energy',
+ `pe_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `pe_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `unicity` (`computermodels_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_computertypes` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`computertypes_id` int unsigned NOT NULL DEFAULT '0',
@@ -139,6 +155,22 @@ CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_environmentalimpacts` (
UNIQUE KEY `unicity` (`computers_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_monitormodels` (
+ `id` int unsigned NOT NULL AUTO_INCREMENT,
+ `monitormodels_id` int unsigned NOT NULL DEFAULT '0',
+ `gwp` int DEFAULT '0' COMMENT '(unit gCO2eq) Global warming potential',
+ `gwp_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `gwp_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ `adp` int DEFAULT '0' COMMENT '(unit gSbEq) Abiotic depletion potential',
+ `adp_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `adp_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ `pe` int DEFAULT '0' COMMENT '(unit J) Primary energy',
+ `pe_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `pe_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `unicity` (`monitormodels_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_monitortypes` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`monitortypes_id` int unsigned NOT NULL DEFAULT '0',
@@ -148,6 +180,22 @@ CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_monitortypes` (
UNIQUE KEY `unicity` (`monitortypes_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_networkequipmentmodels` (
+ `id` int unsigned NOT NULL AUTO_INCREMENT,
+ `networkequipmentmodels_id` int unsigned NOT NULL DEFAULT '0',
+ `gwp` int DEFAULT '0' COMMENT '(unit gCO2eq) Global warming potential',
+ `gwp_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `gwp_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ `adp` int DEFAULT '0' COMMENT '(unit gSbEq) Abiotic depletion potential',
+ `adp_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `adp_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ `pe` int DEFAULT '0' COMMENT '(unit J) Primary energy',
+ `pe_source` mediumtext DEFAULT NULL COMMENT 'any information to describe the source, URL preferred',
+ `pe_quality` int DEFAULT '0' COMMENT 'DataTtacking\\AbstractTracked::DATA_QUALITY_* constants',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `unicity` (`networkequipmentmodels_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
CREATE TABLE IF NOT EXISTS `glpi_plugin_carbon_networkequipmenttypes` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`networkequipmenttypes_id` int unsigned NOT NULL DEFAULT '0',
diff --git a/setup.php b/setup.php
index 8bc52c66..3e421701 100644
--- a/setup.php
+++ b/setup.php
@@ -43,7 +43,7 @@
use GlpiPlugin\Carbon\Location;
define('PLUGIN_CARBON_VERSION', '1.2.0-dev');
-define('PLUGIN_CARBON_SCHEMA_VERSION', '1.1.0');
+define('PLUGIN_CARBON_SCHEMA_VERSION', '1.2.0');
// Minimal GLPI version, inclusive
define("PLUGIN_CARBON_MIN_GLPI_VERSION", "11.0.0-beta");
@@ -143,10 +143,15 @@ function plugin_carbon_registerClasses()
Plugin::registerClass(Location::class, ['addtabon' => GlpiLocation::class]);
foreach (PLUGIN_CARBON_TYPES as $itemtype) {
- $item_type_class = 'GlpiPlugin\\Carbon\\' . $itemtype . 'Type';
$core_type_class = $itemtype . 'Type';
+ $item_type_class = 'GlpiPlugin\\Carbon\\' . $core_type_class;
Plugin::registerClass($item_type_class, ['addtabon' => $core_type_class]);
+
Plugin::registerClass(UsageInfo::class, ['addtabon' => $itemtype]);
+
+ $core_model_class = $itemtype . 'Model';
+ $item_model_class = 'GlpiPlugin\\Carbon\\' . $core_model_class;
+ Plugin::registerClass($item_model_class, ['addtabon' => $core_model_class]);
}
}
diff --git a/src/AbstractModel.php b/src/AbstractModel.php
new file mode 100644
index 00000000..950cf3ce
--- /dev/null
+++ b/src/AbstractModel.php
@@ -0,0 +1,141 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon;
+
+use CommonDBChild;
+use CommonDBTM;
+use CommonGLPI;
+use Glpi\Application\View\TemplateRenderer;
+use Session;
+
+class AbstractModel extends CommonDBChild
+{
+ public static $rightname = 'dropdown';
+
+ public static function getIcon(): string
+ {
+ return 'fa-solid fa-solar-panel';
+ }
+
+ public static function getTypeName($nb = 0)
+ {
+ return _n('Environmental impact', 'Environmental impact', $nb, 'carbon');
+ }
+
+ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
+ {
+ $tabName = '';
+ if (!$withtemplate) {
+ if ($item->getType() == static::$itemtype) {
+ return self::createTabEntry(__('Carbon', 'carbon'), 0);
+ }
+ }
+ return $tabName;
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @param CommonGLPI $item
+ * @param integer $tabnum
+ * @param integer $withtemplate
+ * @return void
+ */
+ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0)
+ {
+ /** @var CommonDBTM $item */
+ if ($item->getType() !== static::$itemtype) {
+ return;
+ }
+
+ $type = new static();
+ $type->getOrCreate($item);
+ $type->showForItemType($type->getID());
+ }
+
+ /**
+ * Get the type for the item, creating it if it doesn't exist.
+ *
+ * @param CommonGLPI $item
+ * @return bool
+ */
+ protected function getOrCreate(CommonGLPI $item): bool
+ {
+ /** @var CommonDBTM $item */
+ $item_fk = $item->getForeignKeyField();
+ $this->getFromDBByCrit([$item_fk => $item->getID()]);
+ if ($this->isNewItem()) {
+ $this->add([
+ $item_fk => $item->getID()
+ ]);
+ }
+ return $this->isNewItem();
+ }
+
+ public function showForItemType($ID, $withtemplate = '')
+ {
+ // TODO: Design a rights system for the whole plugin
+ $canedit = Session::haveRight(Config::$rightname, UPDATE);
+
+ $options = [
+ 'candel' => false,
+ 'can_edit' => $canedit,
+ ];
+ $this->initForm($this->getID(), $options);
+
+ $criterias = [
+ 'gwp' => [
+ 'title' => __('Global warming potential', 'carbon'),
+ 'label' => __('Emissions of CO2 (KgCO2eq)', 'carbon'),
+ 'icon' => '', // 'fa-solid fa-temperature-three-quarters'
+ ],
+ 'adp' => [
+ 'title' => __('Abiotic depletion potential', 'carbon'),
+ 'label' => __('Abiotic depletion potential (gSbEq)', 'carbon'),
+ 'icon' => '', // @todo : find an icon
+ ],
+ 'pe' => [
+ 'title' => __('Primary energy', 'carbon'),
+ 'label' => __('Primary energy (J)', 'carbon'),
+ 'icon' => '', // @todo : find an icon
+ ],
+ ];
+
+ $template = strtolower(basename(str_replace('\\', '/', static::class))) . '.html.twig';
+ TemplateRenderer::getInstance()->display('@carbon/' . $template, [
+ 'params' => $options,
+ 'item' => $this,
+ 'criterias' => $criterias,
+ ]);
+ }
+}
diff --git a/src/AbstractType.php b/src/AbstractType.php
index 06f09522..02e6bb8a 100644
--- a/src/AbstractType.php
+++ b/src/AbstractType.php
@@ -42,7 +42,6 @@ abstract class AbstractType extends CommonDBChild
{
public static $rightname = 'dropdown';
-
public static function getIcon(): string
{
return 'fa-solid fa-solar-panel';
@@ -53,7 +52,7 @@ public static function getIcon(): string
*/
public static function getTypeName($nb = 0)
{
- return _n("Power", "Powers", $nb, 'carbon');
+ return _n('Environmental impact', 'Environmental impacts', $nb, 'carbon');
}
public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
diff --git a/src/ComputerModel.php b/src/ComputerModel.php
new file mode 100644
index 00000000..f08fb727
--- /dev/null
+++ b/src/ComputerModel.php
@@ -0,0 +1,41 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon;
+
+use ComputerModel as GlpiComputerModel;
+
+class ComputerModel extends AbstractModel
+{
+ public static $itemtype = GlpiComputerModel::class;
+ public static $items_id = 'computermodels_id';
+}
diff --git a/src/CronTask.php b/src/CronTask.php
index c56e7e1a..9d819164 100644
--- a/src/CronTask.php
+++ b/src/CronTask.php
@@ -37,6 +37,7 @@
use Geocoder\Geocoder;
use GlpiPlugin\Carbon\DataSource\CarbonIntensity\ClientFactory;
use GlpiPlugin\Carbon\DataSource\CarbonIntensity\ClientInterface;
+use GlpiPlugin\Carbon\DataSource\RestApiClient;
use GlpiPlugin\Carbon\Impact\Embodied\Engine as EmbodiedEngine;
use GlpiPlugin\Carbon\Impact\Usage\UsageImpactInterface as UsageImpactInterface;
use GlpiPlugin\Carbon\Impact\Usage\Engine as UsageEngine;
@@ -122,10 +123,9 @@ public static function cronUsageImpact(GlpiCronTask $task): int
}
// Calculate other impacts
- $usage_impacts = Toolbox::getUsageImpactClasses();
- foreach ($usage_impacts as $usage_impact_type) {
+ foreach (PLUGIN_CARBON_TYPES as $itemtype) {
/** @ar UsageImpactInterface $usage_impact */
- $usage_impact = UsageEngine::getEngine($usage_impact_type);
+ $usage_impact = UsageEngine::getEngineFromItemtype($itemtype, new RestApiClient());
if ($usage_impact === null) {
continue;
}
@@ -146,13 +146,12 @@ public static function cronUsageImpact(GlpiCronTask $task): int
public static function cronEmbodiedImpact(GlpiCronTask $task): int
{
$count = 0;
-
$embodied_impacts = Toolbox::getEmbodiedImpactClasses();
$task->setVolume(0); // start with zero
$remaining = $task->fields['param'];
$limit_per_type = max(1, floor(($remaining) / count($embodied_impacts)));
- foreach ($embodied_impacts as $embodied_impact_type) {
- $embodied_impact = EmbodiedEngine::getEngine($embodied_impact_type);
+ foreach (PLUGIN_CARBON_TYPES as $itemtype) {
+ $embodied_impact = EmbodiedEngine::getEngineFromItemtype($itemtype, new RestApiClient());
if ($embodied_impact === null) {
// An error occured while configuring the engine
continue;
diff --git a/src/DataSource/RestApiClient.php b/src/DataSource/RestApiClient.php
index 6b68f45a..dd46c5d7 100644
--- a/src/DataSource/RestApiClient.php
+++ b/src/DataSource/RestApiClient.php
@@ -35,7 +35,6 @@
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7;
-use Session;
use Toolbox;
class RestApiClient implements RestApiClientInterface
diff --git a/src/DataTracking/AbstractTracked.php b/src/DataTracking/AbstractTracked.php
index 5b9dd680..7e19117b 100644
--- a/src/DataTracking/AbstractTracked.php
+++ b/src/DataTracking/AbstractTracked.php
@@ -32,6 +32,7 @@
namespace GlpiPlugin\Carbon\DataTracking;
+use Dropdown;
use LogicException;
/**
@@ -64,6 +65,36 @@ public function __construct($source = null)
$this->appendSource($source);
}
+ /**
+ * Get name of data qualities
+ *
+ * @return array
+ */
+ public static function getDataQualities(): array
+ {
+ return [
+ self::DATA_QUALITY_UNSPECIFIED => __('Unspecified quality', 'carbon'),
+ self::DATA_QUALITY_MANUAL => __('Manual data', 'carbon'),
+ self::DATA_QUALITY_ESTIMATED => __('Estimated data', 'carbon'),
+ self::DATA_QUALITY_RAW_REAL_TIME_MEASUREMENT_DOWNSAMPLED => __('Downsampled data', 'carbon'),
+ self::DATA_QUALITY_RAW_REAL_TIME_MEASUREMENT => __('Measured data', 'carbon'),
+ ];
+ }
+
+ /**
+ * Show or return HTML code displaying a dropdown of data qualities
+ * @see constants DATA_QUALITY_*
+ *
+ * @param string $name
+ * @param array $options
+ * @return integer|string
+ */
+ public static function dropdownQuality(string $name, array $options = [])
+ {
+ $items = self::getDataQualities();
+ return Dropdown::showFromArray($name, $items, $options);
+ }
+
public function getSource(): array
{
return $this->sources;
diff --git a/src/Impact/Embodied/Engine.php b/src/Impact/Embodied/Engine.php
index b14a6a60..e562af1c 100644
--- a/src/Impact/Embodied/Engine.php
+++ b/src/Impact/Embodied/Engine.php
@@ -35,7 +35,8 @@
use CommonGLPI;
use GlpiPlugin\Carbon\Config;
use GlpiPlugin\Carbon\DataSource\Boaviztapi;
-use GlpiPlugin\Carbon\DataSource\RestApiClient;
+use GlpiPlugin\Carbon\Impact\Embodied\Boavizta\AbstractAsset;
+use GlpiPlugin\Carbon\DataSource\RestApiClientInterface;
class Engine extends CommonGLPI
{
@@ -55,54 +56,61 @@ public static function getAvailableBackends(): array
* Returns null if no engine found
*
* @param string $itemtype itemtype of assets to analyze
+ * @param ?RestApiClientInterface $client
* @return EmbodiedImpactInterface|null an instance if an embodied impact calculation object or null on error
*/
- public static function getEngineFromItemtype(string $itemtype): ?EmbodiedImpactInterface
+ public static function getEngineFromItemtype(string $itemtype, ?RestApiClientInterface $client = null): ?EmbodiedImpactInterface
{
$embodied_impact_namespace = Config::getEmbodiedImpactEngine();
$embodied_impact_class = $embodied_impact_namespace . '\\' . $itemtype;
if (!class_exists($embodied_impact_class) || !is_subclass_of($embodied_impact_class, AbstractEmbodiedImpact::class)) {
- return null;
+ return self::getInternalEngineFromItemtype($itemtype);
}
/** @var AbstractEmbodiedImpact $embodied_impact */
$embodied_impact = new $embodied_impact_class();
try {
- return self::configureEngine($embodied_impact);
+ return self::configureEngine($embodied_impact, $client);
} catch (\RuntimeException $e) {
// If the engine cannot be configured, it is not usable
return null;
}
}
- public static function getEngine(string $engine_class): ?EmbodiedImpactInterface
+ /**
+ * Get an instance of the internal engine to calcilate impacts for the given itemtype
+ * This is a fallback engine
+ *
+ * @param string $itemtype
+ * @return ?EmbodiedImpactInterface
+ */
+ public static function getInternalEngineFromItemtype(string $itemtype): ?EmbodiedImpactInterface
{
- if (!is_subclass_of($engine_class, EmbodiedImpactInterface::class)) {
- return null;
- }
- $embodied_impact = new $engine_class();
-
- try {
- return self::configureEngine($embodied_impact);
- } catch (\RuntimeException $e) {
- // If the engine cannot be configured, it is not usable
+ $embodied_impact_class = 'GlpiPlugin\\Carbon\\Impact\\Embodied\Internal' . '\\' . $itemtype;
+ if (!class_exists($embodied_impact_class) || !is_subclass_of($embodied_impact_class, AbstractEmbodiedImpact::class)) {
return null;
}
+ $embodied_impact = new $embodied_impact_class();
+ return $embodied_impact;
}
/**
* Configure the engine depending on its specificities
*
* @param EmbodiedImpactInterface $engine the engine to configure
+ * @param ?RestApiClientInterface $client
* @return EmbodiedImpactInterface the configured engine
*/
- protected static function configureEngine(EmbodiedImpactInterface $engine): EmbodiedImpactInterface
+ protected static function configureEngine(EmbodiedImpactInterface $engine, ?RestApiClientInterface $client = null): EmbodiedImpactInterface
{
$embodied_impact_namespace = explode('\\', get_class($engine));
switch (array_slice($embodied_impact_namespace, -2, 1)[0]) {
case 'Boavizta':
- /** @var Boavizta\AbstractAsset $engine */
- $engine->setClient(new Boaviztapi(new RestApiClient()));
+ if ($client === null) {
+ throw new \RuntimeException('A RestApiClientInterface instance is required to configure Boavizta embodied impact engine');
+ }
+ /** @var AbstractAsset $engine */
+ $engine->setClient(new Boaviztapi($client));
}
return $engine;
diff --git a/src/Impact/Embodied/Internal/AbstractAsset.php b/src/Impact/Embodied/Internal/AbstractAsset.php
new file mode 100644
index 00000000..341f7939
--- /dev/null
+++ b/src/Impact/Embodied/Internal/AbstractAsset.php
@@ -0,0 +1,44 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Impact\Embodied\Internal;
+
+use GlpiPlugin\Carbon\Impact\Embodied\AbstractEmbodiedImpact;
+
+abstract class AbstractAsset extends AbstractEmbodiedImpact
+{
+ /** @var string $engine Name of the calculation engine */
+ protected string $engine = 'Internal';
+
+ /** @var string $engine_version Version of the calculation engine */
+ protected string $engine_version = '1';
+}
diff --git a/src/Impact/Embodied/Internal/Computer.php b/src/Impact/Embodied/Internal/Computer.php
new file mode 100644
index 00000000..0c96194c
--- /dev/null
+++ b/src/Impact/Embodied/Internal/Computer.php
@@ -0,0 +1,100 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Impact\Embodied\Internal;
+
+use CommonDBTM;
+use Computer as GlpiComputer;
+use GlpiPlugin\Carbon\DataTracking\TrackedFloat;
+use ComputerModel as GlpiComputerModel;
+use GlpiPlugin\Carbon\Impact\Type;
+
+/**
+ * This embodied impact
+ */
+class Computer extends AbstractAsset
+{
+ protected static string $itemtype = GlpiComputer::class;
+
+ protected function doEvaluation(CommonDBTM $item): ?array
+ {
+ if (GlpiComputerModel::isNewID($item->fields['networkequipmentmodels_id'])) {
+ return [];
+ }
+
+ $model = new GlpiComputerModel();
+ $model->getFromDBByCrit([
+ 'networkequipmentmodels_id' => $item->fields['networkequipmentmodels_id']
+ ]);
+ if ($model->isNewItem()) {
+ return [];
+ }
+
+ $impacts = [];
+ $types = Type::getImpactTypes();
+ foreach ($types as $type) {
+ switch ($type) {
+ case 'gwp':
+ if (!empty($model->fields['gwp'])) {
+ $impacts[Type::IMPACT_GWP] = new TrackedFloat(
+ $model->fields['gwp'] * 1000, // UI Field in KgCO2Eq,
+ null,
+ $model->fields['gwp_quality']
+ );
+ }
+ break;
+
+ case 'adp':
+ if (!empty($model->fields['adp'])) {
+ $impacts[Type::IMPACT_ADP] = new TrackedFloat(
+ $model->fields['adp'],
+ null,
+ $model->fields['adp_quality']
+ );
+ }
+ break;
+
+ case 'pe':
+ if (!empty($model->fields['pe'])) {
+ $impacts[Type::IMPACT_PE] = new TrackedFloat(
+ $model->fields['pe'],
+ null,
+ $model->fields['pe_quality']
+ );
+ }
+ break;
+ }
+ }
+
+ return $impacts;
+ }
+}
diff --git a/src/Impact/Embodied/Internal/Monitor.php b/src/Impact/Embodied/Internal/Monitor.php
new file mode 100644
index 00000000..caac7f6a
--- /dev/null
+++ b/src/Impact/Embodied/Internal/Monitor.php
@@ -0,0 +1,100 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Impact\Embodied\Internal;
+
+use CommonDBTM;
+use Monitor as GlpiMonitor;
+use GlpiPlugin\Carbon\DataTracking\TrackedFloat;
+use MonitorModel as GlpiMonitorModel;
+use GlpiPlugin\Carbon\Impact\Type;
+
+/**
+ * This embodied impact
+ */
+class Monitor extends AbstractAsset
+{
+ protected static string $itemtype = GlpiMonitor::class;
+
+ protected function doEvaluation(CommonDBTM $item): ?array
+ {
+ if (GlpiMonitorModel::isNewID($item->fields['networkequipmentmodels_id'])) {
+ return [];
+ }
+
+ $model = new GlpiMonitorModel();
+ $model->getFromDBByCrit([
+ 'networkequipmentmodels_id' => $item->fields['networkequipmentmodels_id']
+ ]);
+ if ($model->isNewItem()) {
+ return [];
+ }
+
+ $impacts = [];
+ $types = Type::getImpactTypes();
+ foreach ($types as $type) {
+ switch ($type) {
+ case 'gwp':
+ if (!empty($model->fields['gwp'])) {
+ $impacts[Type::IMPACT_GWP] = new TrackedFloat(
+ $model->fields['gwp'] * 1000, // UI Field in KgCO2Eq
+ null,
+ $model->fields['gwp_quality']
+ );
+ }
+ break;
+
+ case 'adp':
+ if (!empty($model->fields['adp'])) {
+ $impacts[Type::IMPACT_ADP] = new TrackedFloat(
+ $model->fields['adp'],
+ null,
+ $model->fields['adp_quality']
+ );
+ }
+ break;
+
+ case 'pe':
+ if (!empty($model->fields['pe'])) {
+ $impacts[Type::IMPACT_PE] = new TrackedFloat(
+ $model->fields['pe'],
+ null,
+ $model->fields['pe_quality']
+ );
+ }
+ break;
+ }
+ }
+
+ return $impacts;
+ }
+}
diff --git a/src/Impact/Embodied/Internal/NetworkEquipment.php b/src/Impact/Embodied/Internal/NetworkEquipment.php
new file mode 100644
index 00000000..59b6904a
--- /dev/null
+++ b/src/Impact/Embodied/Internal/NetworkEquipment.php
@@ -0,0 +1,101 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Impact\Embodied\Internal;
+
+use CommonDBTM;
+use GlpiPlugin\Carbon\DataTracking\TrackedFloat;
+use NetworkEquipment as GlpiNetworkEquipment;
+use NetworkEquipmentModel as GlpiNetworkEquipmentModel;
+use GlpiPlugin\Carbon\Impact\Type;
+use GlpiPlugin\Carbon\NetworkEquipmentModel;
+
+/**
+ * This embodied impact
+ */
+class NetworkEquipment extends AbstractAsset
+{
+ protected static string $itemtype = GlpiNetworkEquipment::class;
+
+ protected function doEvaluation(CommonDBTM $item): ?array
+ {
+ if (GlpiNetworkEquipmentModel::isNewID($item->fields['networkequipmentmodels_id'])) {
+ return [];
+ }
+
+ $model = new NetworkEquipmentModel();
+ $success = $model->getFromDBByCrit([
+ 'networkequipmentmodels_id' => $item->fields['networkequipmentmodels_id']
+ ]);
+ if ($success === false) {
+ return [];
+ }
+
+ $impacts = [];
+ $types = Type::getImpactTypes();
+ foreach ($types as $type) {
+ switch ($type) {
+ case 'gwp':
+ if (!empty($model->fields['gwp'])) {
+ $impacts[Type::IMPACT_GWP] = new TrackedFloat(
+ $model->fields['gwp'] * 1000, // UI Field in KgCO2Eq
+ null,
+ $model->fields['gwp_quality']
+ );
+ }
+ break;
+
+ case 'adp':
+ if (!empty($model->fields['adp'])) {
+ $impacts[Type::IMPACT_ADP] = new TrackedFloat(
+ $model->fields['adp'],
+ null,
+ $model->fields['adp_quality']
+ );
+ }
+ break;
+
+ case 'pe':
+ if (!empty($model->fields['pe'])) {
+ $impacts[Type::IMPACT_PE] = new TrackedFloat(
+ $model->fields['pe'],
+ null,
+ $model->fields['pe_quality']
+ );
+ }
+ break;
+ }
+ }
+
+ return $impacts;
+ }
+}
diff --git a/src/Impact/Usage/Engine.php b/src/Impact/Usage/Engine.php
index b0429722..3b52d110 100644
--- a/src/Impact/Usage/Engine.php
+++ b/src/Impact/Usage/Engine.php
@@ -36,6 +36,7 @@
use GlpiPlugin\Carbon\Config;
use GlpiPlugin\Carbon\DataSource\Boaviztapi;
use GlpiPlugin\Carbon\DataSource\RestApiClient;
+use GlpiPlugin\Carbon\DataSource\RestApiClientInterface;
class Engine extends CommonGLPI
{
@@ -55,9 +56,10 @@ public static function getAvailableBackends(): array
* Returns null if no engine found
*
* @param string $itemtype itemtype of assets to analyze
+ * @param ?RestApiClientInterface $client
* @return AbstractUsageImpact|null an instance if an embodied impact calculation object or null on error
*/
- public static function getEngineFromItemtype(string $itemtype): ?AbstractUsageImpact
+ public static function getEngineFromItemtype(string $itemtype, ?RestApiClientInterface $client = null): ?AbstractUsageImpact
{
$usage_impact_namespace = Config::getUsageImpactEngine();
$usage_impact_class = $usage_impact_namespace . '\\' . $itemtype;
@@ -68,23 +70,7 @@ public static function getEngineFromItemtype(string $itemtype): ?AbstractUsageIm
/** @var AbstractUsageImpact $usage_impact */
$usage_impact = new $usage_impact_class();
try {
- return self::configureEngine($usage_impact);
- } catch (\RuntimeException $e) {
- return null;
- }
- }
-
- public static function getEngine(string $engine_class): ?AbstractUsageImpact
- {
- if (!is_subclass_of($engine_class, AbstractUsageImpact::class)) {
- return null;
- }
-
- /** @var AbstractUsageImpact $usage_impact */
- $usage_impact = new $engine_class();
-
- try {
- return self::configureEngine($usage_impact);
+ return self::configureEngine($usage_impact, $client);
} catch (\RuntimeException $e) {
return null;
}
@@ -94,15 +80,16 @@ public static function getEngine(string $engine_class): ?AbstractUsageImpact
* Configure the engine depending on its specificities
*
* @param AbstractUsageImpact $engine the engine to configure
+ * @param ?RestApiClientInterface $client
* @return AbstractUsageImpact the configured engine
*/
- protected static function configureEngine(AbstractUsageImpact $engine): AbstractUsageImpact
+ protected static function configureEngine(AbstractUsageImpact $engine, ?RestApiClientInterface $client = null): AbstractUsageImpact
{
$embodied_impact_namespace = explode('\\', get_class($engine));
switch (array_slice($embodied_impact_namespace, -2, 1)[0]) {
case 'Boavizta':
/** @var Boavizta\AbstractAsset $engine */
- $engine->setClient(new Boaviztapi(new RestApiClient()));
+ $engine->setClient(new Boaviztapi($client));
}
return $engine;
diff --git a/src/MonitorModel.php b/src/MonitorModel.php
new file mode 100644
index 00000000..d929e3d2
--- /dev/null
+++ b/src/MonitorModel.php
@@ -0,0 +1,41 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon;
+
+use MonitorModel as GlpiMonitorModel;
+
+class MonitorModel extends AbstractModel
+{
+ public static $itemtype = GlpiMonitorModel::class;
+ public static $items_id = 'monitormodels_id';
+}
diff --git a/src/NetworkEquipmentModel.php b/src/NetworkEquipmentModel.php
new file mode 100644
index 00000000..70bde975
--- /dev/null
+++ b/src/NetworkEquipmentModel.php
@@ -0,0 +1,41 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon;
+
+use NetworkEquipmentModel as GlpiNetworkEquipmentModel;
+
+class NetworkEquipmentModel extends AbstractModel
+{
+ public static $itemtype = GlpiNetworkEquipmentModel::class;
+ public static $items_id = 'networkequipmentmodels_id';
+}
diff --git a/src/NetworkEquipmentType.php b/src/NetworkEquipmentType.php
index e6021180..2d9bf942 100644
--- a/src/NetworkEquipmentType.php
+++ b/src/NetworkEquipmentType.php
@@ -57,7 +57,6 @@ public static function showMassiveActionsSubForm(MassiveAction $ma)
return parent::showMassiveActionsSubForm($ma);
}
-
public static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $item, array $ids)
{
switch ($ma->getAction()) {
diff --git a/templates/components/form/fields_macros.html.twig b/templates/components/form/fields_macros.html.twig
index fb7953e3..10cf5d2e 100644
--- a/templates/components/form/fields_macros.html.twig
+++ b/templates/components/form/fields_macros.html.twig
@@ -97,3 +97,38 @@
{{ fields.field(name, field, label, options|merge({'id': 'dropdown_' ~ name ~ '_' ~ options.rand})) }}
{% endif %}
{% endmacro %}
+
+{% macro dropdownDataQuaity(name, value, label = '', options = {}) %}
+ {% import 'components/form/fields_macros.html.twig' as fields %}
+
+ {% if options.multiple ?? false %}
+ {# Needed for empty value as the input wont be sent in this case... we need something to know the input was displayed AND empty #}
+ {% set defined_input_name = "_#{name}_defined" %}
+
+
+ {# Multiple values will be set, input need to be an array #}
+ {% set name = "#{name}[]" %}
+ {% endif %}
+ {% set options = {
+ 'rand': random(),
+ 'disabled': false,
+ }|merge(options) %}
+ {% if options.fields_template.isMandatoryField(name)|default(false) %}
+ {% set options = {'specific_tags': {'required': true}}|merge(options) %}
+ {% endif %}
+
+ {% if options.disabled %}
+ {% set options = options|merge({specific_tags: {'disabled': 'disabled'}}) %}
+ {% endif %}
+
+ {% set field %}
+ {% do call('GlpiPlugin\\Carbon\\DataTracking\\TrackedInt::dropdownQuality', [name, {
+ 'value': value,
+ 'rand': options.rand,
+ 'width': '100%',
+ }|merge(options)]) %}
+ {% endset %}
+ {% if field|trim is not empty %}
+ {{ fields.field(name, field, label, options|merge({'id': 'dropdown_' ~ name ~ '_' ~ options.rand})) }}
+ {% endif %}
+{% endmacro %}
diff --git a/templates/computermodel.html.twig b/templates/computermodel.html.twig
new file mode 100644
index 00000000..23272f79
--- /dev/null
+++ b/templates/computermodel.html.twig
@@ -0,0 +1,60 @@
+{#
+ # -------------------------------------------------------------------------
+ # Carbon plugin for GLPI
+ #
+ # @copyright Copyright (C) 2024-2025 Teclib' and contributors.
+ # @license https://www.gnu.org/licenses/gpl-3.0.txt GPLv3+
+ # @license MIT https://opensource.org/licenses/mit-license.php
+ # @link https://github.com/pluginsGLPI/carbon
+ #
+ # -------------------------------------------------------------------------
+ #
+ # LICENSE
+ #
+ # This file is part of Carbon plugin for GLPI.
+ #
+ # This program is free software: you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation, either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program. If not, see .
+ #
+ # -------------------------------------------------------------------------
+ #}
+
+{% extends "generic_show_form.html.twig" %}
+{% import "components/form/fields_macros.html.twig" as fields %}
+{% import "@carbon/components/form/fields_macros.html.twig" as carbonFields %}
+
+{% block form_fields %}
+ {% for key, field_description in criterias %}
+ {% set criteria = key %}
+ {% set criteria_source = key ~ '_source' %}
+ {% set criteria_quality = key ~ '_quality' %}
+
+ {{ fields.smallTitle(field_description.title) }}
+
+ {{ fields.numberField(criteria,
+ item.fields[criteria],
+ field_description.label, {
+ min: 0
+ }) }}
+
+ {{ fields.textfield(criteria_source,
+ item.fields[criteria_source],
+ __('Data source', 'carbon'), {}) }}
+
+ {{ carbonFields.dropdownDataQuaity(criteria_quality,
+ item.fields[criteria_quality],
+ __('Data quality', 'carbon'), {
+ min: 0
+ }) }}
+ {% endfor %}
+{% endblock %}
diff --git a/templates/monitormodel.html.twig b/templates/monitormodel.html.twig
new file mode 100644
index 00000000..272e794c
--- /dev/null
+++ b/templates/monitormodel.html.twig
@@ -0,0 +1,60 @@
+{#
+ # -------------------------------------------------------------------------
+ # Carbon plugin for GLPI
+ #
+ # @copyright Copyright (C) 2024-2025 Teclib' and contributors.
+ # @license https://www.gnu.org/licenses/gpl-3.0.txt GPLv3+
+ # @license MIT https://opensource.org/licenses/mit-license.php
+ # @link https://github.com/pluginsGLPI/carbon
+ #
+ # -------------------------------------------------------------------------
+ #
+ # LICENSE
+ #
+ # This file is part of Carbon plugin for GLPI.
+ #
+ # This program is free software: you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation, either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program. If not, see .
+ #
+ # -------------------------------------------------------------------------
+ #}
+
+{% extends "generic_show_form.html.twig" %}
+{% import "components/form/fields_macros.html.twig" as fields %}
+{% import "@carbon/components/form/fields_macros.html.twig" as carbonFields %}
+
+{% block form_fields %}
+ {% for key, field_description in criterias %}
+ {% set criteria = key %}
+ {% set criteria_source = key ~ '_source' %}
+ {% set criteria_quality = key ~ '_quality' %}
+
+ {{ fields.smallTitle(field_description.title, field_description.icon) }}
+
+ {{ fields.numberField(criteria,
+ item.fields[criteria],
+ field_description.label, {
+ min: 0
+ }) }}
+
+ {{ fields.textfield(criteria_source,
+ item.fields[criteria_source],
+ __('Data source', 'carbon'), {}) }}
+
+ {{ carbonFields.dropdownDataQuaity(criteria_quality,
+ item.fields[criteria_quality],
+ __('Data quality', 'carbon'), {
+ min: 0
+ }) }}
+ {% endfor %}
+{% endblock %}
diff --git a/templates/networkequipmentmodel.html.twig b/templates/networkequipmentmodel.html.twig
new file mode 100644
index 00000000..23272f79
--- /dev/null
+++ b/templates/networkequipmentmodel.html.twig
@@ -0,0 +1,60 @@
+{#
+ # -------------------------------------------------------------------------
+ # Carbon plugin for GLPI
+ #
+ # @copyright Copyright (C) 2024-2025 Teclib' and contributors.
+ # @license https://www.gnu.org/licenses/gpl-3.0.txt GPLv3+
+ # @license MIT https://opensource.org/licenses/mit-license.php
+ # @link https://github.com/pluginsGLPI/carbon
+ #
+ # -------------------------------------------------------------------------
+ #
+ # LICENSE
+ #
+ # This file is part of Carbon plugin for GLPI.
+ #
+ # This program is free software: you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation, either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program. If not, see .
+ #
+ # -------------------------------------------------------------------------
+ #}
+
+{% extends "generic_show_form.html.twig" %}
+{% import "components/form/fields_macros.html.twig" as fields %}
+{% import "@carbon/components/form/fields_macros.html.twig" as carbonFields %}
+
+{% block form_fields %}
+ {% for key, field_description in criterias %}
+ {% set criteria = key %}
+ {% set criteria_source = key ~ '_source' %}
+ {% set criteria_quality = key ~ '_quality' %}
+
+ {{ fields.smallTitle(field_description.title) }}
+
+ {{ fields.numberField(criteria,
+ item.fields[criteria],
+ field_description.label, {
+ min: 0
+ }) }}
+
+ {{ fields.textfield(criteria_source,
+ item.fields[criteria_source],
+ __('Data source', 'carbon'), {}) }}
+
+ {{ carbonFields.dropdownDataQuaity(criteria_quality,
+ item.fields[criteria_quality],
+ __('Data quality', 'carbon'), {
+ min: 0
+ }) }}
+ {% endfor %}
+{% endblock %}
diff --git a/tests/install/PluginInstallTest.php b/tests/install/PluginInstallTest.php
index b364c45f..3ba3f42f 100644
--- a/tests/install/PluginInstallTest.php
+++ b/tests/install/PluginInstallTest.php
@@ -32,6 +32,10 @@
namespace GlpiPlugin\Carbon\Tests;
+use CommonGLPI;
+use Computer;
+use ComputerModel;
+use ComputerType;
use Session;
use Config;
use CronTask as GLPICronTask;
@@ -49,14 +53,19 @@
use Glpi\Plugin\Hooks;
use Glpi\System\Diagnostic\DatabaseSchemaIntegrityChecker;
use GlpiPlugin\Carbon\CarbonIntensity;
-use GlpiPlugin\Carbon\CarbonIntensitySource;
-use GlpiPlugin\Carbon\CarbonIntensitySource_Zone;
use GlpiPlugin\Carbon\Source;
use GlpiPlugin\Carbon\Source_Zone;
use GlpiPlugin\Carbon\Zone;
use GlpiPlugin\Carbon\ComputerUsageProfile;
use GlpiPlugin\Carbon\CronTask;
use GlpiPlugin\Carbon\Report;
+use Location;
+use Monitor;
+use MonitorModel;
+use MonitorType;
+use NetworkEquipment;
+use NetworkEquipmentModel;
+use NetworkEquipmentType;
class PluginInstallTest extends CommonTestCase
{
@@ -137,6 +146,7 @@ public function testInstallPlugin()
$this->checkDisplayPrefs();
$this->checkPredefinedUsageProfiles();
$this->checkSourceZoneRelation();
+ $this->checkRegisteredClasses();
}
public function testConfigurationExists()
@@ -842,4 +852,55 @@ public function checkSourceZoneRelation()
]);
$this->assertEquals(1, $iterator->count());
}
+
+ public function checkRegisteredClasses()
+ {
+ $result = CommonGLPI::getOtherTabs(Config::class);
+ $expected = ['GlpiPlugin\Carbon\Config'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(Profile::class);
+ $expected = ['GlpiPlugin\Carbon\Profile'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(Location::class);
+ $expected = ['GlpiPlugin\Carbon\Location'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(Computer::class);
+ $expected = ['GlpiPlugin\Carbon\UsageInfo'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(Monitor::class);
+ $expected = ['GlpiPlugin\Carbon\UsageInfo'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(NetworkEquipment::class);
+ $expected = ['GlpiPlugin\Carbon\UsageInfo'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(ComputerType::class);
+ $expected = ['GlpiPlugin\Carbon\ComputerType'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(MonitorType::class);
+ $expected = ['GlpiPlugin\Carbon\MonitorType'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(NetworkEquipmentType::class);
+ $expected = ['GlpiPlugin\Carbon\NetworkEquipmentType'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(ComputerModel::class);
+ $expected = ['GlpiPlugin\Carbon\ComputerModel'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(MonitorModel::class);
+ $expected = ['GlpiPlugin\Carbon\MonitorModel'];
+ $this->assertEquals($expected, $result);
+
+ $result = CommonGLPI::getOtherTabs(NetworkEquipmentModel::class);
+ $expected = ['GlpiPlugin\Carbon\NetworkEquipmentModel'];
+ $this->assertEquals($expected, $result);
+ }
}
diff --git a/tests/integration/SearchOptionTest.php b/tests/integration/SearchOptionTest.php
index b5918e05..d77fff51 100644
--- a/tests/integration/SearchOptionTest.php
+++ b/tests/integration/SearchOptionTest.php
@@ -47,6 +47,9 @@
use CommonGLPI;
use DBmysql;
use DbUtils;
+use GlpiPlugin\Carbon\ComputerModel;
+use GlpiPlugin\Carbon\MonitorModel;
+use GlpiPlugin\Carbon\NetworkEquipmentModel;
use Plugin;
use PHPUnit\Framework\Attributes\CoversMethod;
@@ -68,6 +71,7 @@ class SearchOptionTest extends CommonTestCase
],
ComputerType::class => [],
MonitorType::class => [],
+ NetworkEquipmentType::class => [],
UsageInfo::class => [],
CarbonIntensity::class => [
'data_quality'
@@ -77,11 +81,13 @@ class SearchOptionTest extends CommonTestCase
'adp_quality',
'pe_quality',
],
- NetworkEquipmentType::class => [],
Location::class => [],
Zone::class => [
'entities_id',
],
+ ComputerModel::class => [],
+ MonitorModel::class => [],
+ NetworkEquipmentModel::class => [],
];
private array $mapping = [
diff --git a/tests/units/ComputerModelTest.php b/tests/units/ComputerModelTest.php
new file mode 100644
index 00000000..3535c547
--- /dev/null
+++ b/tests/units/ComputerModelTest.php
@@ -0,0 +1,69 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Tests;
+
+use ComputerModel as GlpiComputerModel;
+use GlpiPlugin\Carbon\ComputerModel;
+use Symfony\Component\DomCrawler\Crawler;
+
+class ComputerModelTest extends DbTestCase
+{
+ /**
+ * #CoversMethod GlpiPlugin\Carbon\AbstractType::showForItemType
+ */
+ public function testShowForItemType()
+ {
+ $glpi_computer_model = $this->createItem(GlpiComputerModel::class);
+ $computer_model = $this->createItem(ComputerModel::class, [
+ 'computermodels_id' => $glpi_computer_model->getID(),
+ ]);
+ $this->login('glpi', 'glpi');
+ ob_start();
+ $computer_model->showForItemType($glpi_computer_model);
+ $output = ob_get_clean();
+ $crawler = new Crawler($output);
+ $gwp = $crawler->filter('input[name="gwp"]');
+ $this->assertEquals(1, $gwp->count());
+ $gwp->each(function (Crawler $node) {
+ $this->assertEquals(0, $node->attr('value'));
+ $this->assertEquals('number', $node->attr('type'));
+ });
+
+ $gwp_source = $crawler->filter('input[name="gwp_source"]');
+ $gwp_source->each(function (Crawler $node) {
+ $this->assertEquals('', $node->attr('value'));
+ });
+
+ $gwp_quality = $crawler->filter('select[name="gwp_quality"]');
+ }
+}
diff --git a/tests/units/ComputerTypeTest.php b/tests/units/ComputerTypeTest.php
index 8941cd8e..58635176 100644
--- a/tests/units/ComputerTypeTest.php
+++ b/tests/units/ComputerTypeTest.php
@@ -43,8 +43,8 @@ class ComputerTypeTest extends DbTestCase
{
public function testGetTypeName()
{
- $this->assertEquals('Power', ComputerType::getTypeName(1));
- $this->assertEquals('Powers', ComputerType::getTypeName(Session::getPluralNumber()));
+ $this->assertEquals('Environmental impact', ComputerType::getTypeName(1));
+ $this->assertEquals('Environmental impacts', ComputerType::getTypeName(Session::getPluralNumber()));
}
public function testGetTabNameForItem()
diff --git a/tests/units/Impact/Embodied/EngineTest.php b/tests/units/Impact/Embodied/EngineTest.php
new file mode 100644
index 00000000..23699565
--- /dev/null
+++ b/tests/units/Impact/Embodied/EngineTest.php
@@ -0,0 +1,73 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Impact\Embodied\Tests;
+
+use Computer as GlpiComputer;
+use Monitor as GlpiMonitor;
+use NetworkEquipment as GlpiNetworkEquipment;
+use Config as GlpiConfig;
+use GlpiPlugin\Carbon\DataSource\RestApiClient;
+use GlpiPlugin\Carbon\Tests\DbTestCase;
+use GlpiPlugin\Carbon\Impact\Embodied\Boavizta\Computer;
+use GlpiPlugin\Carbon\Impact\Embodied\Boavizta\Monitor;
+use GlpiPlugin\Carbon\Impact\Embodied\Internal\NetworkEquipment;
+use GlpiPlugin\Carbon\Impact\Embodied\Engine;
+
+class EngineTest extends DbTestCase
+{
+ public function testGetEngineFromItemtypeForBoavizta()
+ {
+ GlpiConfig::setConfigurationValues('plugin:carbon', [
+ 'boaviztapi_base_url' => 'http://localhost:5000'
+ ]);
+ $version_response = [
+ '1.3.11',
+ ];
+ $client_stub = $this->getMockBuilder(RestApiClient::class)
+ ->getMock();
+ $client_stub->method('request')->willReturn($version_response);
+
+ $itemtype = GlpiComputer::class;
+ $result = Engine::getEngineFromItemtype($itemtype, $client_stub);
+ $this->assertTrue($result instanceof Computer);
+
+ $itemtype = GlpiMonitor::class;
+ $result = Engine::getEngineFromItemtype($itemtype, $client_stub);
+ $this->assertTrue($result instanceof Monitor);
+
+ // This case returns internal embodied impact engine, as Boavizta does not provide data
+ $itemtype = GlpiNetworkEquipment::class;
+ $result = Engine::getEngineFromItemtype($itemtype, $client_stub);
+ $this->assertTrue($result instanceof NetworkEquipment);
+ }
+}
diff --git a/tests/units/Impact/Usage/EngineTest.php b/tests/units/Impact/Usage/EngineTest.php
new file mode 100644
index 00000000..6c8eb7e1
--- /dev/null
+++ b/tests/units/Impact/Usage/EngineTest.php
@@ -0,0 +1,72 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Impact\Usage\Tests;
+
+use Computer as GlpiComputer;
+use Monitor as GlpiMonitor;
+use NetworkEquipment as GlpiNetworkEquipment;
+use Config as GlpiConfig;
+use GlpiPlugin\Carbon\DataSource\RestApiClient;
+use GlpiPlugin\Carbon\Tests\DbTestCase;
+use GlpiPlugin\Carbon\Impact\Usage\Boavizta\Computer;
+use GlpiPlugin\Carbon\Impact\Usage\Boavizta\Monitor;
+use GlpiPlugin\Carbon\Impact\Usage\Engine;
+
+class EngineTest extends DbTestCase
+{
+ public function testGetEngineFromItemtypeForBoavizta()
+ {
+ GlpiConfig::setConfigurationValues('plugin:carbon', [
+ 'boaviztapi_base_url' => 'http://localhost:5000'
+ ]);
+ $version_response = [
+ '1.3.11',
+ ];
+ $client_stub = $this->getMockBuilder(RestApiClient::class)
+ ->getMock();
+ $client_stub->method('request')->willReturn($version_response);
+
+ $itemtype = GlpiComputer::class;
+ $result = Engine::getEngineFromItemtype($itemtype, $client_stub);
+ $this->assertTrue($result instanceof Computer);
+
+ $itemtype = GlpiMonitor::class;
+ $result = Engine::getEngineFromItemtype($itemtype, $client_stub);
+ $this->assertTrue($result instanceof Monitor);
+
+ // This case returns null, as Boavizta does not provide data
+ $itemtype = GlpiNetworkEquipment::class;
+ $result = Engine::getEngineFromItemtype($itemtype, $client_stub);
+ $this->assertNull($result);
+ }
+}
diff --git a/tests/units/MonitorModelTest.php b/tests/units/MonitorModelTest.php
new file mode 100644
index 00000000..0390417e
--- /dev/null
+++ b/tests/units/MonitorModelTest.php
@@ -0,0 +1,69 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Tests;
+
+use MonitorModel as GlpiMonitorModel;
+use GlpiPlugin\Carbon\MonitorModel;
+use Symfony\Component\DomCrawler\Crawler;
+
+class MonitorModelTest extends DbTestCase
+{
+ /**
+ * #CoversMethod GlpiPlugin\Carbon\AbstractType::showForItemType
+ */
+ public function testShowForItemType()
+ {
+ $glpi_monitor_model = $this->createItem(GlpiMonitorModel::class);
+ $monitor_model = $this->createItem(MonitorModel::class, [
+ 'monitormodels_id' => $glpi_monitor_model->getID(),
+ ]);
+ $this->login('glpi', 'glpi');
+ ob_start();
+ $monitor_model->showForItemType($glpi_monitor_model);
+ $output = ob_get_clean();
+ $crawler = new Crawler($output);
+ $gwp = $crawler->filter('input[name="gwp"]');
+ $this->assertEquals(1, $gwp->count());
+ $gwp->each(function (Crawler $node) {
+ $this->assertEquals(0, $node->attr('value'));
+ $this->assertEquals('number', $node->attr('type'));
+ });
+
+ $gwp_source = $crawler->filter('input[name="gwp_source"]');
+ $gwp_source->each(function (Crawler $node) {
+ $this->assertEquals('', $node->attr('value'));
+ });
+
+ $gwp_quality = $crawler->filter('select[name="gwp_quality"]');
+ }
+}
diff --git a/tests/units/MonitorTypeTest.php b/tests/units/MonitorTypeTest.php
index 9ef57c9b..c9727a95 100644
--- a/tests/units/MonitorTypeTest.php
+++ b/tests/units/MonitorTypeTest.php
@@ -45,8 +45,8 @@ class MonitorTypeTest extends DbTestCase
{
public function testGetTypeName()
{
- $this->assertEquals('Power', MonitorType::getTypeName(1));
- $this->assertEquals('Powers', MonitorType::getTypeName(Session::getPluralNumber()));
+ $this->assertEquals('Environmental impact', MonitorType::getTypeName(1));
+ $this->assertEquals('Environmental impacts', MonitorType::getTypeName(Session::getPluralNumber()));
}
public function testGetTabNameForItem()
diff --git a/tests/units/NetworkEquipmentModelTest.php b/tests/units/NetworkEquipmentModelTest.php
new file mode 100644
index 00000000..dc90e319
--- /dev/null
+++ b/tests/units/NetworkEquipmentModelTest.php
@@ -0,0 +1,69 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon\Tests;
+
+use NetworkEquipmentModel as GlpiNetworkEquipmentModel;
+use GlpiPlugin\Carbon\NetworkEquipmentModel;
+use Symfony\Component\DomCrawler\Crawler;
+
+class NetworkEquipmentModelTest extends DbTestCase
+{
+ /**
+ * #CoversMethod GlpiPlugin\Carbon\AbstractType::showForItemType
+ */
+ public function testShowForItemType()
+ {
+ $glpi_networkequipment_model = $this->createItem(GlpiNetworkEquipmentModel::class);
+ $networkequipment_model = $this->createItem(NetworkEquipmentModel::class, [
+ 'networkequipmentmodels_id' => $glpi_networkequipment_model->getID(),
+ ]);
+ $this->login('glpi', 'glpi');
+ ob_start();
+ $networkequipment_model->showForItemType($glpi_networkequipment_model);
+ $output = ob_get_clean();
+ $crawler = new Crawler($output);
+ $gwp = $crawler->filter('input[name="gwp"]');
+ $this->assertEquals(1, $gwp->count());
+ $gwp->each(function (Crawler $node) {
+ $this->assertEquals(0, $node->attr('value'));
+ $this->assertEquals('number', $node->attr('type'));
+ });
+
+ $gwp_source = $crawler->filter('input[name="gwp_source"]');
+ $gwp_source->each(function (Crawler $node) {
+ $this->assertEquals('', $node->attr('value'));
+ });
+
+ $gwp_quality = $crawler->filter('select[name="gwp_quality"]');
+ }
+}
diff --git a/tests/units/NetworkEquipmentTypeTest.php b/tests/units/NetworkEquipmentTypeTest.php
index db334e17..4eb19426 100644
--- a/tests/units/NetworkEquipmentTypeTest.php
+++ b/tests/units/NetworkEquipmentTypeTest.php
@@ -36,7 +36,6 @@
use MassiveAction;
use NetworkEquipmentType as GlpiNetworkEquipmentType;
use PHPUnit\Framework\Attributes\CoversClass;
-use PHPUnit\Framework\Attributes\CoversMethod;
use Session;
use Symfony\Component\DomCrawler\Crawler;
@@ -46,8 +45,8 @@ class NetworkEquipmentTypeTest extends DbTestCase
{
public function testGetTypeName()
{
- $this->assertEquals('Power', NetworkEquipmentType::getTypeName(1));
- $this->assertEquals('Powers', NetworkEquipmentType::getTypeName(Session::getPluralNumber()));
+ $this->assertEquals('Environmental impact', NetworkEquipmentType::getTypeName(1));
+ $this->assertEquals('Environmental impacts', NetworkEquipmentType::getTypeName(Session::getPluralNumber()));
}
public function testGetTabNameForItem()