diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 16370820b8..9f751ebeee 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -20,7 +20,7 @@ jobs: name: "Generate CI matrix" uses: "glpi-project/plugin-ci-workflows/.github/workflows/generate-ci-matrix.yml@v1" with: - glpi-version: "11.0.x" + glpi-version: "12.0.x" ci: name: "GLPI ${{ matrix.glpi-version }} - php:${{ matrix.php-version }} - ${{ matrix.db-image }}" needs: "generate-ci-matrix" diff --git a/.gitignore b/.gitignore index 044ece9716..8b75e501cf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ vendor/ .gh_token *.min.* var/ +.phpunit.result.cache \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ee8a97de3..5a04aea38e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [UNRELEASED] +## [unreleased] + +### Added + +- GLPI 12 compatibility ### Fixed diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..ef1bed5ac8 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +include ../../PluginsMakefile.mk diff --git a/ajax/billactions.php b/ajax/billactions.php index 1287c21992..225d2960c2 100644 --- a/ajax/billactions.php +++ b/ajax/billactions.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -Session::checkRight("plugin_order_bill", READ); +Session::checkRight(PluginOrderBill::$rightname, READ); header("Content-Type: text/html; charset=UTF-8"); diff --git a/ajax/dropdownReference.php b/ajax/dropdownReference.php index 33595b0aff..f68164d7d7 100644 --- a/ajax/dropdownReference.php +++ b/ajax/dropdownReference.php @@ -31,9 +31,7 @@ /** @var DBmysql $DB */ global $DB; -include_once(__DIR__ . "/../../../inc/includes.php"); - -Session::checkRight("plugin_order_reference", READ); +Session::checkRight(PluginOrderReference::$rightname, READ); // Make a select box for references if (isset($_POST["itemtype"])) { diff --git a/ajax/dropdownSupplier.php b/ajax/dropdownSupplier.php index 43d524dc40..2b142d7507 100644 --- a/ajax/dropdownSupplier.php +++ b/ajax/dropdownSupplier.php @@ -35,7 +35,7 @@ Html::header_nocache(); } -Session::checkRight("contact_enterprise", READ); +Session::checkRight(Contact::$rightname, READ); // Make a select box if (isset($_POST["suppliers_id"])) { diff --git a/composer.json b/composer.json index 263a787aae..36ee69f733 100644 --- a/composer.json +++ b/composer.json @@ -4,9 +4,6 @@ "php": ">=8.2", "sboden/odtphp": "^3.2" }, - "require-dev": { - "glpi-project/tools": "^0.8" - }, "config": { "optimize-autoloader": true, "platform": { @@ -20,6 +17,11 @@ "url": "https://github.com/teclib/odtphp/" } ], + "autoload": { + "psr-4": { + "GlpiPlugin\\Order\\Tests\\": "tests" + } + }, "autoload-dev": { "psr-4": { "Glpi\\Tools\\": "../../tools/src/" diff --git a/composer.lock b/composer.lock index 7295f72ee9..62c91af32c 100644 --- a/composer.lock +++ b/composer.lock @@ -173,16 +173,16 @@ }, { "name": "symfony/console", - "version": "v6.4.43", + "version": "v6.4.45", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3b643aa587acbc42f967a429af088a56ed8f046d" + "reference": "3b8473e0d14157f2d22b0a0d7259ad23483d1e6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3b643aa587acbc42f967a429af088a56ed8f046d", - "reference": "3b643aa587acbc42f967a429af088a56ed8f046d", + "url": "https://api.github.com/repos/symfony/console/zipball/3b8473e0d14157f2d22b0a0d7259ad23483d1e6d", + "reference": "3b8473e0d14157f2d22b0a0d7259ad23483d1e6d", "shasum": "" }, "require": { @@ -247,7 +247,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.43" + "source": "https://github.com/symfony/console/tree/v6.4.45" }, "funding": [ { @@ -267,7 +267,7 @@ "type": "tidelift" } ], - "time": "2026-07-26T14:44:19+00:00" + "time": "2026-08-25T13:08:31+00:00" }, { "name": "symfony/deprecation-contracts", @@ -507,16 +507,16 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.38.0", + "version": "v1.42.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b" + "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b", - "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", "shasum": "" }, "require": { @@ -568,7 +568,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" }, "funding": [ { @@ -588,7 +588,7 @@ "type": "tidelift" } ], - "time": "2026-05-25T13:48:31+00:00" + "time": "2026-08-07T06:33:24+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -677,16 +677,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.7.1", + "version": "v3.7.3", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0" + "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0", - "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/15e6a07ec2a2c75ceb1b21dd98105ee8456d2257", + "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257", "shasum": "" }, "require": { @@ -740,7 +740,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.7.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.3" }, "funding": [ { @@ -760,7 +760,7 @@ "type": "tidelift" } ], - "time": "2026-06-16T09:55:08+00:00" + "time": "2026-07-27T15:39:01+00:00" }, { "name": "symfony/string", @@ -936,15 +936,15 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=8.2" }, - "platform-dev": {}, + "platform-dev": [], "platform-overrides": { "php": "8.2.99" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/front/bill.form.php b/front/bill.form.php index 8bb949881b..fade990cf4 100644 --- a/front/bill.form.php +++ b/front/bill.form.php @@ -93,7 +93,7 @@ Html::back(); } -Session::checkRight("plugin_order_bill", READ); +Session::checkRight(PluginOrderBill::$rightname, READ); Html::header(PluginOrderBill::getTypeName(), $_SERVER['PHP_SELF'], "management", "PluginOrderMenu", "bill"); if (isset($_REQUEST['id'])) { diff --git a/front/bill.php b/front/bill.php index a3b0c2b8cc..813a90c93e 100644 --- a/front/bill.php +++ b/front/bill.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -Session::checkRight("plugin_order_bill", READ); +Session::checkRight(PluginOrderBill::$rightname, READ); Html::header(PluginOrderBill::getTypeName(), $_SERVER['PHP_SELF'], "management", "PluginOrderMenu", "bill"); diff --git a/front/config.form.php b/front/config.form.php index 78faf46627..0607409ba2 100644 --- a/front/config.form.php +++ b/front/config.form.php @@ -40,7 +40,7 @@ } else { Html::header(__s("Orders", "order"), $_SERVER['PHP_SELF'], "management", "PluginOrderMenu", "order"); - Session::checkRight("config", UPDATE); + Session::checkRight(Config::$rightname, UPDATE); $config->showForm(1); Html::footer(); diff --git a/front/order.php b/front/order.php index 8711a2b1aa..0a1eb07b0e 100644 --- a/front/order.php +++ b/front/order.php @@ -42,7 +42,7 @@ "order", ); -if (PluginOrderOrder::canView() || Session::haveRight("config", UPDATE)) { +if (PluginOrderOrder::canView() || Session::haveRight(Config::$rightname, UPDATE)) { Search::show("PluginOrderOrder"); } else { echo "


