diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index cf34169..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * ------------------------------------------------------------------------- - * Deploy plugin for GLPI - * ------------------------------------------------------------------------- - * - * LICENSE - * - * This file is part of Deploy. - * - * Deploy 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. - * - * Deploy 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 Deploy. If not, see . - * ------------------------------------------------------------------------- - * @copyright Copyright (C) 2022-2024 by Deploy plugin team. - * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html - * @link https://github.com/pluginsGLPI/deploy - * ------------------------------------------------------------------------- - */ - -module.exports = { - "root": true, - "ignorePatterns": [ - "/lib/*", - "/vendor/*", - ], - "env": { - "browser": true, - "es6": true, - "jquery": true, - }, - "extends": "eslint:recommended", - "globals": { - "CFG_GLPI": true, - "GLPI_PLUGINS_PATH": true, - "__": true, - "_n": true, - "_x": true, - "_nx": true - }, - "parserOptions": { - "ecmaVersion": 8, - }, - "plugins": [ - "@stylistic/js", - ], - "rules": { - "no-console": ["error", {"allow": ["warn", "error"]}], - "no-unused-vars": ["error", {"vars": "local"}], - "@stylistic/js/eol-last": ["error", "always"], - "@stylistic/js/indent": ["error", 4], - "@stylistic/js/linebreak-style": ["error", "unix"], - "@stylistic/js/semi": ["error", "always"], - }, - "overrides": [ - { - "files": [".eslintrc.js", ".stylelintrc.js"], - "env": { - "node": true - } - }, - ], -}; diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bdde6c1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Change Log + +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] + +### Fixed + +- Fix plugin installation failing on raw queries executed through `DBmysql::request()` +- Fix fatal error caused by missing `bool` return types on computer group rights methods +- Fix plugin uninstallation failing and leaving package tables and display preferences behind +- Fix PHP 8.4 deprecation on implicitly nullable parameters +- Replace deprecated `Html::displayErrorAndDie()` and `Html::displayRightError()` calls with HTTP exceptions +- CI: fix PHPStan bootstrap for GLPI 11, migrate ESLint configuration to flat config, drop the stray `glpi-project/tools` composer dependency, declare a unique composer autoloader suffix diff --git a/composer.json b/composer.json index e9108b8..851fa53 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,6 @@ "php": ">=8.1" }, "require-dev": { - "glpi-project/tools": "^0.8.4", "php-parallel-lint/php-parallel-lint": "^1.4", "phpstan/extension-installer": "^1.4", "phpstan/phpstan": "^1.10", @@ -11,6 +10,7 @@ "squizlabs/php_codesniffer": "^4.0" }, "config": { + "autoloader-suffix": "PluginDeploy", "optimize-autoloader": true, "platform": { "php": "8.1" diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..79b783c --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,22 @@ +import glpiEslintConfig from '../../eslint.config.mjs'; + +const filteredConfig = glpiEslintConfig.filter(config => !config.ignores); + +export default [ + ...filteredConfig, + { + ignores: [ + 'lib/*', + 'node_modules/*', + 'vendor/*', + ], + }, + { + languageOptions: { + globals: { + GLPI_PLUGINS_PATH: true, + noUiSlider: true, + }, + }, + }, +]; diff --git a/front/package.php b/front/package.php index 7799537..3aab177 100644 --- a/front/package.php +++ b/front/package.php @@ -30,6 +30,7 @@ namespace GlpiPlugin\Deploy; +use Glpi\Exception\Http\AccessDeniedHttpException; use Html; use Search; use Session; @@ -38,6 +39,10 @@ Session::checkRight("dashboard", UPDATE); +if (!Package::canView()) { + throw new AccessDeniedHttpException(); +} + Html::header( Package::getTypeName(Session::getPluralNumber()), '', @@ -46,11 +51,6 @@ 'package' ); -$package = new Package(); -if ($package->canView()) { - Search::show('GlpiPlugin\Deploy\Package'); -} else { - Html::displayRightError(); -} +Search::show('GlpiPlugin\Deploy\Package'); Html::footer(); diff --git a/hook.php b/hook.php index 97ca5f4..b8bf3cf 100644 --- a/hook.php +++ b/hook.php @@ -32,13 +32,12 @@ use GlpiPlugin\Deploy\Computer\GroupDynamic; use GlpiPlugin\Deploy\Computer\GroupStatic; use GlpiPlugin\Deploy\Package; -use GlpiPlugin\Deploy\PackageJob; use GlpiPlugin\Deploy\PackageAction; use GlpiPlugin\Deploy\PackageCheck; use GlpiPlugin\Deploy\PackageFile; +use GlpiPlugin\Deploy\PackageJob; use GlpiPlugin\Deploy\PackageTarget; use GlpiPlugin\Deploy\Profile; -use GlpiPlugin\Deploy\PackageTimeslot; use GlpiPlugin\Deploy\Repository; use GlpiPlugin\Deploy\Timeslot; use GlpiPlugin\Deploy\TimeslotRange; @@ -71,7 +70,7 @@ * ------------------------------------------------------------------------- */ - // Define Dropdown tables to be manage in GLPI : +// Define Dropdown tables to be manage in GLPI : function plugin_deploy_getDropdown() { $dropdowns = [Timeslot::class => Timeslot::getTypeName(2)]; @@ -103,16 +102,18 @@ function plugin_deploy_install() /** * Plugin uninstall process * - * @return boolean + * @return bool */ function plugin_deploy_uninstall() { $migration = new Migration(PLUGIN_DEPLOY_VERSION); + PackageAction::uninstall($migration); + PackageCheck::uninstall($migration); + PackageFile::uninstall($migration); PackageTarget::uninstall($migration); Package::uninstall($migration); PackageJob::uninstall($migration); - PackageTarget::uninstall($migration); Profile::uninstall($migration); Repository::uninstall($migration); Group::uninstall($migration); diff --git a/javascript/timeslot.js b/javascript/timeslot.js index 32bc747..c8c4217 100644 --- a/javascript/timeslot.js +++ b/javascript/timeslot.js @@ -26,147 +26,150 @@ * ------------------------------------------------------------------------- */ -var AJAX_URL = CFG_GLPI.root_doc + '/' + GLPI_PLUGINS_PATH.deploy + '/ajax/timeslot.php'; - -var timeslot = {}; -var timeslotsData = JSON.parse(document.getElementById('timeslotsData').dataset.value); - -var everydayButton = document.getElementById('everyday'); -var daysLength = parseInt(document.getElementById('daysLength').dataset.value); -var timeslot_id = parseInt(document.getElementById('timeslotId').dataset.value); - -function setSliderValues(slider, values) { - slider.noUiSlider.set(values); -} - -function toggleSlider(slider, checkbox, addRangeButton, delRangeButton, i) { - if (checkbox.checked) { - addRangeButton.removeAttribute('disabled'); - delRangeButton.removeAttribute('disabled'); - setSliderValues(slider, timeslotsData[i] ? timeslotsData[i].map(slot => [slot.starttime, slot.endtime]).flat() : [8, 12, 14, 18]); - slider.style.display = 'block'; - } else { - addRangeButton.setAttribute('disabled', true); - delRangeButton.setAttribute('disabled', true); - slider.style.display = 'none'; + +(() => { + const AJAX_URL = `${CFG_GLPI.root_doc}/${GLPI_PLUGINS_PATH.deploy}/ajax/timeslot.php`; + + const timeslot = {}; + const timeslotsData = JSON.parse(document.getElementById('timeslotsData').dataset.value); + + const everydayButton = document.getElementById('everyday'); + const daysLength = parseInt(document.getElementById('daysLength').dataset.value); + const timeslot_id = parseInt(document.getElementById('timeslotId').dataset.value); + + function setSliderValues(slider, values) { + slider.noUiSlider.set(values); } - timeslot[i]['is_enable'] = +checkbox.checked; - document.getElementById('timeslot').value = JSON.stringify(timeslot); -} - -function sendAjaxRequest(action, timeslot, timeslot_id) { - $.ajax({ - method: 'POST', - url: AJAX_URL, - data: { - action: action, - timeslot: timeslot, - plugin_deploy_timeslots_id: timeslot_id - } - }).done(function(response) { - $('#tr_countainer').html(response); - }); -} - -for (let i = 1; i <= daysLength; i++) { - const slider = document.getElementById('slider' + i); - const checkbox = document.getElementById('notimeslot' + i); - const alldayButton = document.getElementById('allday' + i); - const addRangeButton = document.getElementById('addrange' + i); - const delRangeButton = document.getElementById('delrange' + i); - - timeslot[i] = { - is_enable: +checkbox.checked - }; - - noUiSlider.create(slider, { - start: timeslotsData[i] ? timeslotsData[i].map(slot => [slot.starttime, slot.endtime]).flat() : [0, 0, 0, 0], - connect: [false, ...Array(timeslotsData[i].length * 2).fill().flatMap((_, idx) => idx % 2 === 0 ? [true, false] : [])], - behaviour: 'drag', - step: 1, - range: { - 'min': 0, - 'max': 24 - }, - margin: 1, - }); - slider.noUiSlider.on('update', function(values, handle) { - timeslot[i]['is_enable'] = +checkbox.checked; - const order = Math.floor(handle / 2); - const start = document.getElementById('value' + order + '_start' + i); - const end = document.getElementById('value' + order + '_end' + i); - if (handle % 2 === 1) { - end.value = values[handle]; + function toggleSlider(slider, checkbox, addRangeButton, delRangeButton, i) { + if (checkbox.checked) { + addRangeButton.removeAttribute('disabled'); + delRangeButton.removeAttribute('disabled'); + setSliderValues(slider, timeslotsData[i] ? timeslotsData[i].map(slot => [slot.starttime, slot.endtime]).flat() : [8, 12, 14, 18]); + slider.style.display = 'block'; } else { - start.value = values[handle]; + addRangeButton.setAttribute('disabled', true); + delRangeButton.setAttribute('disabled', true); + slider.style.display = 'none'; } - timeslot[i][order] = { - starttime: start.value, - endtime: end.value - }; + timeslot[i]['is_enable'] = +checkbox.checked; document.getElementById('timeslot').value = JSON.stringify(timeslot); - }); + } - // Disable slider if checkbox is not checked - toggleSlider(slider, checkbox, addRangeButton, delRangeButton, i); + function sendAjaxRequest(action, timeslot, timeslot_id) { + $.ajax({ + method: 'POST', + url: AJAX_URL, + data: { + action: action, + timeslot: timeslot, + plugin_deploy_timeslots_id: timeslot_id + } + }).done((response) => { + $('#tr_countainer').html(response); + }); + } - // Enable or disable slider on checkbox change - checkbox.addEventListener('change', function() { - toggleSlider(slider, this, addRangeButton, delRangeButton, i); - }); + for (let i = 1; i <= daysLength; i++) { + const slider = document.getElementById(`slider${i}`); + const checkbox = document.getElementById(`notimeslot${i}`); + const alldayButton = document.getElementById(`allday${i}`); + const addRangeButton = document.getElementById(`addrange${i}`); + const delRangeButton = document.getElementById(`delrange${i}`); - alldayButton.addEventListener('click', function(event) { timeslot[i] = { - 0: { - starttime: '0.00', - endtime: '24.00' - }, - is_enable: 1 + is_enable: +checkbox.checked }; - document.getElementById('timeslot').value = JSON.stringify(timeslot); - sendAjaxRequest('add', timeslot, timeslot_id); - }); - // Disable add button if there are already 12 ranges - if (Object.keys(timeslot[i]).length - 1 >= 12) { - addRangeButton.setAttribute('disabled', true); - } + noUiSlider.create(slider, { + start: timeslotsData[i] ? timeslotsData[i].map(slot => [slot.starttime, slot.endtime]).flat() : [0, 0, 0, 0], + connect: [false, ...Array(timeslotsData[i].length * 2).fill().flatMap((_, idx) => idx % 2 === 0 ? [true, false] : [])], + behaviour: 'drag', + step: 1, + range: { + 'min': 0, + 'max': 24 + }, + margin: 1, + }); + + slider.noUiSlider.on('update', (values, handle) => { + timeslot[i]['is_enable'] = +checkbox.checked; + const order = Math.floor(handle / 2); + const start = document.getElementById(`value${order}_start${i}`); + const end = document.getElementById(`value${order}_end${i}`); + if (handle % 2 === 1) { + end.value = values[handle]; + } else { + start.value = values[handle]; + } + timeslot[i][order] = { + starttime: start.value, + endtime: end.value + }; + document.getElementById('timeslot').value = JSON.stringify(timeslot); + }); + + // Disable slider if checkbox is not checked + toggleSlider(slider, checkbox, addRangeButton, delRangeButton, i); + + // Enable or disable slider on checkbox change + checkbox.addEventListener('change', function() { + toggleSlider(slider, this, addRangeButton, delRangeButton, i); + }); + + alldayButton.addEventListener('click', () => { + timeslot[i] = { + 0: { + starttime: '0.00', + endtime: '24.00' + }, + is_enable: 1 + }; + document.getElementById('timeslot').value = JSON.stringify(timeslot); + sendAjaxRequest('add', timeslot, timeslot_id); + }); + + // Disable add button if there are already 12 ranges + if (Object.keys(timeslot[i]).length - 1 >= 12) { + addRangeButton.setAttribute('disabled', true); + } - addRangeButton.addEventListener('click', function(event) { - const lastKey = Object.keys(timeslot[i]).length - 1; - timeslot[i][lastKey + 1] = { - starttime: '23.00', - endtime: '24.00' - }; - document.getElementById('timeslot').value = JSON.stringify(timeslot); - sendAjaxRequest('add', timeslot, timeslot_id); - }); + addRangeButton.addEventListener('click', () => { + const lastKey = Object.keys(timeslot[i]).length - 1; + timeslot[i][lastKey + 1] = { + starttime: '23.00', + endtime: '24.00' + }; + document.getElementById('timeslot').value = JSON.stringify(timeslot); + sendAjaxRequest('add', timeslot, timeslot_id); + }); + + // Disable delete button if there is only 1 range + if (Object.keys(timeslot[i]).length - 1 === 1) { + delRangeButton.setAttribute('disabled', true); + } + + delRangeButton.addEventListener('click', () => { + const lastKey = Object.keys(timeslot[i]).length - 1; + delete timeslot[i][lastKey - 1]; + document.getElementById('timeslot').value = JSON.stringify(timeslot); + sendAjaxRequest('add', timeslot, timeslot_id); + }); - // Disable delete button if there is only 1 range - if (Object.keys(timeslot[i]).length - 1 === 1) { - delRangeButton.setAttribute('disabled', true); } - delRangeButton.addEventListener('click', function(event) { - const lastKey = Object.keys(timeslot[i]).length - 1; - delete timeslot[i][lastKey - 1]; - document.getElementById('timeslot').value = JSON.stringify(timeslot); - sendAjaxRequest('add', timeslot, timeslot_id); + everydayButton.addEventListener('click', () => { + for (let i = 1; i <= daysLength; i++) { + timeslot[i] = { + 0: { + starttime: '0.00', + endtime: '24.00' + }, + is_enable: 1 + }; + document.getElementById('timeslot').value = JSON.stringify(timeslot); + document.getElementById("rangeform").submit(); + } }); - -} - -everydayButton.addEventListener('click', function(event) { - for (let i = 1; i <= daysLength; i++) { - timeslot[i] = { - 0: { - starttime: '0.00', - endtime: '24.00' - }, - is_enable: 1 - }; - document.getElementById('timeslot').value = JSON.stringify(timeslot); - document.getElementById("rangeform").submit(); - } -}); +})(); diff --git a/phpstan.neon b/phpstan.neon index 788e872..9515ab8 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,7 +3,8 @@ parameters: maximumNumberOfProcesses: 2 level: 1 bootstrapFiles: - - ../../inc/based_config.php + - ../../stubs/glpi_constants.php + - ../../vendor/autoload.php paths: - ajax - front @@ -13,7 +14,3 @@ parameters: scanDirectories: - ../../inc - ../../src - stubFiles: - - ../../stubs/glpi_constants.php -rules: - - GlpiProject\Tools\PHPStan\Rules\GlobalVarTypeRule diff --git a/src/Computer/Group.php b/src/Computer/Group.php index b04172c..851066d 100644 --- a/src/Computer/Group.php +++ b/src/Computer/Group.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ - namespace GlpiPlugin\Deploy\Computer; +namespace GlpiPlugin\Deploy\Computer; use CommonDBTM; use Computer; @@ -37,7 +37,6 @@ use GlpiPlugin\Deploy\PackageTarget; use GlpiPlugin\Deploy\Timeslot; use Migration; -use Search; use Session; class Group extends CommonDBTM @@ -51,12 +50,12 @@ public static function getTypeName($nb = 0) return _n('Computer Group', 'Computers Group', $nb, 'deploy'); } - public static function canCreate() + public static function canCreate(): bool { return Session::haveRight(static::$rightname, UPDATE); } - public static function canPurge() + public static function canPurge(): bool { return Session::haveRight(static::$rightname, UPDATE); } @@ -81,7 +80,7 @@ public function rawSearchOptions() 'field' => 'id', 'name' => __('ID'), 'massiveaction' => false, // implicit field is id - 'datatype' => 'number' + 'datatype' => 'number', ]; $tab[] = [ @@ -89,7 +88,7 @@ public function rawSearchOptions() 'table' => $this->getTable(), 'field' => 'comment', 'name' => __('Comment'), - 'datatype' => 'text' + 'datatype' => 'text', ]; $tab[] = [ @@ -145,9 +144,9 @@ public function rawSearchOptions() 'table' => GroupStatic::getTable(), 'joinparams' => [ 'jointype' => 'child', - ] - ] - ] + ], + ], + ], ]; $tab[] = [ @@ -163,9 +162,9 @@ public function rawSearchOptions() 'table' => PackageTarget::getTable(), 'joinparams' => [ 'jointype' => 'child', - ] - ] - ] + ], + ], + ], ]; return $tab; @@ -179,13 +178,13 @@ public function showForm($id, array $options = []) } else { $this->getEmpty(); } - $this->initForm($id, $options); + $this->initForm($id, $options); - TemplateRenderer::getInstance()->display('generic_show_form.html.twig', [ - 'item' => $this, - 'params' => $options, - ]); - return true; + TemplateRenderer::getInstance()->display('generic_show_form.html.twig', [ + 'item' => $this, + 'params' => $options, + ]); + return true; } public function countDynamicItem() @@ -194,7 +193,7 @@ public function countDynamicItem() $group = new GroupDynamic(); if ( $group->getFromDBByCrit([ - 'plugin_deploy_computers_groups_id' => $this->fields['id'] + 'plugin_deploy_computers_groups_id' => $this->fields['id'], ]) ) { $count = $group->countDynamicItems(); @@ -265,15 +264,15 @@ public static function install(Migration $migration) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; $DB->doQuery($query) or die($DB->error()); - // install default display preferences + // install default display preferences - // add display preferences + // add display preferences $nb_display_pref = countElementsInTable(DisplayPreference::getTable(), [ - 'itemtype' => self::getType() + 'itemtype' => self::getType(), ]); if ($nb_display_pref == 0) { - $dp = new DisplayPreference(); - $i = 1; + $dp = new DisplayPreference(); + $i = 1; foreach ([3, 5, 6] as $id_so) { $dp->add([ 'itemtype' => self::getType(), @@ -305,9 +304,4 @@ public static function getIcon() { return "ti ti-sitemap"; } - - - public function post_purgeItem() - { - } } diff --git a/src/Computer/GroupDynamic.php b/src/Computer/GroupDynamic.php index 817c1f5..90eb0a0 100644 --- a/src/Computer/GroupDynamic.php +++ b/src/Computer/GroupDynamic.php @@ -50,13 +50,13 @@ public static function getTypeName($nb = 0) } - public static function canCreate() + public static function canCreate(): bool { return Session::haveRight(static::$rightname, UPDATE); } - public static function canPurge() + public static function canPurge(): bool { return Session::haveRight(static::$rightname, UPDATE); } @@ -70,7 +70,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) $computergroup_dynamic = new self(); if ( $computergroup_dynamic->getFromDBByCrit([ - 'plugin_deploy_computers_groups_id' => $item->getID() + 'plugin_deploy_computers_groups_id' => $item->getID(), ]) ) { $count = $computergroup_dynamic->countDynamicItems(); @@ -126,7 +126,7 @@ public static function getSpecificValueToDisplay($field, $values, array $options $line_delimiter = '
'; } - //move full list to tooltip if needed + //move full list to tooltip if needed if ( count($values) > 1 && Toolbox::strlen($value) > $CFG_GLPI['cut'] @@ -144,7 +144,7 @@ public static function getSpecificValueToDisplay($field, $values, array $options 'awesome-class' => 'fa-comments', 'display' => false, 'autoclose' => false, - 'onclick' => true + 'onclick' => true, ] ); $out .= $values[0] . $valTip; @@ -187,7 +187,7 @@ public function isDynamicSearchMatchComputer(Computer $computer) { $count = 0; - //add new criteria to force computer ID + //add new criteria to force computer ID $search = unserialize($this->fields['search']); $search['criteria'][] = [ "link" => "AND", @@ -217,11 +217,11 @@ public static function showForItem(Group $computergroup) $canedit = $computergroup->canEdit($ID); if ($canedit) { $firsttime = true; - //load dynamic search criteria from DB if exist + //load dynamic search criteria from DB if exist $computergroup_dynamic = new self(); if ( $computergroup_dynamic->getFromDBByCrit([ - 'plugin_deploy_computers_groups_id' => $ID + 'plugin_deploy_computers_groups_id' => $ID, ]) ) { $computers_params = unserialize($computergroup_dynamic->fields['search']); @@ -229,7 +229,7 @@ public static function showForItem(Group $computergroup) $p = $search_params = Search::manageParams('Computer', $computers_params); $firsttime = false; } else { - //retrieve filter value from search if exist and reset it + //retrieve filter value from search if exist and reset it $_GET["reset"] = true; $p = $search_params = Search::manageParams('Computer', $_GET); if (isset($_SESSION['glpisearch']['Computer'])) { @@ -237,21 +237,21 @@ public static function showForItem(Group $computergroup) } } - //redirect to computergroup dynamic tab after saved search + //redirect to computergroup dynamic tab after saved search $target = Group::getFormURLWithID($ID); $target .= "&_glpi_tab=Computer_GroupDynamic$1"; $p['target'] = $target; $p['addhidden'] = [ 'plugin_deploy_computers_groups_id' => $computergroup->getID(), 'id' => $computergroup->getID(), - 'start' => 0 + 'start' => 0, ]; $p['actionname'] = 'save'; $p['actionvalue'] = _sx('button', 'Save'); $p['showbookmark'] = false; Search::showGenericSearch(Computer::getType(), $p); - //display result from search + //display result from search if (!$firsttime) { $data = Search::prepareDatasForSearch('Computer', $search_params); Search::constructSQL($data); @@ -261,7 +261,7 @@ public static function showForItem(Group $computergroup) $data['search']['is_deleted'] = false; Search::displayData($data); - //remove search header(trashbin / map switch) + //remove search header(trashbin / map switch) echo Html::scriptBlock(" $(document).ready( function() { diff --git a/src/Computer/GroupStatic.php b/src/Computer/GroupStatic.php index 9c9a802..0c6c825 100644 --- a/src/Computer/GroupStatic.php +++ b/src/Computer/GroupStatic.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ - namespace GlpiPlugin\Deploy\Computer; +namespace GlpiPlugin\Deploy\Computer; use CommonDBRelation; use CommonGLPI; @@ -36,15 +36,13 @@ use Dropdown; use Entity; use Glpi\Application\View\TemplateRenderer; -use Html; use Migration; -use Search; use Session; use Toolbox; class GroupStatic extends CommonDBRelation { - // From CommonDBRelation + // From CommonDBRelation public static $itemtype_1 = 'GlpiPlugin\Deploy\Computer\Group'; public static $items_id_1 = 'plugin_deploy_computers_groups_id'; public static $itemtype_2 = 'Computer'; @@ -63,19 +61,19 @@ public static function getTypeName($nb = 0) } - public static function canCreate() + public static function canCreate(): bool { return Session::haveRight(static::$rightname, UPDATE); } - public function canCreateItem() + public function canCreateItem(): bool { return Session::haveRight(static::$rightname, UPDATE); } - public static function canPurge() + public static function canPurge(): bool { return Session::haveRight(static::$rightname, UPDATE); return true; diff --git a/src/Package.php b/src/Package.php index a916141..0fe589c 100644 --- a/src/Package.php +++ b/src/Package.php @@ -30,13 +30,12 @@ namespace GlpiPlugin\Deploy; -use Agent; use CommonDBTM; -use Migration; use DBConnection; use DisplayPreference; use Entity; use Glpi\Application\View\TemplateRenderer; +use Migration; class Package extends CommonDBTM { @@ -73,7 +72,7 @@ public function defineTabs($options = []) public function showDebug() { TemplateRenderer::getInstance()->display('@deploy/package/debug_json.html.twig', [ - 'json' => self::getJson($this, true) + 'json' => self::getJson($this, true), ]); } @@ -120,12 +119,12 @@ public static function moveSubitem( if ($ref_ID) { // Move after/before an existing line $subitem->getFromDB($ref_ID); $new_rank = $subitem->fields["order"]; - } else if ($type == self::MOVE_AFTER) { + } elseif ($type == self::MOVE_AFTER) { // Move after all $result = $DB->request([ 'SELECT' => ['MAX' => 'order AS maxi'], 'FROM' => $subitem::getTable(), - 'WHERE' => ['plugin_deploy_packages_id' => $package_id] + 'WHERE' => ['plugin_deploy_packages_id' => $package_id], ])->current(); $new_rank = $result['maxi']; } else { @@ -148,14 +147,14 @@ public static function moveSubitem( 'WHERE' => [ 'plugin_deploy_packages_id' => $package_id, ['order' => ['>', $old_rank]], - ['order' => ['<=', $new_rank]] - ] + ['order' => ['<=', $new_rank]], + ], ]); foreach ($iterator as $data) { $data['order']--; $result = $subitem->update($data); } - } else if ($old_rank > $new_rank) { + } elseif ($old_rank > $new_rank) { if ($type == self::MOVE_AFTER) { $new_rank++; } @@ -167,8 +166,8 @@ public static function moveSubitem( 'WHERE' => [ 'plugin_deploy_packages_id' => $package_id, ['order' => ['>=', $new_rank]], - ['order' => ['<', $old_rank]] - ] + ['order' => ['<', $old_rank]], + ], ]); foreach ($iterator as $data) { $data['order']++; @@ -182,7 +181,7 @@ public static function moveSubitem( if ($result && ($old_rank != $new_rank)) { $result = $subitem->update([ 'id' => $ID, - 'order' => $new_rank + 'order' => $new_rank, ]); } return ($result ? true : false); @@ -200,7 +199,7 @@ public function rawSearchOptions() 'field' => 'id', 'name' => __('ID'), 'massiveaction' => false, // implicit field is id - 'datatype' => 'number' + 'datatype' => 'number', ]; $tab[] = [ @@ -208,7 +207,7 @@ public function rawSearchOptions() 'table' => $this->getTable(), 'field' => 'comment', 'name' => __('Comments'), - 'datatype' => 'text' + 'datatype' => 'text', ]; $tab[] = [ @@ -217,7 +216,7 @@ public function rawSearchOptions() 'field' => 'date_mod', 'name' => __('Last update'), 'datatype' => 'datetime', - 'massiveaction' => false + 'massiveaction' => false, ]; $tab[] = [ @@ -226,7 +225,7 @@ public function rawSearchOptions() 'field' => 'date_creation', 'name' => __('Creation date'), 'datatype' => 'datetime', - 'massiveaction' => false + 'massiveaction' => false, ]; $tab[] = [ @@ -234,7 +233,7 @@ public function rawSearchOptions() 'table' => 'glpi_entities', 'field' => 'completename', 'name' => Entity::getTypeName(1), - 'datatype' => 'dropdown' + 'datatype' => 'dropdown', ]; return $tab; @@ -288,7 +287,7 @@ public static function install(Migration $migration) // add display preferences $nb_display_pref = countElementsInTable(DisplayPreference::getTable(), [ - 'itemtype' => self::getType() + 'itemtype' => self::getType(), ]); if ($nb_display_pref == 0) { $dp = new DisplayPreference(); @@ -314,6 +313,6 @@ public static function uninstall(Migration $migration) $migration->displayMessage("Uninstalling $table"); $migration->dropTable($table); - $DB->doQuery("DELETE FROM `glpi_displaypreferences` WHERE `itemtype` = '" . self::getType() . "'"); + $DB->delete(DisplayPreference::getTable(), ['itemtype' => self::class]); } } diff --git a/src/PackageAction.php b/src/PackageAction.php index 70c5524..d437942 100644 --- a/src/PackageAction.php +++ b/src/PackageAction.php @@ -107,7 +107,7 @@ public static function getTypeIconClass($type = ""): string } - public static function getLabelForType(string $type = null, bool $with_icon = false): string + public static function getLabelForType(?string $type = null, bool $with_icon = false): string { $types = self::getTypes($with_icon); return $types[$type] ?? ""; @@ -183,7 +183,7 @@ private function prepareJsonInput(array $input = []): array $json_array = [ $input['type'] => [ 'name' => $input['name'] ?? "", - ] + ], ]; switch ($input['type']) { case self::ACTION_CMD: diff --git a/src/PackageCheck.php b/src/PackageCheck.php index a1f2066..60f7e0e 100644 --- a/src/PackageCheck.php +++ b/src/PackageCheck.php @@ -112,8 +112,8 @@ public static function getTypes(bool $flat = false): array self::WINVALUEMISSING => __("Registry value missing", 'deploy'), self::WINKEYEQUALS => __("Registry value equals to", 'deploy'), self::WINKEYNOTEQUALS => __("Registry value not equals to", 'deploy'), - self::WINVALUETYPE => __("Type of registry value equals to", 'deploy') - ] + self::WINVALUETYPE => __("Type of registry value equals to", 'deploy'), + ], ], 'file' => [ 'icon' => 'ti ti-file', @@ -126,7 +126,7 @@ public static function getTypes(bool $flat = false): array self::FILESIZELOWER => __("File size is lower than", 'deploy'), self::FILESHA512 => __("SHA-512 hash value matches", 'deploy'), self::FILESHA512MISMATCH => __("SHA-512 hash value mismatch", 'deploy'), - ] + ], ], 'directory' => [ 'icon' => 'ti ti-subtask', @@ -134,15 +134,15 @@ public static function getTypes(bool $flat = false): array 'subtypes' => [ self::DIRECTORYEXISTS => __("Directory exists", 'deploy'), self::DIRECTORYMISSING => __("Directory is missing", 'deploy'), - ] + ], ], 'other' => [ 'icon' => 'ti ti-dots', 'label' => __('Other'), 'subtypes' => [ - self::FREESPACEGREATER => __("Free space is greater than", 'deploy') - ] - ] + self::FREESPACEGREATER => __("Free space is greater than", 'deploy'), + ], + ], ]; if ($flat) { @@ -175,7 +175,7 @@ public static function getTypesWithValueField(): array } - public static function getIconForParentType(string $parent_type = null): string + public static function getIconForParentType(?string $parent_type = null): string { $types = self::getTypes(false); return $types[$parent_type]['icon'] ?? ""; @@ -183,7 +183,7 @@ public static function getIconForParentType(string $parent_type = null): string - public static function getLabelForType(string $type = null): string + public static function getLabelForType(?string $type = null): string { $types = self::getTypes(true); return $types[$type] ?? ""; @@ -216,12 +216,12 @@ public static function getReturnValues(bool $with_icon = false): array self::RET_INFO => ($with_icon ? '' : "") . __("Report info", 'deploy'), self::RET_WARNING => ($with_icon ? '' : "") - . __("Report warning", 'deploy') + . __("Report warning", 'deploy'), ]; } - public static function getLabelForReturnValue(string $value = null, bool $with_icon = false): string + public static function getLabelForReturnValue(?string $value = null, bool $with_icon = false): string { $values = self::getReturnValues($with_icon); $string = $values[$value] ?? ""; diff --git a/src/PackageFile.php b/src/PackageFile.php index 74abe39..e4902f7 100644 --- a/src/PackageFile.php +++ b/src/PackageFile.php @@ -34,7 +34,8 @@ use DBConnection; use DOMDocument; use FilesystemIterator; -use Html; +use Glpi\Exception\Http\BadRequestHttpException; +use Glpi\Exception\Http\NotFoundHttpException; use Migration; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; @@ -101,7 +102,7 @@ public function prepareInputForAdd($input) public function pre_deleteItem() { $found_files = $this->find([ - 'sha512' => $this->fields['sha512'] + 'sha512' => $this->fields['sha512'], ]); // do not delete file in repository if it's also used in other packages @@ -119,7 +120,7 @@ public static function getFilesTreeFromServer(): string $path = GLPI_UPLOAD_DIR; $dir_iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST); - $dom = new DomDocument("1.0"); + $dom = new DOMDocument("1.0"); $list = $dom->createElement("ul"); $list->setAttribute('id', "treeData"); $dom->appendChild($list); @@ -257,7 +258,7 @@ public function downloadFile($file_id) // If there is any extra data, the sent file will be corrupted. // 1. Turn off any extra buffering level. Keep one buffering level if PHP output_buffering directive is not "off". $ob_config = ini_get('output_buffering'); - $max_buffering_level = $ob_config !== false && (strtolower($ob_config) === 'on' || (is_numeric($ob_config) && (int)$ob_config > 0)) + $max_buffering_level = $ob_config !== false && (strtolower($ob_config) === 'on' || (is_numeric($ob_config) && (int) $ob_config > 0)) ? 1 : 0; while (ob_get_level() > $max_buffering_level) { @@ -280,13 +281,13 @@ public function downloadFile($file_id) readgzfile($path); } } else { - Html::displayErrorAndDie(__('An error occurs', 'deploy'), true); + throw new BadRequestHttpException(); } } else { - Html::displayErrorAndDie(__('File not found', 'deploy'), true); // Not found + throw new NotFoundHttpException(); } } else { - Html::displayErrorAndDie(__('File not found', 'deploy'), true); // Not found + throw new NotFoundHttpException(); } } diff --git a/src/PackageJob.php b/src/PackageJob.php index 82d83f9..dd4acc2 100644 --- a/src/PackageJob.php +++ b/src/PackageJob.php @@ -36,7 +36,6 @@ use DBmysqlIterator; use Glpi\Application\View\TemplateRenderer; use Migration; -use Toolbox; class PackageJob extends CommonDBTM { @@ -135,8 +134,8 @@ public static function getForPackage(Package $package): DBmysqlIterator $iterator = $DBread->request([ 'FROM' => self::getTable(), 'WHERE' => [ - 'plugin_deploy_packages_id' => $package->fields['id'] - ] + 'plugin_deploy_packages_id' => $package->fields['id'], + ], ]); return $iterator; @@ -150,12 +149,12 @@ public static function getPackageAgents(Package $package): array [ "plugin_deploy_packages_id" => $package->getID(), "NOT" => [ - "agents_id" => 0 - ] + "agents_id" => 0, + ], ] ); $agent_list = [ - 0 => __('No agent') + 0 => __('No agent'), ]; $agent = new Agent(); foreach ($agent_id_list as $agent_id) { @@ -278,7 +277,7 @@ public static function showForPackage(Package $package) 'order' => $order, 'href' => $package::getFormURLWithID($package->getID()), 'additional_params' => $is_filtered ? http_build_query([ - 'filters' => $filters + 'filters' => $filters, ]) : "", 'is_tab' => true, 'items_id' => $package->fields['id'], @@ -341,7 +340,7 @@ public static function install(Migration $migration) KEY `date_mod` (`date_mod`), KEY `date_done` (`date_done`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->request($query); + $DB->doQuery($query); } } @@ -353,7 +352,7 @@ public static function uninstall(Migration $migration) $table = self::getTable(); if ($DB->tableExists($table)) { $migration->displayMessage("Uninstalling $table"); - $DB->request("DROP TABLE {$table}"); + $DB->doQuery("DROP TABLE {$table}"); } } } diff --git a/src/Timeslot.php b/src/Timeslot.php index da98f76..f121a10 100644 --- a/src/Timeslot.php +++ b/src/Timeslot.php @@ -79,7 +79,7 @@ public static function install(Migration $migration) KEY `date_creation` (`date_creation`), KEY `date_mod` (`date_mod`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->request($query); + $DB->doQuery($query); } } diff --git a/src/TimeslotRange.php b/src/TimeslotRange.php index 3c5a39a..3d553f5 100644 --- a/src/TimeslotRange.php +++ b/src/TimeslotRange.php @@ -91,7 +91,7 @@ public static function getForTimeslot(Timeslot $timeslot) 'checked' => '', 'starttime' => 14, 'endtime' => 18, - ] + ], ]; } } @@ -105,7 +105,7 @@ public static function showForTimeslot(Timeslot $timeslot) 'rand' => mt_rand(), 'timeslot_id' => $timeslot->fields['id'], 'days_list' => self::getDayList(), - 'timeslots_data' => $timeslots_data + 'timeslots_data' => $timeslots_data, ]); } @@ -133,7 +133,7 @@ public static function cleanOldData(array $input) foreach ($olddata as $data) { $timeslot->delete( [ - 'id' => $data['id'] + 'id' => $data['id'], ] ); } @@ -154,7 +154,7 @@ public static function cleanInput(array $input) 'weekday' => $key, 'time_start' => $start_time, 'time_end' => $end_time, - 'is_enable' => (bool)$value['is_enable'], + 'is_enable' => (bool) $value['is_enable'], ]; } } @@ -190,7 +190,7 @@ public static function install(Migration $migration) KEY `is_recursive` (`is_recursive`), KEY `date_mod` (`date_mod`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->request($query); + $DB->doQuery($query); } }