diff --git a/CHANGELOG.md b/CHANGELOG.md index 1872d0b..3425412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] -### Fixed +### Added +- Add Links for uninstall templates From Item Form - Fix SQL errors when uninstalling or replacing peripheral assets - Fix locales encoding diff --git a/ajax/dropdownReplaceFindDevice.php b/ajax/dropdownReplaceFindDevice.php index 85cbf49..f2528de 100644 --- a/ajax/dropdownReplaceFindDevice.php +++ b/ajax/dropdownReplaceFindDevice.php @@ -50,9 +50,9 @@ throw new AccessDeniedHttpException(__s("You don't have permission to perform this action.")); } -if (class_exists($_REQUEST['itemtype']) && is_a($_REQUEST['itemtype'], CommonDBTM::class, true)) { +$item = getItemForItemtype($_REQUEST['itemtype']); +if ($item instanceof CommonDBTM) { $itemtypeisplugin = isPluginItemType($_REQUEST['itemtype']); - $item = new $_REQUEST['itemtype'](); $table = getTableForItemType($_REQUEST['itemtype']); $options = []; $count = 0; diff --git a/front/config.form.php b/front/config.form.php index 5c6dad1..ed15f50 100644 --- a/front/config.form.php +++ b/front/config.form.php @@ -28,6 +28,8 @@ * ------------------------------------------------------------------------- */ +declare(strict_types=1); + Session::checkRight('config', UPDATE); /** @var array $CFG_GLPI */ diff --git a/inc/state.class.php b/inc/state.class.php index be19111..0b5857e 100644 --- a/inc/state.class.php +++ b/inc/state.class.php @@ -28,9 +28,7 @@ * ------------------------------------------------------------------------- */ -use function Safe\json_encode; -use function Safe\ob_end_clean; -use function Safe\ob_start; +use Glpi\Application\View\TemplateRenderer; class PluginUninstallState { @@ -58,36 +56,17 @@ public static function replaceState($params = []) 'complete' => true, ]); - // get form for uninstall actions - ob_start(); - PluginUninstallUninstall::showFormUninstallation($items_id, $item, $users_id); - $html_modal = ob_get_contents(); - ob_end_clean(); + // Get the uninstall actions form as a string (no output buffering). + $html_modal = PluginUninstallUninstall::showFormUninstallation($items_id, $item, $users_id, 0, false); - // we json encore to pass it to js (auto-escaping) - $html = json_encode(" - {$states_name} - " - . __s("Update") - . ""); - $modal_body = json_encode($html_modal); - - $JS = <<display('@uninstall/state_replace.html.twig', [ + 'rand' => mt_rand(), + 'states_name' => $states_name, + 'modal' => $html_modal, + ]); - glpi_html_dialog({ - body: {$modal_body} - }) - }); - }); -JAVASCRIPT; - echo Html::scriptBlock($JS); return null; } } diff --git a/inc/uninstall.class.php b/inc/uninstall.class.php index 6ff8ee9..13d8748 100644 --- a/inc/uninstall.class.php +++ b/inc/uninstall.class.php @@ -29,8 +29,7 @@ */ use Glpi\Asset\Asset_PeripheralAsset; - -use function Safe\preg_grep; +use Glpi\Application\View\TemplateRenderer; /** * ------------------------------------------------------------------------- @@ -60,6 +59,8 @@ * ------------------------------------------------------------------------- */ +use function Safe\preg_grep; + class PluginUninstallUninstall extends CommonDBTM { public const PLUGIN_UNINSTALL_TRANSFER_NAME = "plugin_uninstall"; @@ -921,61 +922,165 @@ public static function getInfocomPresentForDevice($type, $ID) /** - * @param $ID - * @param $item - * @param $user_id - **/ - public static function showFormUninstallation($ID, $item, $user_id) + * Render the "apply uninstall/replace model" form. + * + * @param int|string $ID id of the item the form applies to + * @param CommonGLPI $item item the form applies to + * @param int $user_id current user id (for stored location preference) + * @param int $templates_id 0 for a fresh model selector, otherwise the model to apply + * @param bool $display true echoes the form, false returns it as a string + * + * @return string|null the HTML when $display is false + **/ + public static function showFormUninstallation($ID, $item, $user_id, $templates_id = 0, $display = true) { /** * @var array $CFG_GLPI */ - global $CFG_GLPI; + global $CFG_GLPI, $DB; $type = $item->getType(); - echo "
"; - echo Html::hidden('device_type', ['value' => $type]); - echo ""; - echo ""; - echo ""; + $entities_id = $item->fields["entities_id"]; + + if ($templates_id == 0) { + $rand = mt_rand(); + $model_dropdown = self::dropdownUninstallModels( + "model_id", + $_SESSION["glpiID"], + $entities_id, + ['display' => false, 'rand' => $rand], + ); - $params = ['templates_id' => '__VALUE__', - 'entity' => $item->fields["entities_id"], - 'users_id' => $_SESSION["glpiID"], - ]; + $params = [ + 'templates_id' => '__VALUE__', + 'entity' => $entities_id, + 'users_id' => $_SESSION["glpiID"], + ]; + + $onselect_js = Ajax::updateItemOnSelectEvent( + 'dropdown_model_id' . $rand, + "show_objects", + $CFG_GLPI['root_doc'] . "/plugins/uninstall/ajax/locations.php", + $params, + false, + ); - Ajax::updateItemOnSelectEvent( - 'dropdown_model_id' . $rand, - "show_objects", - $CFG_GLPI['root_doc'] . "/plugins/uninstall/ajax/locations.php", - $params, - ); + $location_html = "" . Dropdown::EMPTY_VALUE . ""; + } else { + $used = []; + if (!PluginUninstallModel::canReplace()) { + $used = array_column( + iterator_to_array( + $DB->request([ + 'SELECT' => ['id'], + 'FROM' => 'glpi_plugin_uninstall_models', + 'WHERE' => [ + 'types_id' => [2, 3], + ], + ]), + ), + 'id', + ); + } + + $model_dropdown = PluginUninstallModel::dropdown([ + 'name' => "model_id", + 'value' => $templates_id, + 'entity' => $entities_id, + 'used' => $used, + 'display' => false, + ]); + + $location = PluginUninstallPreference::getLocationByUserByEntity( + $user_id, + $templates_id, + $entities_id, + ); + $location_html = Location::dropdown([ + 'value' => ($location == '' ? 0 : $location), + 'comments' => 1, + 'entity' => $entities_id, + 'toadd' => [ + -1 => __('Keep previous location', 'uninstall'), + 0 => __('Empty location', 'uninstall'), + ], + 'display' => false, + ]); + } + } + + $html = TemplateRenderer::getInstance()->render('@uninstall/form_uninstallation.html.twig', [ + 'supported' => $supported, + 'action_url' => $CFG_GLPI['root_doc'] . "/plugins/uninstall/front/action.php", + 'device_type' => $type, + 'item_id' => $ID, + 'model_dropdown' => $model_dropdown, + 'location_html' => $location_html, + 'onselect_js' => $onselect_js, + ]); + if ($display) { + echo $html; + return null; } - echo ""; - echo "\n"; - echo ""; + return $html; + } - echo ""; - echo "
" . __s("Apply model", 'uninstall') . "
" . __s("Model") . ""; - if (class_exists($type) && is_a($type, CommonDBTM::class, true)) { + $item = getItemForItemtype($type); + $supported = $item instanceof CommonDBTM; - $item = new $type(); + $model_dropdown = ''; + $location_html = ''; + $onselect_js = ''; + + if ($supported) { $item->getFromDB($ID); - $rand = self::dropdownUninstallModels( - "model_id", - $_SESSION["glpiID"], - $item->fields["entities_id"], - ); - echo "
" . __s("Item's location after applying model", "uninstall") . "\n" . Dropdown::EMPTY_VALUE . "
"; - echo ""; - echo ""; - echo "
"; - Html::closeForm(); + public static function showLinksUninstallation( + $params, + ) { + /** + * @var array $UNINSTALL_TYPES + */ + global $DB, $UNINSTALL_TYPES; + + $right = Session::haveRight(self::$rightname, READ); + + $users_id = Session::getLoginUserID(); + $item = $params['item']; + if ( + !$right + || !in_array($item->getType(), $UNINSTALL_TYPES) + || $item->getID() <= 0 + ) { + return null; + } + + $criteria = [ + "FROM" => 'glpi_plugin_uninstall_models', + ]; + + if (!PluginUninstallModel::canReplace()) { + $criteria['WHERE'] = ['NOT' => ['types_id' => [2, 3]]]; + } + + $links = []; + foreach ($DB->request($criteria) as $data) { + $links[] = [ + 'id' => (int) $data['id'], + 'name' => $data['name'], + // The modal body is captured as a string (no output buffering) + // and rendered inside an inert