"plugin_order_orderstates_id", ], "glpi_plugin_order_accountsections" => [ - "glpi_plugin_order_accountsections" => "plugin_order_accountsections_id", + "glpi_plugin_order_orders" => "plugin_order_accountsections_id", ], "glpi_plugin_order_analyticnatures" => [ "glpi_plugin_order_orders_items" => "plugin_order_analyticnatures_id", @@ -237,7 +237,12 @@ function plugin_order_getAddSearchOptions($itemtype) $plugin = new Plugin(); $sopt = []; - if ($plugin->isInstalled('order') && $plugin->isActivated('order') && Session::haveRight("plugin_order_order", READ) && in_array($itemtype, PluginOrderOrder_Item::getClasses(true))) { + if ( + $plugin->isInstalled('order') + && $plugin->isActivated('order') + && Session::haveRight(PluginOrderOrder::$rightname, READ) + && in_array($itemtype, PluginOrderOrder_Item::getClasses(true)) + ) { $sopt[3160]['table'] = 'glpi_plugin_order_orders'; $sopt[3160]['field'] = 'name'; $sopt[3160]['linkfield'] = ''; diff --git a/inc/accountsection.class.php b/inc/accountsection.class.php index dde22de35c..a7c4e74500 100644 --- a/inc/accountsection.class.php +++ b/inc/accountsection.class.php @@ -32,7 +32,7 @@ class PluginOrderAccountsection extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) { diff --git a/inc/analyticnature.class.php b/inc/analyticnature.class.php index 57dec6e214..b991120fa9 100644 --- a/inc/analyticnature.class.php +++ b/inc/analyticnature.class.php @@ -32,7 +32,7 @@ class PluginOrderAnalyticnature extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) { diff --git a/inc/bill.class.php b/inc/bill.class.php index 773f982e62..a1ed70bc0d 100644 --- a/inc/bill.class.php +++ b/inc/bill.class.php @@ -32,9 +32,9 @@ class PluginOrderBill extends CommonDropdown { - public static $rightname = 'plugin_order_bill'; + public static string $rightname = 'plugin_order_bill'; - public $dohistory = true; + public bool $dohistory = true; public $first_level_menu = "plugins"; @@ -641,7 +641,7 @@ public static function uninstall() public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (!$withtemplate) { - switch ($item->getType()) { + switch ($item::class) { case 'PluginOrderOrder': return self::createTabEntry( self::getTypeName(), diff --git a/inc/billstate.class.php b/inc/billstate.class.php index 14b09fa49d..4be48cadff 100644 --- a/inc/billstate.class.php +++ b/inc/billstate.class.php @@ -36,7 +36,7 @@ class PluginOrderBillState extends CommonDropdown public const PAID = 1; - public static $rightname = 'plugin_order_bill'; + public static string $rightname = 'plugin_order_bill'; public static function getTypeName($nb = 0) diff --git a/inc/billtype.class.php b/inc/billtype.class.php index 93dc5f2e62..7a4baf2130 100644 --- a/inc/billtype.class.php +++ b/inc/billtype.class.php @@ -32,7 +32,7 @@ class PluginOrderBillType extends CommonDropdown { - public static $rightname = 'plugin_order_bill'; + public static string $rightname = 'plugin_order_bill'; public static function getTypeName($nb = 0) diff --git a/inc/config.class.php b/inc/config.class.php index 8e170183e9..5e53cfab48 100644 --- a/inc/config.class.php +++ b/inc/config.class.php @@ -32,7 +32,7 @@ class PluginOrderConfig extends CommonDBTM { - public static $rightname = 'config'; + public static string $rightname = 'config'; public const CONFIG_NEVER = 0; @@ -53,13 +53,13 @@ public function __construct() public static function canView(): bool { - return Session::haveRight('config', READ); + return Session::haveRight(Config::$rightname, READ); } public static function canCreate(): bool { - return Session::haveRight('config', UPDATE); + return Session::haveRight(Config::$rightname, UPDATE); } diff --git a/inc/documentcategory.class.php b/inc/documentcategory.class.php index b674ec1150..2e91df91d7 100644 --- a/inc/documentcategory.class.php +++ b/inc/documentcategory.class.php @@ -42,7 +42,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { $config = PluginOrderConfig::getConfig(); - if ($item->getType() == "DocumentCategory" && $config->canRenameDocuments()) { + if ($item::class == "DocumentCategory" && $config->canRenameDocuments()) { return __s("Orders", "order"); } @@ -54,7 +54,7 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $ { $config = PluginOrderConfig::getConfig(); - if ($item->getType() == "DocumentCategory" && $config->canRenameDocuments()) { + if ($item::class == "DocumentCategory" && $config->canRenameDocuments()) { self::showForDocumentCategory($item); } @@ -79,7 +79,7 @@ public static function showForDocumentCategory($item) } echo "
"; + . Toolbox::getItemTypeFormURL($documentCategory::class) . "'>"; echo "
"; echo ""; diff --git a/inc/link.class.php b/inc/link.class.php index e66b6a16d9..69a5efecad 100644 --- a/inc/link.class.php +++ b/inc/link.class.php @@ -33,15 +33,15 @@ class PluginOrderLink extends CommonDBChild { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public $dohistory = true; + public bool $dohistory = true; - public static $itemtype = 'PluginOrderOrder'; + public static string $itemtype = 'PluginOrderOrder'; - public static $items_id = 'plugin_order_orders_id'; + public static string $items_id = 'plugin_order_orders_id'; - public static $checkParentRights = self::DONT_CHECK_ITEM_RIGHTS; + public static int $checkParentRights = self::DONT_CHECK_ITEM_RIGHTS; public static function getTypeName($nb = 0) @@ -625,11 +625,11 @@ public static function processMassiveActionsForOneItemtype( foreach ($ma->getItems()[self::class] as $key => $val) { $itemtype = $ma->POST['add_items'][$key]['itemtype'] ?? ''; if (in_array($itemtype, self::getTypesThanCannotBeGenerated()) && $itemtype !== 'SoftwareLicense') { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_OK); } elseif (isset($newIDs[$key]) && $newIDs[$key]) { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_OK); } else { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_KO); } } @@ -639,7 +639,7 @@ public static function processMassiveActionsForOneItemtype( // For consumables and cartridges, createLinkWithItem creates a new item // (glpi_consumables/glpi_cartridges) for each selected detail line; // therefore, multiple items can be linked to the same reference item at once - $allow_multiple_link = isset($ma->POST['add_items']) && $ma->POST['add_items'] !== [] && array_reduce( + $allow_multiple_link = $ma->POST['add_items'] !== [] && array_reduce( $ma->POST['add_items'], fn($carry, $data) => $carry && in_array( $data['itemtype'] ?? '', @@ -652,7 +652,7 @@ public static function processMassiveActionsForOneItemtype( if (!$allow_multiple_link && count($ids) > 1) { $ma->addMessage(__s("Cannot link several items to one detail line", "order")); foreach ($ids as $id) { - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $id, MassiveAction::ACTION_KO); } break; @@ -663,7 +663,7 @@ public static function processMassiveActionsForOneItemtype( $order_item->getFromDB($val); if ($order_item->fields["states_id"] == PluginOrderOrder::ORDER_DEVICE_NOT_DELIVRED) { $ma->addMessage(__s("Cannot link items not delivered", "order")); - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_KO); } else { $link->createLinkWithItem( $key, @@ -671,7 +671,7 @@ public static function processMassiveActionsForOneItemtype( $ma->POST['add_items'][$key]['itemtype'], $ma->POST['plugin_order_orders_id'], ); - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_OK); } } @@ -684,7 +684,7 @@ public static function processMassiveActionsForOneItemtype( $ma->POST['add_items'][$key]['itemtype'], $ma->POST['plugin_order_orders_id'], ); - $ma->itemDone($item->getType(), $val, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $val, MassiveAction::ACTION_OK); } break; @@ -695,11 +695,11 @@ public static function processMassiveActionsForOneItemtype( $order_item->getFromDB($key); if ($order_item->fields["items_id"] != 0) { $ma->addMessage(__s("Unable to cancel reception when items are already linked, please unlink them before trying again.", "order")); - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_KO); } elseif (!$link->cancelReception($key)) { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_KO); } else { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_OK); } } @@ -1446,7 +1446,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) if ( $item instanceof PluginOrderOrder && $item->checkIfDetailExists($item->getID(), true) - && Session::haveRight('plugin_order_order', READ) + && Session::haveRight(PluginOrderOrder::$rightname, READ) ) { return self::createTabEntry( _sn("Associated item", "Associated items", 2), @@ -1515,7 +1515,7 @@ public static function copyDocuments($itemtype, $items_id, $orders_id, $entity) 'sha1sum' => $document->fields['sha1sum'], ], ); - if (empty($found_docs)) { + if ($found_docs === []) { $tmpdoc = $document->fields; $tmpdoc['entities_id'] = $entity; unset($tmpdoc['id']); diff --git a/inc/menu.class.php b/inc/menu.class.php index 5c6b5571c6..fe58f9abf6 100644 --- a/inc/menu.class.php +++ b/inc/menu.class.php @@ -66,7 +66,7 @@ public static function getMenuContent() } $menu['options']['order']['links']['lists'] = ""; - $menu['options']['order']['lists_itemtype'] = PluginOrderOrder::getType(); + $menu['options']['order']['lists_itemtype'] = PluginOrderOrder::class; } if (PluginOrderBill::canView()) { @@ -87,7 +87,7 @@ public static function getMenuContent() } $menu['options']['bill']['links']['lists'] = ""; - $menu['options']['bill']['lists_itemtype'] = PluginOrderBill::getType(); + $menu['options']['bill']['lists_itemtype'] = PluginOrderBill::class; } if (PluginOrderReference::canView()) { @@ -108,7 +108,7 @@ public static function getMenuContent() } $menu['options']['references']['links']['lists'] = ""; - $menu['options']['references']['lists_itemtype'] = PluginOrderReference::getType(); + $menu['options']['references']['lists_itemtype'] = PluginOrderReference::class; } return $menu; diff --git a/inc/notificationtargetorder.class.php b/inc/notificationtargetorder.class.php index 940d2907c7..58fa934aa3 100644 --- a/inc/notificationtargetorder.class.php +++ b/inc/notificationtargetorder.class.php @@ -157,7 +157,7 @@ public function addDataForTemplate($event, $options = []) $this->data['##lang.ordervalidation.url##'] = "URL"; $this->data['##ordervalidation.url##'] = $this->formatURL( $options['additionnaloption']['usertype'], - $this->obj->getType() . "_" . $this->obj->getField("id"), + $this->obj::class . "_" . $this->obj->getField("id"), ); } } diff --git a/inc/order.class.php b/inc/order.class.php index 15f6e1be35..577d4eb5fc 100644 --- a/inc/order.class.php +++ b/inc/order.class.php @@ -40,17 +40,17 @@ class PluginOrderOrder extends CommonDBTM { use Clonable; - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public $is_template = true; - public $dohistory = true; + public bool $dohistory = true; protected $usenotepadrights = true; - protected $usenotepad = true; + protected bool $usenotepad = true; - public static $forward_entity_to = [ + public static array $forward_entity_to = [ "PluginOrderOrder_Item", "PluginOrderOrder_Supplier", "PluginOrderSurveySupplier", @@ -108,37 +108,37 @@ public function getState() public static function canCancel() { - return Session::haveRight("plugin_order_order", self::RIGHT_CANCEL); + return Session::haveRight(self::$rightname, self::RIGHT_CANCEL); } public static function canUndo() { - return Session::haveRight("plugin_order_order", self::RIGHT_UNDO_VALIDATION); + return Session::haveRight(self::$rightname, self::RIGHT_UNDO_VALIDATION); } public static function canValidate() { - return Session::haveRight("plugin_order_order", self::RIGHT_VALIDATION); + return Session::haveRight(self::$rightname, self::RIGHT_VALIDATION); } public static function canGenerateWithoutValidation() { - return Session::haveRight("plugin_order_order", self::RIGHT_GENERATEODT_WITHOUT_VALIDATION); + return Session::haveRight(self::$rightname, self::RIGHT_GENERATEODT_WITHOUT_VALIDATION); } public static function canGenerate() { - return Session::haveRight("plugin_order_order", self::RIGHT_GENERATEODT); + return Session::haveRight(self::$rightname, self::RIGHT_GENERATEODT); } public static function canDeliver() { - return Session::haveRight("plugin_order_order", self::RIGHT_DELIVERY); + return Session::haveRight(self::$rightname, self::RIGHT_DELIVERY); } @@ -635,7 +635,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) $ong = []; $config = PluginOrderConfig::getConfig(); if ( - Session::haveRightsOr("plugin_order_order", [ + Session::haveRightsOr(self::$rightname, [ self::RIGHT_VALIDATION, self::RIGHT_CANCEL, self::RIGHT_UNDO_VALIDATION, @@ -751,17 +751,15 @@ public function post_addItem() "glpi_documents_items", [ 'items_id' => $this->input["_oldID"], - 'itemtype' => $this->getType(), + 'itemtype' => static::class, ], ); - if (!empty($docs)) { - foreach ($docs as $doc) { - $docitem->add([ - 'documents_id' => $doc["documents_id"], - 'itemtype' => $this->getType(), - 'items_id' => $this->fields['id'], - ]); - } + foreach ($docs as $doc) { + $docitem->add([ + 'documents_id' => $doc["documents_id"], + 'itemtype' => static::class, + 'items_id' => $this->fields['id'], + ]); } } } @@ -915,7 +913,7 @@ public function showForm($ID, $options = []) $this->fields["name"], "name", ($template === "newcomp"), - $this->getType(), + static::class, $this->fields["entities_id"], ); echo Html::input( @@ -962,7 +960,7 @@ public function showForm($ID, $options = []) $this->fields["num_order"], "num_order", ($template === "newcomp"), - $this->getType(), + static::class, $this->fields["entities_id"], ); echo Html::input( @@ -1581,7 +1579,7 @@ public function addStatusLog($orders_id, $status, $comments = '') $changes .= " : " . $comments; } - $this->addHistory($this->getType(), '', $changes, $orders_id); + $this->addHistory(static::class, '', $changes, $orders_id); } @@ -2521,7 +2519,7 @@ public static function addDocumentCategory(Document $document) // Get order linked to document $document_item = new Document_Item(); - if ($document_item->getFromDBByCrit(['documents_id' => $document->fields['id'], 'itemtype' => self::getType()])) { + if ($document_item->getFromDBByCrit(['documents_id' => $document->fields['id'], 'itemtype' => static::class])) { // Update document name $order = new self(); $order->getFromDB($document_item->fields['items_id']); @@ -2571,7 +2569,7 @@ public function getSpecificMassiveActions($checkitem = null) $isadmin = static::canUpdate(); $actions = parent::getSpecificMassiveActions($checkitem); - if ($isadmin && (Session::haveRight('transfer', READ) && Session::isMultiEntitiesMode())) { + if ($isadmin && (Session::haveRight(Transfer::$rightname, READ) && Session::isMultiEntitiesMode())) { $actions['PluginOrderOrder:transfert'] = __s('Transfer'); } @@ -2596,7 +2594,7 @@ public static function processMassiveActionsForOneItemtype(MassiveAction $ma, Co "entities_id" => $entities_id, "update" => __s('Update'), ]); - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $id, MassiveAction::ACTION_OK); } } diff --git a/inc/order_item.class.php b/inc/order_item.class.php index 596a1131d1..808ef145f2 100644 --- a/inc/order_item.class.php +++ b/inc/order_item.class.php @@ -36,24 +36,24 @@ class PluginOrderOrder_Item extends CommonDBRelation // phpcs:ignore { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public $dohistory = true; + public bool $dohistory = true; // From CommonDBRelation - public static $itemtype_1 = "PluginOrderOrder"; + public static ?string $itemtype_1 = "PluginOrderOrder"; - public static $items_id_1 = 'plugin_order_orders_id'; + public static ?string $items_id_1 = 'plugin_order_orders_id'; - public static $checkItem_1_Rights = self::DONT_CHECK_ITEM_RIGHTS; + public static int $checkItem_1_Rights = self::DONT_CHECK_ITEM_RIGHTS; - public static $itemtype_2 = 'itemtype'; + public static ?string $itemtype_2 = 'itemtype'; - public static $items_id_2 = 'items_id'; + public static ?string $items_id_2 = 'items_id'; - public static $checkItem_2_Rights = self::DONT_CHECK_ITEM_RIGHTS; + public static int $checkItem_2_Rights = self::DONT_CHECK_ITEM_RIGHTS; - public static $check_entity_coherency = false; + public static bool $check_entity_coherency = false; //TODO better right and entity menber (ex Computer_Item) @@ -918,7 +918,7 @@ public function showFormDetail($plugin_order_orders_id) $canedit = $order->can($plugin_order_orders_id, UPDATE) && $order->canUpdateOrder(); Session::initNavigateListItems( - $this->getType(), + static::class, __s("Order", "order") . " = " . $order->getName(), ); foreach ($result_ref as $data_ref) { @@ -1201,7 +1201,7 @@ public function getItems($rand, $data_ref, $plugin_order_orders_id, $numref, $ca $visible = $_GET[$countainer_name . 'visible'] ?? false; foreach ($iterator as $data) { - Session::addToNavigateListItems($this->getType(), (int) $data['IDD']); + Session::addToNavigateListItems(static::class, (int) $data['IDD']); // Build entry for this row $entry = []; @@ -1434,11 +1434,11 @@ public function showPluginFromItems($itemtype, $ID) 'items_id' => $ID, ], ); - if (!empty($result)) { + if ($result !== []) { $link = array_shift($result); $reference = new PluginOrderReference(); $reference->getFromDB($link['plugin_order_references_id']); - if (Session::haveRight('plugin_order_reference', READ)) { + if (Session::haveRight(PluginOrderReference::$rightname, READ)) { $twig_option['reference_link'] = $reference->getLink(); } @@ -2219,7 +2219,7 @@ public static function countForItem(CommonDBTM $item) return countElementsInTable( 'glpi_plugin_order_orders_items', [ - 'itemtype' => $item->getType(), + 'itemtype' => $item::class, 'items_id' => $item->getID(), ], ); @@ -2271,7 +2271,7 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $ } } elseif ( is_subclass_of($item, CommonDBTM::class) - && in_array($item->getType(), PluginOrderOrder_Item::getClasses(true)) + && in_array($item::class, PluginOrderOrder_Item::getClasses(true)) ) { $order_item = new self(); $order_item->showPluginFromItems($item::class, $item->fields['id']); diff --git a/inc/order_supplier.class.php b/inc/order_supplier.class.php index a0c8c5fb1e..c585c3d0cf 100644 --- a/inc/order_supplier.class.php +++ b/inc/order_supplier.class.php @@ -32,13 +32,13 @@ class PluginOrderOrder_Supplier extends CommonDBChild // phpcs:ignore { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public static $itemtype = 'PluginOrderOrder'; + public static string $itemtype = 'PluginOrderOrder'; - public static $items_id = 'plugin_order_orders_id'; + public static string $items_id = 'plugin_order_orders_id'; - public $dohistory = true; + public bool $dohistory = true; public static function getTypeName($nb = 0) diff --git a/inc/orderpayment.class.php b/inc/orderpayment.class.php index de87bbdaa9..9f1e01cf93 100644 --- a/inc/orderpayment.class.php +++ b/inc/orderpayment.class.php @@ -33,7 +33,7 @@ // Class for a Dropdown class PluginOrderOrderPayment extends CommonDropdown { - public static $rightname = 'plugin_order_order'; //'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; //'plugin_order_order'; public static function getTypeName($nb = 0) { diff --git a/inc/orderstate.class.php b/inc/orderstate.class.php index 8f39b80338..3a6633e68c 100644 --- a/inc/orderstate.class.php +++ b/inc/orderstate.class.php @@ -47,7 +47,7 @@ class PluginOrderOrderState extends CommonDropdown public const PAID = 7; - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/ordertax.class.php b/inc/ordertax.class.php index ca8a167e91..d826f37421 100644 --- a/inc/ordertax.class.php +++ b/inc/ordertax.class.php @@ -33,7 +33,7 @@ // Class for a Dropdown class PluginOrderOrderTax extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/ordertype.class.php b/inc/ordertype.class.php index f484a20040..b270d3c645 100644 --- a/inc/ordertype.class.php +++ b/inc/ordertype.class.php @@ -33,7 +33,7 @@ // Class for a Dropdown class PluginOrderOrdertype extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/other.class.php b/inc/other.class.php index 20e0682e53..27e316650c 100644 --- a/inc/other.class.php +++ b/inc/other.class.php @@ -32,7 +32,7 @@ class PluginOrderOther extends CommonDBTM { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/othertype.class.php b/inc/othertype.class.php index 71879d0774..d9d5cb0efa 100644 --- a/inc/othertype.class.php +++ b/inc/othertype.class.php @@ -32,7 +32,7 @@ class PluginOrderOthertype extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/preference.class.php b/inc/preference.class.php index 413127177c..d0273d4fb7 100644 --- a/inc/preference.class.php +++ b/inc/preference.class.php @@ -65,7 +65,7 @@ public function addDefaultPreference($users_id) public static function checkPreferenceValue($field, $users_id = 0) { $data = getAllDataFromTable(self::getTable(), ['users_id' => $users_id]); - if (!empty($data)) { + if ($data !== []) { $first = array_pop($data); return $first[$field]; } else { diff --git a/inc/profile.class.php b/inc/profile.class.php index c39ddf708f..f2dfed0203 100644 --- a/inc/profile.class.php +++ b/inc/profile.class.php @@ -32,7 +32,7 @@ class PluginOrderProfile extends CommonDBTM { - public static $rightname = 'profile'; + public static string $rightname = 'profile'; public static function createFirstAccess($ID) diff --git a/inc/reception.class.php b/inc/reception.class.php index 70fed233f0..24bdbea6bf 100644 --- a/inc/reception.class.php +++ b/inc/reception.class.php @@ -32,15 +32,15 @@ class PluginOrderReception extends CommonDBChild { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public $dohistory = true; + public bool $dohistory = true; - public static $itemtype = 'PluginOrderOrder'; + public static string $itemtype = 'PluginOrderOrder'; - public static $items_id = 'plugin_order_orders_id'; + public static string $items_id = 'plugin_order_orders_id'; - public static $checkParentRights = self::DONT_CHECK_ITEM_RIGHTS; + public static int $checkParentRights = self::DONT_CHECK_ITEM_RIGHTS; public static function getTable($classname = null) @@ -61,14 +61,14 @@ public static function getIcon() public function canUpdateItem(): bool { - return Session::haveRight('plugin_order_order', PluginOrderOrder::RIGHT_DELIVERY); + return Session::haveRight(PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_DELIVERY); } public function canViewItem(): bool { - return Session::haveRight('plugin_order_order', PluginOrderOrder::RIGHT_DELIVERY) - && Session::haveRight('plugin_order_order', READ); + return Session::haveRight(PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_DELIVERY) + && Session::haveRight(PluginOrderOrder::$rightname, READ); } @@ -272,12 +272,12 @@ public function showForm($ID, $options = []) echo ""; echo ""; $status = 1; if ($typeRef != 'SoftwareLicense') { @@ -562,7 +562,7 @@ public function showOrderReceptionItem($data_ref, $numref, $canedit, $reference, } echo ""; echo ""; - $link = Toolbox::getItemTypeFormURL($this->getType()); + $link = Toolbox::getItemTypeFormURL(static::class); echo ""; echo "
" . __s('Document category prefix', 'order') . "
" . __s("Bill", "order") . ""; - if (Session::haveRight("plugin_order_bill", UPDATE)) { + if (Session::haveRight(PluginOrderBill::$rightname, UPDATE)) { PluginOrderBill::Dropdown([ 'name' => "plugin_order_bills_id", 'value' => $this->fields["plugin_order_bills_id"], ]); - } elseif (Session::haveRight("plugin_order_bill", READ)) { + } elseif (Session::haveRight(PluginOrderBill::$rightname, READ)) { echo Dropdown::getDropdownName( "glpi_plugin_order_bills", $this->fields["plugin_order_bills_id"], @@ -318,7 +318,7 @@ public function showOrderReception($orders_id) $order_order->getFromDB($orders_id); Session::initNavigateListItems( - $this->getType(), + static::class, __s("Order", "order") . " = " . $order_order->fields["name"], ); @@ -531,7 +531,7 @@ public function showOrderReceptionItem($data_ref, $numref, $canedit, $reference, foreach ($all_data as $data) { $detailID = $data["IDD"]; - Session::addToNavigateListItems($this->getType(), (int) $detailID); + Session::addToNavigateListItems(static::class, (int) $detailID); echo "
"; - $link = Toolbox::getItemTypeFormURL($this->getType()); + $link = Toolbox::getItemTypeFormURL(static::class); if ($canedit && $data["states_id"] == PluginOrderOrder::ORDER_DEVICE_DELIVRED) { echo ''; } diff --git a/inc/reference.class.php b/inc/reference.class.php index 36e101151d..5fbba29882 100644 --- a/inc/reference.class.php +++ b/inc/reference.class.php @@ -59,11 +59,11 @@ */ class PluginOrderReference extends CommonDBTM { - public static $rightname = 'plugin_order_reference'; //'plugin_order_reference'; //TODO : A développer + public static string $rightname = 'plugin_order_reference'; //'plugin_order_reference'; //TODO : A développer - public $dohistory = true; + public bool $dohistory = true; - public static $forward_entity_to = ['PluginOrderReference_Supplier']; + public static array $forward_entity_to = ['PluginOrderReference_Supplier']; public static function getTypeName($nb = 0) @@ -355,7 +355,7 @@ public function referenceInUse() public function getReceptionReferenceLink($data) { - $link = Toolbox::getItemTypeFormURL($this->getType()); + $link = Toolbox::getItemTypeFormURL(static::class); if (self::canView()) { return '' . $data["name"] . ""; @@ -1029,7 +1029,7 @@ public function getSpecificMassiveActions($checkitem = null) if ($isadmin) { if ( - Session::haveRight('transfer', READ) + Session::haveRight(Transfer::$rightname, READ) && Session::isMultiEntitiesMode() ) { $actions['PluginOrderReference:transfert'] = __s('Transfer'); @@ -1061,7 +1061,7 @@ public static function processMassiveActionsForOneItemtype(MassiveAction $ma, Co "entities_id" => $entities_id, "update" => __s('Update'), ]); - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $id, MassiveAction::ACTION_OK); } } @@ -1075,7 +1075,7 @@ public static function processMassiveActionsForOneItemtype(MassiveAction $ma, Co $item->copy($id); } - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $id, MassiveAction::ACTION_OK); } return; diff --git a/inc/reference_supplier.class.php b/inc/reference_supplier.class.php index bdb4ac5156..72d186c812 100644 --- a/inc/reference_supplier.class.php +++ b/inc/reference_supplier.class.php @@ -32,13 +32,13 @@ class PluginOrderReference_Supplier extends CommonDBChild // phpcs:ignore { - public static $rightname = 'plugin_order_reference'; + public static string $rightname = 'plugin_order_reference'; - public static $itemtype = 'PluginOrderReference'; + public static string $itemtype = 'PluginOrderReference'; - public static $items_id = 'plugin_order_references_id'; + public static string $items_id = 'plugin_order_references_id'; - public $dohistory = true; + public bool $dohistory = true; public static function getTypeName($nb = 0) @@ -273,7 +273,7 @@ public function showReferenceManufacturers($ID) $target = Toolbox::getItemTypeFormURL(self::class); Session::initNavigateListItems( - $this->getType(), + static::class, __s("Product reference", "order") . " = " . $ref->fields["name"], ); @@ -308,7 +308,7 @@ public function showReferenceManufacturers($ID) echo Html::hidden('plugin_order_references_id', ['value' => $ID]); foreach ($result as $data) { - Session::addToNavigateListItems($this->getType(), (int) $data['id']); + Session::addToNavigateListItems(static::class, (int) $data['id']); echo Html::hidden("item[" . $data["id"] . "]", ['value' => $ID]); echo "
"; @@ -332,7 +332,7 @@ public function showReferenceManufacturers($ID) echo "" . Dropdown::getDropdownName("glpi_suppliers", (int) $data["suppliers_id"]) . ""; diff --git a/inc/referencefree.class.php b/inc/referencefree.class.php index 860d53d75b..ffcc9198b1 100644 --- a/inc/referencefree.class.php +++ b/inc/referencefree.class.php @@ -32,9 +32,9 @@ class PluginOrderReferenceFree extends CommonDBTM { - public static $rightname = 'plugin_order_reference'; + public static string $rightname = 'plugin_order_reference'; - public $dohistory = true; + public bool $dohistory = true; public static function getTypeName($nb = 0) { diff --git a/inc/surveysupplier.class.php b/inc/surveysupplier.class.php index 306af52697..2f21193d40 100644 --- a/inc/surveysupplier.class.php +++ b/inc/surveysupplier.class.php @@ -32,11 +32,11 @@ class PluginOrderSurveySupplier extends CommonDBChild { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public static $itemtype = 'PluginOrderOrder'; + public static string $itemtype = 'PluginOrderOrder'; - public static $items_id = 'plugin_order_orders_id'; + public static string $items_id = 'plugin_order_orders_id'; public static function getTypeName($nb = 0) @@ -175,8 +175,6 @@ public static function showGlobalNotation($suppliers_id) $survey = new self(); $survey_table = $survey->getTable(); - getEntitiesRestrictRequest(" AND ", "orders", "entities_id", '', true); - $criteria = [ 'SELECT' => [ 'orders.id', diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000000..e9f60d9f8c --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,7 @@ + + + + tests/Units + + + diff --git a/public/css/order.css b/public/css/order.css index 8bbc0f5417..694aba60cd 100644 --- a/public/css/order.css +++ b/public/css/order.css @@ -37,7 +37,9 @@ input[type="number"].quantity { input[type="number"].decimal, input[type="number"].smalldecimal, input[type="number"].quantity { - width: 100px; + width: 100%; + max-width: 100px; + box-sizing: border-box; } input[type="number"].decimal::-webkit-inner-spin-button, @@ -70,6 +72,30 @@ input[type="number"].quantity::-webkit-inner-spin-button { width: 25%; } +/* quantity */ +.tab_order_add_items th:nth-child(4), +.tab_order_add_items td:nth-child(4) { + width: 90px; +} + +/* unit price tax free */ +.tab_order_add_items th:nth-child(5), +.tab_order_add_items td:nth-child(5) { + width: 100px; +} + +/* VAT */ +.tab_order_add_items th:nth-child(6), +.tab_order_add_items td:nth-child(6) { + width: 130px; +} + +/* discount */ +.tab_order_add_items th:nth-child(7), +.tab_order_add_items td:nth-child(7) { + width: 100px; +} + /* ADD button */ .tab_order_add_items th:nth-child(8), .tab_order_add_items td:nth-child(8) { diff --git a/report/deliveryinfos/deliveryinfos.php b/report/deliveryinfos/deliveryinfos.php index b63e36e3d8..e19fb7f008 100644 --- a/report/deliveryinfos/deliveryinfos.php +++ b/report/deliveryinfos/deliveryinfos.php @@ -38,12 +38,6 @@ * ---------------------------------------------------------------------- */ -//Options for GLPI 0.71 and newer : need slave db to access the report -$USEDBREPLICATE = 1; -$DBCONNECTION_REQUIRED = 0; // Really a big SQL request - -include(__DIR__ . "/../../../../inc/includes.php"); - $report = new PluginReportsAutoReport(__s("deliveryinfos_report_title", "order")); new PluginReportsDateIntervalCriteria($report, 'order_date', __s("Date of order", "order")); new PluginReportsDateIntervalCriteria($report, 'deliverydate', __s("Delivery date")); diff --git a/report/orderdelivery/orderdelivery.php b/report/orderdelivery/orderdelivery.php index cfd9449bb9..8fb40e07ab 100644 --- a/report/orderdelivery/orderdelivery.php +++ b/report/orderdelivery/orderdelivery.php @@ -38,12 +38,6 @@ * ---------------------------------------------------------------------- */ -//Options for GLPI 0.71 and newer : need slave db to access the report -$USEDBREPLICATE = 1; -$DBCONNECTION_REQUIRED = 0; // Really a big SQL request - -include(__DIR__ . "/../../../../inc/includes.php"); - $report = new PluginReportsAutoReport(__s("orderdelivery_report_title", "order")); new PluginReportsDateIntervalCriteria($report, 'order_date', __s("Date of order", "order")); new PluginReportsDateIntervalCriteria($report, 'deliverydate', __s("Delivery date")); diff --git a/setup.php b/setup.php index 7768b99afc..a2b78815c0 100644 --- a/setup.php +++ b/setup.php @@ -35,9 +35,9 @@ define('PLUGIN_ORDER_VERSION', '2.12.9'); // Minimal GLPI version, inclusive -define("PLUGIN_ORDER_MIN_GLPI", "11.0.0"); +define("PLUGIN_ORDER_MIN_GLPI", "12.0.0"); // Maximum GLPI version, exclusive -define("PLUGIN_ORDER_MAX_GLPI", "11.0.99"); +define("PLUGIN_ORDER_MAX_GLPI", "12.0.99"); if (!defined('PLUGIN_ORDER_DIR')) { define("PLUGIN_ORDER_DIR", Plugin::getPhpDir('order')); @@ -200,7 +200,7 @@ function plugin_init_order() $PLUGIN_HOOKS['add_css']['order'][] = 'css/order.css'; /* link to the config page in plugins menu */ - if (Session::haveRight("config", UPDATE)) { + if (Session::haveRight(Config::$rightname, UPDATE)) { $PLUGIN_HOOKS['config_page']['order'] = 'front/config.form.php'; } diff --git a/templates/order_getitems.html.twig b/templates/order_getitems.html.twig index 5c8ab6d274..517bc6dd5d 100644 --- a/templates/order_getitems.html.twig +++ b/templates/order_getitems.html.twig @@ -60,7 +60,6 @@ {% if form_action is defined %} - {% endif %} {% if hidden_fields is defined %} diff --git a/tests/OrderTestCase.php b/tests/OrderTestCase.php new file mode 100644 index 0000000000..3d62c73ae4 --- /dev/null +++ b/tests/OrderTestCase.php @@ -0,0 +1,120 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests; + +use Glpi\Tests\DbTestCase; +use PluginOrderOrder; +use PluginOrderOrder_Item; +use PluginOrderReference; +use PluginOrderReference_Supplier; +use Supplier; + +abstract class OrderTestCase extends DbTestCase +{ + /** + * Create a Supplier fixture, usable both as an order supplier and a + * reference supplier. + */ + public function createSupplier(string $name = 'Test Supplier'): Supplier + { + return $this->createItem(Supplier::class, [ + 'name' => $name . '_' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + ]); + } + + /** + * Create a catalog Product reference (PluginOrderReference), optionally + * linked to a Supplier via PluginOrderReference_Supplier. + */ + public function createReference( + ?Supplier $supplier = null, + string $itemtype = 'Computer', + float $price_taxfree = 100, + ): PluginOrderReference { + $reference = $this->createItem(PluginOrderReference::class, [ + 'name' => 'Test Reference_' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + 'itemtype' => $itemtype, + ]); + + if ($supplier !== null) { + $this->createItem(PluginOrderReference_Supplier::class, [ + 'plugin_order_references_id' => $reference->getID(), + 'suppliers_id' => $supplier->getID(), + 'price_taxfree' => $price_taxfree, + ]); + } + + return $reference; + } + + /** + * Create a draft PluginOrderOrder fixture. + */ + public function createOrder(array $input = []): PluginOrderOrder + { + return $this->createItem(PluginOrderOrder::class, array_merge([ + 'name' => 'Test Order_' . $this->getUniqueString(), + 'num_order' => 'CMD_' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + ], $input)); + } + + /** + * Link a Product reference to an order, as PluginOrderOrder_Item does + * through PluginOrderOrder::showAddForm() / addDetails(). + */ + public function addReferenceToOrder( + PluginOrderOrder $order, + PluginOrderReference $reference, + int $quantity = 1, + float $price = 100, + float $discount = 0, + ): array { + $order_item = new PluginOrderOrder_Item(); + $order_item->addDetails( + $reference->getID(), + $reference->fields['itemtype'], + $order->getID(), + $quantity, + $price, + $discount, + 0, + 0, + ); + + return array_values($order_item->find([ + 'plugin_order_orders_id' => $order->getID(), + 'plugin_order_references_id' => $reference->getID(), + ])); + } +} diff --git a/tests/Units/BillTest.php b/tests/Units/BillTest.php new file mode 100644 index 0000000000..4bea55186c --- /dev/null +++ b/tests/Units/BillTest.php @@ -0,0 +1,104 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderBill; + +final class BillTest extends OrderTestCase +{ + public function testCreateBillRequiresNumber(): void + { + $this->login(); + + $bill = new PluginOrderBill(); + $id = $bill->add([ + 'name' => 'Bill without number', + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->assertFalse($id); + $this->hasSessionMessages(ERROR, ['A bill number is mandatory']); + } + + public function testCreateBillLinkedToOrderAndSupplier(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + + $bill = $this->createItem(PluginOrderBill::class, [ + 'name' => 'Test bill', + 'number' => 'INV-' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + 'suppliers_id' => $supplier->getID(), + 'plugin_order_orders_id' => $order->getID(), + 'value' => 199.99, + ]); + + $this->assertSame($supplier->getID(), (int) $bill->fields['suppliers_id']); + $this->assertSame($order->getID(), (int) $bill->fields['plugin_order_orders_id']); + $this->assertEqualsWithDelta(199.99, (float) $bill->fields['value'], 0.001); + } + + public function testUpdateBill(): void + { + $this->login(); + + $bill = $this->createItem(PluginOrderBill::class, [ + 'name' => 'Test bill', + 'number' => 'INV-' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->updateItem(PluginOrderBill::class, $bill->getID(), [ + 'value' => 42.5, + ]); + + $bill->getFromDB($bill->getID()); + $this->assertEqualsWithDelta(42.5, (float) $bill->fields['value'], 0.001); + } + + public function testDeleteBill(): void + { + $this->login(); + + $bill = $this->createItem(PluginOrderBill::class, [ + 'name' => 'Test bill', + 'number' => 'INV-' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->assertTrue($bill->delete(['id' => $bill->getID()], true)); + $this->assertFalse((new PluginOrderBill())->getFromDB($bill->getID())); + } +} diff --git a/tests/Units/DropdownsTest.php b/tests/Units/DropdownsTest.php new file mode 100644 index 0000000000..6e7228daa2 --- /dev/null +++ b/tests/Units/DropdownsTest.php @@ -0,0 +1,78 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use GlpiPlugin\Order\Tests\OrderTestCase; +use PHPUnit\Framework\Attributes\DataProvider; + +/** + * Generic CRUD coverage for every simple CommonDropdown exposed by the + * plugin. These are all used as reference data on Orders / Order items / + * Bills, so a regression here (e.g. a rightname or table change breaking + * under a newer GLPI) would silently break every form relying on them. + */ +final class DropdownsTest extends OrderTestCase +{ + public static function dropdownClassesProvider(): array + { + return [ + ['PluginOrderOrderState'], + ['PluginOrderOrdertype'], + ['PluginOrderOrderTax'], + ['PluginOrderOrderPayment'], + ['PluginOrderAccountsection'], + ['PluginOrderAnalyticnature'], + ['PluginOrderDeliverystate'], + ['PluginOrderBillState'], + ['PluginOrderBillType'], + ['PluginOrderOthertype'], + ]; + } + + #[DataProvider('dropdownClassesProvider')] + public function testCreateUpdateAndDeleteDropdown(string $itemtype): void + { + $this->login(); + + $item = $this->createItem($itemtype, [ + 'name' => 'Test ' . $itemtype . '_' . $this->getUniqueString(), + ]); + + $this->updateItem($itemtype, $item->getID(), [ + 'comment' => 'Updated via functional test', + ]); + $item->getFromDB($item->getID()); + $this->assertSame('Updated via functional test', $item->fields['comment']); + + $this->assertTrue($item->delete(['id' => $item->getID()], true)); + $this->assertFalse((new $itemtype())->getFromDB($item->getID())); + } +} diff --git a/tests/Units/OrderItemTest.php b/tests/Units/OrderItemTest.php new file mode 100644 index 0000000000..3e8f179b39 --- /dev/null +++ b/tests/Units/OrderItemTest.php @@ -0,0 +1,107 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use Computer; +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderOrder_Item; + +final class OrderItemTest extends OrderTestCase +{ + public function testGetClassesIncludesNativeGlpiAssets(): void + { + $this->login(); + + $classes = PluginOrderOrder_Item::getClasses(true); + + // Order lines can natively point to these core GLPI asset types. + $this->assertContains(Computer::class, $classes); + $this->assertContains('Monitor', $classes); + $this->assertContains('NetworkEquipment', $classes); + $this->assertContains('Printer', $classes); + $this->assertContains('SoftwareLicense', $classes); + } + + public function testAddDetailsCreatesOneLinePerQuantity(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier, Computer::class, 250); + + $lines = $this->addReferenceToOrder($order, $reference, 3, 250, 10); + + $this->assertCount(3, $lines); + foreach ($lines as $line) { + $this->assertSame($order->getID(), (int) $line['plugin_order_orders_id']); + $this->assertSame($reference->getID(), (int) $line['plugin_order_references_id']); + $this->assertSame(Computer::class, $line['itemtype']); + // 250 - 10% discount = 225 + $this->assertEqualsWithDelta(225.0, (float) $line['price_discounted'], 0.001); + } + } + + public function testGetAllPricesSumsOrderLines(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier, Computer::class, 100); + + $this->addReferenceToOrder($order, $reference, 2, 100, 0); + + $order_item = new PluginOrderOrder_Item(); + $prices = $order_item->getAllPrices($order->getID()); + + $this->assertEqualsWithDelta(200.0, (float) $prices['priceHT'], 0.001); + } + + public function testDeletingOrderItemDoesNotDeleteTheOrder(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier, Computer::class, 100); + $lines = $this->addReferenceToOrder($order, $reference, 1, 100, 0); + + $order_item = new PluginOrderOrder_Item(); + $this->assertTrue($order_item->delete(['id' => $lines[0]['id']], true)); + + $this->assertCount( + 0, + $order_item->find(['id' => $lines[0]['id']]), + ); + $this->assertTrue($order->getFromDB($order->getID())); + } +} diff --git a/tests/Units/OrderTest.php b/tests/Units/OrderTest.php new file mode 100644 index 0000000000..de16ec9fd8 --- /dev/null +++ b/tests/Units/OrderTest.php @@ -0,0 +1,202 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderOrder; +use PluginOrderOrder_Item; +use PluginOrderOrder_Supplier; +use PluginOrderOrderState; + +final class OrderTest extends OrderTestCase +{ + public function testCreateOrderIsDraftByDefault(): void + { + $this->login(); + + $order = $this->createOrder(); + + $this->assertSame( + PluginOrderOrderState::DRAFT, + (int) $order->fields['plugin_order_orderstates_id'], + ); + $this->assertTrue($order->isDraft()); + $this->assertFalse($order->isCanceled()); + $this->assertFalse($order->isDelivered()); + } + + public function testCreateOrderWithoutNumOrderFails(): void + { + $this->login(); + + $order = new PluginOrderOrder(); + $id = $order->add([ + 'name' => 'Missing num_order', + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->assertFalse($id); + $this->hasSessionMessages(ERROR, ['An order number is mandatory !']); + } + + public function testUpdateOrder(): void + { + $this->login(); + + $order = $this->createOrder(); + + $this->updateItem(PluginOrderOrder::class, $order->getID(), [ + 'comment' => 'Updated comment', + ]); + + $order->getFromDB($order->getID()); + $this->assertSame('Updated comment', $order->fields['comment']); + } + + public function testUpdateOrderStatusAddsHistoryLog(): void + { + $this->login(); + + $order = $this->createOrder(); + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::VALIDATED, 'validated for test'); + + $order->getFromDB($order->getID()); + $this->assertSame(PluginOrderOrderState::VALIDATED, (int) $order->fields['plugin_order_orderstates_id']); + $this->assertTrue($order->isApproved()); + } + + public function testDeliveredStateSetsDeliveryDate(): void + { + $this->login(); + + $order = $this->createOrder(); + $this->assertEmpty($order->fields['deliverydate']); + + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::DELIVERED); + + $order->getFromDB($order->getID()); + $this->assertTrue($order->isDelivered()); + $this->assertNotEmpty($order->fields['deliverydate']); + } + + public function testCanValidateOrderWithoutValidationProcessDependsOnDraftState(): void + { + $this->login(); + + $order = $this->createOrder(); + + // No validation workflow configured by default: draft orders can be validated directly. + $this->assertTrue($order->canValidateOrder()); + + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::VALIDATED); + $order->getFromDB($order->getID()); + $this->assertFalse($order->canValidateOrder()); + } + + public function testCanCancelOrderRequiresRight(): void + { + $this->removeRightFromProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_CANCEL); + $this->login(); + + $order = $this->createOrder(); + $this->assertFalse($order->canCancelOrder()); + + $this->logOut(); + $this->addRightToProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_CANCEL); + $this->login(); + + $order->getFromDB($order->getID()); + $this->assertTrue($order->canCancelOrder()); + } + + public function testCanceledOrderCannotBeCanceledAgain(): void + { + $this->addRightToProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_CANCEL); + $this->login(); + + $order = $this->createOrder(); + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::CANCELED); + $order->getFromDB($order->getID()); + + $this->assertTrue($order->isCanceled()); + $this->assertFalse($order->canCancelOrder()); + } + + public function testUndoValidationRequiresRightAndValidatedState(): void + { + $this->addRightToProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_UNDO_VALIDATION); + $this->login(); + + $order = $this->createOrder(); + // Still draft: nothing to undo. + $this->assertFalse($order->canUndoValidation()); + + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::VALIDATED); + $order->getFromDB($order->getID()); + $this->assertTrue($order->canUndoValidation()); + + $this->logOut(); + $this->removeRightFromProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_UNDO_VALIDATION); + $this->login(); + + $order->getFromDB($order->getID()); + $this->assertFalse($order->canUndoValidation()); + } + + public function testPurgingOrderCascadesToRelatedItems(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + + $order_supplier = $this->createItem(PluginOrderOrder_Supplier::class, [ + 'plugin_order_orders_id' => $order->getID(), + 'suppliers_id' => $supplier->getID(), + ]); + + $reference = $this->createReference($supplier); + $this->addReferenceToOrder($order, $reference); + + $this->assertNotCount( + 0, + (new PluginOrderOrder_Item())->find(['plugin_order_orders_id' => $order->getID()]), + ); + + $this->assertTrue($order->delete(['id' => $order->getID()], true)); + + $this->assertFalse((new PluginOrderOrder_Supplier())->getFromDB($order_supplier->getID())); + $this->assertCount( + 0, + (new PluginOrderOrder_Item())->find(['plugin_order_orders_id' => $order->getID()]), + ); + } +} diff --git a/tests/Units/OrderableCapacityTest.php b/tests/Units/OrderableCapacityTest.php new file mode 100644 index 0000000000..fe50c9fffd --- /dev/null +++ b/tests/Units/OrderableCapacityTest.php @@ -0,0 +1,110 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use Glpi\Asset\AssetDefinitionManager; +use Glpi\Asset\Capacity; +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderOrder_Item; +use PluginOrderOrderableCapacity; +use PluginOrderReference; + +/** + * Coverage for the GLPI 11/12 custom-asset integration: enabling the + * "Orderable" capacity on a custom asset definition must make its class + * usable as a Product reference itemtype, and disabling it must clean up + * any plugin data that referenced it. + */ +final class OrderableCapacityTest extends OrderTestCase +{ + /** + * GLPITestCase::tearDown() resets the AssetDefinitionManager singleton + * after every test, which discards the capacity registration normally + * done once by plugin_init_order(). Re-register it before each test + * that needs to create/toggle it on a definition. + */ + private function registerOrderableCapacity(): void + { + AssetDefinitionManager::getInstance()->registerCapacity(new PluginOrderOrderableCapacity()); + } + + public function testCapacityUsageDescriptionReflectsLinkedReferences(): void + { + $this->login(); + $this->registerOrderableCapacity(); + + $capacity = new PluginOrderOrderableCapacity(); + + $definition = $this->initAssetDefinition( + capacities: [new Capacity(name: PluginOrderOrderableCapacity::class)], + ); + $classname = $definition->getAssetClassName(); + + $this->assertSame(0, (int) filter_var( + $capacity->getCapacityUsageDescription($classname), + FILTER_SANITIZE_NUMBER_INT, + )); + + $reference = $this->createReference(itemtype: $classname); + + $this->assertSame(1, (int) filter_var( + $capacity->getCapacityUsageDescription($classname), + FILTER_SANITIZE_NUMBER_INT, + )); + + // Sanity check: the created reference is retrievable and points to the custom asset class. + $this->assertSame($classname, $reference->fields['itemtype']); + } + + public function testDisablingCapacityCleansUpLinkedReferencesAndOrderItems(): void + { + $this->login(); + $this->registerOrderableCapacity(); + + $definition = $this->initAssetDefinition( + capacities: [new Capacity(name: PluginOrderOrderableCapacity::class)], + ); + $classname = $definition->getAssetClassName(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier, $classname); + $this->addReferenceToOrder($order, $reference); + + $this->assertNotCount(0, (new PluginOrderReference())->find(['itemtype' => $classname])); + $this->assertNotCount(0, (new PluginOrderOrder_Item())->find(['itemtype' => $classname])); + + $this->disableCapacity($definition, PluginOrderOrderableCapacity::class); + + $this->assertCount(0, (new PluginOrderReference())->find(['itemtype' => $classname])); + $this->assertCount(0, (new PluginOrderOrder_Item())->find(['itemtype' => $classname])); + } +} diff --git a/tests/Units/ProfileTest.php b/tests/Units/ProfileTest.php new file mode 100644 index 0000000000..627b78f1c5 --- /dev/null +++ b/tests/Units/ProfileTest.php @@ -0,0 +1,87 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderBill; +use PluginOrderOrder; +use PluginOrderProfile; +use PluginOrderReference; +use ProfileRight; + +final class ProfileTest extends OrderTestCase +{ + public function testGetAllRightsDeclaresTheThreeRightBuckets(): void + { + $rights = PluginOrderProfile::getAllRights(); + + $fields = array_column($rights, 'field'); + $this->assertContains(PluginOrderOrder::$rightname, $fields); + $this->assertContains(PluginOrderReference::$rightname, $fields); + $this->assertContains(PluginOrderBill::$rightname, $fields); + + $itemtypes = array_column($rights, 'itemtype'); + $this->assertContains(PluginOrderOrder::class, $itemtypes); + $this->assertContains(PluginOrderReference::class, $itemtypes); + $this->assertContains(PluginOrderBill::class, $itemtypes); + } + + public function testEveryDeclaredRightIsRegisteredInProfileRights(): void + { + // initProfile() is run on plugin activation; the columns must already exist. + foreach (PluginOrderProfile::getAllRights(true) as $data) { + $this->assertGreaterThan( + 0, + countElementsInTable('glpi_profilerights', ['name' => $data['field']]), + sprintf('Right "%s" is not registered in glpi_profilerights', $data['field']), + ); + } + } + + public function testToggleOrderRightBitOnProfile(): void + { + $profile_right = new ProfileRight(); + $profile_right->getFromDBByCrit([ + 'profiles_id' => getItemByTypeName('Profile', 'Super-Admin', true), + 'name' => PluginOrderOrder::$rightname, + ]); + + $this->addRightToProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_DELIVERY); + + $profile_right->getFromDB($profile_right->getID()); + $this->assertNotSame(0, (int) $profile_right->fields['rights'] & PluginOrderOrder::RIGHT_DELIVERY); + + $this->removeRightFromProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_DELIVERY); + + $profile_right->getFromDB($profile_right->getID()); + $this->assertSame(0, (int) $profile_right->fields['rights'] & PluginOrderOrder::RIGHT_DELIVERY); + } +} diff --git a/tests/Units/ReferenceTest.php b/tests/Units/ReferenceTest.php new file mode 100644 index 0000000000..9d7d6d0a93 --- /dev/null +++ b/tests/Units/ReferenceTest.php @@ -0,0 +1,158 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use Computer; +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderReference; +use PluginOrderReference_Supplier; + +final class ReferenceTest extends OrderTestCase +{ + public function testCreateReference(): void + { + $this->login(); + + $reference = $this->createReference(); + + $this->assertSame(Computer::class, $reference->fields['itemtype']); + $this->assertSame(1, (int) $reference->fields['is_active']); + } + + public function testCreateReferenceWithoutNameFails(): void + { + $this->login(); + + $reference = new PluginOrderReference(); + $id = $reference->add([ + 'entities_id' => $this->getTestRootEntity(true), + 'itemtype' => Computer::class, + ]); + + $this->assertFalse($id); + $this->hasSessionMessages(ERROR, ['Cannot create reference without a name']); + } + + public function testCreateReferenceWithoutItemtypeFails(): void + { + $this->login(); + + $reference = new PluginOrderReference(); + $id = $reference->add([ + 'name' => 'No itemtype', + 'entities_id' => $this->getTestRootEntity(true), + 'itemtype' => '', + ]); + + $this->assertFalse($id); + $this->hasSessionMessages(ERROR, ['Cannot create reference without a type']); + } + + public function testDuplicateNameInSameEntityIsRejected(): void + { + $this->login(); + + $name = 'Duplicate Reference_' . $this->getUniqueString(); + $entities_id = $this->getTestRootEntity(true); + + $reference1 = new PluginOrderReference(); + $id1 = $reference1->add([ + 'name' => $name, + 'entities_id' => $entities_id, + 'itemtype' => Computer::class, + ]); + $this->assertGreaterThan(0, $id1); + + $reference2 = new PluginOrderReference(); + $id2 = $reference2->add([ + 'name' => $name, + 'entities_id' => $entities_id, + 'itemtype' => Computer::class, + ]); + $this->assertFalse($id2); + $this->hasSessionMessages(ERROR, ['A reference with the same name still exists']); + } + + public function testLinkReferenceToSupplier(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $reference = $this->createReference($supplier, Computer::class, 150.5); + + $links = (new PluginOrderReference_Supplier())->find([ + 'plugin_order_references_id' => $reference->getID(), + 'suppliers_id' => $supplier->getID(), + ]); + + $this->assertCount(1, $links); + $link = reset($links); + $this->assertEqualsWithDelta(150.5, (float) $link['price_taxfree'], 0.001); + } + + public function testUpdateReference(): void + { + $this->login(); + + $reference = $this->createReference(); + + $this->updateItem(PluginOrderReference::class, $reference->getID(), [ + 'comment' => 'Updated reference comment', + ]); + + $reference->getFromDB($reference->getID()); + $this->assertSame('Updated reference comment', $reference->fields['comment']); + } + + public function testDeleteUnusedReference(): void + { + $this->login(); + + $reference = $this->createReference(); + + $this->assertTrue($reference->delete(['id' => $reference->getID()], true)); + $this->assertFalse((new PluginOrderReference())->getFromDB($reference->getID())); + } + + public function testDeletingReferenceInUseIsBlocked(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier); + $this->addReferenceToOrder($order, $reference); + + $this->assertFalse($reference->delete(['id' => $reference->getID()], true)); + $this->assertTrue((new PluginOrderReference())->getFromDB($reference->getID())); + $this->hasSessionMessages(ERROR, ['Reference(s) in use']); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000000..dd47afaba5 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,36 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +require __DIR__ . '/../../../tests/bootstrap.php'; +require __DIR__ . '/../vendor/autoload.php'; + +if (!Plugin::isPluginActive('order')) { + throw new RuntimeException('Plugin order is not active in the test database'); +}