Feature GLP11 (#88)

* Feature GLP11

* phpstan

* enable CI and fix phstanneon

* Update .github/workflows/continuous-integration.yml

Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com>

* Update phpstan.neon

Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com>

* Pass all paramters to parent call

* move query -> doQuery

* fix direct query

* release GLPI 11.0

* Clean composer.json

* psalm + rector

* fix

---------

Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com>
Co-authored-by: Johan Cwiklinski <johan@x-tnd.be>
Co-authored-by: Rom1-B <rom1.biot@gmail.com>
This commit is contained in:
Stanislas
2025-09-30 16:14:41 +02:00
committed by GitHub
parent a2af3e6568
commit 15748a7c3d
35 changed files with 554 additions and 2345 deletions

View File

@@ -0,0 +1,35 @@
name: "Continuous integration"
on:
push:
branches:
- "main"
tags:
- "*"
pull_request:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
generate-ci-matrix:
name: "Generate CI matrix"
uses: "glpi-project/plugin-ci-workflows/.github/workflows/generate-ci-matrix.yml@v1"
with:
glpi-version: "11.0.x"
ci:
name: "GLPI ${{ matrix.glpi-version }} - php:${{ matrix.php-version }} - ${{ matrix.db-image }}"
needs: "generate-ci-matrix"
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.generate-ci-matrix.outputs.matrix) }}
uses: "glpi-project/plugin-ci-workflows/.github/workflows/continuous-integration.yml@v1"
with:
plugin-key: "example"
glpi-version: "${{ matrix.glpi-version }}"
php-version: "${{ matrix.php-version }}"
db-image: "${{ matrix.db-image }}"

12
CHANGELOG.md Normal file
View File

@@ -0,0 +1,12 @@
# 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/).
## [0.1.0] - 2025-09-30
### Added
- GLPI 11 compatibility

View File

@@ -1,16 +1,20 @@
{ {
"require": { "require": {
"php": ">=7.4" "php": ">=8.2"
}, },
"require-dev": { "require-dev": {
"friendsofphp/php-cs-fixer": "^3.86", "glpi-project/tools": "^0.8"
"glpi-project/tools": "^0.8.0"
}, },
"config": { "config": {
"optimize-autoloader": true, "optimize-autoloader": true,
"platform": { "platform": {
"php": "7.4.0" "php": "8.2.99"
}, },
"sort-packages": true "sort-packages": true
},
"autoload-dev": {
"psr-4": {
"Glpi\\Tools\\": "../../tools/src/"
}
} }
} }

2113
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,10 @@
<author>Indepnet</author> <author>Indepnet</author>
</authors> </authors>
<versions> <versions>
<version>
<num>0.1.0</num>
<compatibility>~11.0.0</compatibility>
</version>
<version> <version>
<num>0.0.1</num> <num>0.0.1</num>
<compatibility>~10.0.0</compatibility> <compatibility>~10.0.0</compatibility>

View File

@@ -37,7 +37,7 @@
//header("Location:../../central.php"); //header("Location:../../central.php");
// Entry menu case // Entry menu case
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkRight('config', UPDATE); Session::checkRight('config', UPDATE);
@@ -45,5 +45,5 @@ Session::checkRight('config', UPDATE);
Plugin::load('example'); Plugin::load('example');
Html::header('TITRE', $_SERVER['PHP_SELF'], 'config', 'plugins'); Html::header('TITRE', $_SERVER['PHP_SELF'], 'config', 'plugins');
echo __('This is the plugin config page', 'example'); echo __s('This is the plugin config page', 'example');
Html::footer(); Html::footer();

View File

@@ -35,7 +35,7 @@
use GlpiPlugin\Example\DeviceCamera; use GlpiPlugin\Example\DeviceCamera;
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkLoginUser(); Session::checkLoginUser();
$dropdown = new DeviceCamera(); $dropdown = new DeviceCamera();

View File

@@ -33,7 +33,7 @@
// Purpose of file: // Purpose of file:
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkLoginUser(); Session::checkLoginUser();
$dropdown = new DeviceCamera(); $dropdown = new DeviceCamera();

View File

@@ -35,7 +35,7 @@
use GlpiPlugin\Example\Dropdown; use GlpiPlugin\Example\Dropdown;
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkLoginUser(); Session::checkLoginUser();
Plugin::load('example', true); Plugin::load('example', true);

View File

@@ -35,7 +35,7 @@
use GlpiPlugin\Example\Dropdown; use GlpiPlugin\Example\Dropdown;
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkLoginUser(); Session::checkLoginUser();
Plugin::load('example', true); Plugin::load('example', true);

View File

@@ -35,7 +35,7 @@
use GlpiPlugin\Example\Example; use GlpiPlugin\Example\Example;
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkLoginUser(); Session::checkLoginUser();
if ($_SESSION['glpiactiveprofile']['interface'] == 'central') { if ($_SESSION['glpiactiveprofile']['interface'] == 'central') {

View File

@@ -35,7 +35,7 @@
use GlpiPlugin\Example\Example; use GlpiPlugin\Example\Example;
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkRight(Example::$rightname, READ); Session::checkRight(Example::$rightname, READ);
if ($_SESSION['glpiactiveprofile']['interface'] == 'central') { if ($_SESSION['glpiactiveprofile']['interface'] == 'central') {

View File

@@ -28,7 +28,7 @@
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkLoginUser(); Session::checkLoginUser();
@@ -39,21 +39,16 @@ if (isset($_GET['popup'])) {
if (isset($_SESSION['glpipopup']['name'])) { if (isset($_SESSION['glpipopup']['name'])) {
switch ($_SESSION['glpipopup']['name']) { switch ($_SESSION['glpipopup']['name']) {
case 'test_rule': case 'test_rule':
Html::popHeader(__('Test'), $_SERVER['PHP_SELF']); Html::popHeader(__s('Test'), $_SERVER['PHP_SELF']);
include '../../../front/rule.test.php'; include __DIR__ . '/../../../front/rule.test.php';
break; break;
case 'test_all_rules': case 'test_all_rules':
Html::popHeader(__('Test rules engine'), $_SERVER['PHP_SELF']); Html::popHeader(__s('Test rules engine'), $_SERVER['PHP_SELF']);
include '../../../front/rulesengine.test.php'; include __DIR__ . '/../../../front/rulesengine.test.php';
break;
case 'show_cache':
Html::popHeader(__('Cache information'), $_SERVER['PHP_SELF']);
include '../../../front/rule.cache.php';
break; break;
} }
echo "<div class='center'><br><a href='javascript:window.close()'>" . __('Back') . '</a>'; echo "<div class='center'><br><a href='javascript:window.close()'>" . __s('Back') . '</a>';
echo '</div>'; echo '</div>';
Html::popFooter(); Html::popFooter();
} }

View File

@@ -35,7 +35,7 @@
use GlpiPlugin\Example\RuleTestCollection; use GlpiPlugin\Example\RuleTestCollection;
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkLoginUser(); Session::checkLoginUser();
$rulecollection = new RuleTestCollection(); $rulecollection = new RuleTestCollection();

View File

@@ -35,7 +35,7 @@
use GlpiPlugin\Example\RuleTestCollection; use GlpiPlugin\Example\RuleTestCollection;
include('../../../inc/includes.php'); include(__DIR__ . '/../../../inc/includes.php');
Session::checkLoginUser(); Session::checkLoginUser();
$rulecollection = new RuleTestCollection(); $rulecollection = new RuleTestCollection();

100
hook.php
View File

@@ -33,9 +33,7 @@
// Purpose of file: // Purpose of file:
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
use GlpiPlugin\Example\Dropdown;
use GlpiPlugin\Example\Example; use GlpiPlugin\Example\Example;
use Dropdown as GlpiDropdown;
function plugin_change_profile_example() function plugin_change_profile_example()
{ {
@@ -54,7 +52,7 @@ function plugin_example_getDatabaseRelations()
function plugin_example_getDropdown() function plugin_example_getDropdown()
{ {
// Table => Name // Table => Name
return [Dropdown::class => __('Plugin Example Dropdown', 'example')]; return [Dropdown::class => __s('Plugin Example Dropdown', 'example')];
} }
@@ -70,9 +68,8 @@ function plugin_example_getAddSearchOptions($itemtype)
$sopt[1001]['table'] = 'glpi_plugin_example_dropdowns'; $sopt[1001]['table'] = 'glpi_plugin_example_dropdowns';
$sopt[1001]['field'] = 'name'; $sopt[1001]['field'] = 'name';
$sopt[1001]['linkfield'] = 'plugin_example_dropdowns_id'; $sopt[1001]['linkfield'] = 'plugin_example_dropdowns_id';
$sopt[1001]['name'] = __('Example plugin', 'example'); $sopt[1001]['name'] = __s('Example plugin', 'example');
} }
return $sopt; return $sopt;
} }
@@ -86,10 +83,9 @@ function plugin_example_getAddSearchOptionsNew($itemtype)
'table' => 'glpi_plugin_example_dropdowns', 'table' => 'glpi_plugin_example_dropdowns',
'field' => 'name', 'field' => 'name',
'linkfield' => 'plugin_example_dropdowns_id', 'linkfield' => 'plugin_example_dropdowns_id',
'name' => __('Example plugin new', 'example'), 'name' => __s('Example plugin new', 'example'),
]; ];
} }
return $options; return $options;
} }
@@ -201,7 +197,6 @@ function plugin_example_forceGroupBy($type)
// Force add GROUP BY IN REQUEST // Force add GROUP BY IN REQUEST
return true; return true;
} }
return false; return false;
} }
@@ -212,7 +207,7 @@ function plugin_example_addWhere($link, $nott, $type, $ID, $val, $searchtype)
$table = $searchopt[$ID]['table']; $table = $searchopt[$ID]['table'];
$field = $searchopt[$ID]['field']; $field = $searchopt[$ID]['field'];
$SEARCH = Search::makeTextSearch($val, $nott); Search::makeTextSearch($val, $nott);
// Example of standard Where clause but use it ONLY for specific Where // Example of standard Where clause but use it ONLY for specific Where
// No need of the function if you do not have specific cases // No need of the function if you do not have specific cases
@@ -250,7 +245,7 @@ function plugin_example_addHaving($link, $nott, $type, $ID, $val, $num)
$ADD = " OR ITEM_$num IS NULL"; $ADD = " OR ITEM_$num IS NULL";
} }
return " $LINK ( ITEM_" . $num . $SEARCH . " $ADD ) "; return " $link ( ITEM_" . $num . $SEARCH . " $ADD ) ";
} }
return ''; return '';
@@ -260,8 +255,6 @@ function plugin_example_addHaving($link, $nott, $type, $ID, $val, $num)
function plugin_example_addSelect($type, $ID, $num) function plugin_example_addSelect($type, $ID, $num)
{ {
$searchopt = &Search::getOptions($type); $searchopt = &Search::getOptions($type);
$table = $searchopt[$ID]['table'];
$field = $searchopt[$ID]['field'];
// Example of standard Select clause but use it ONLY for specific Select // Example of standard Select clause but use it ONLY for specific Select
// No need of the function if you do not have specific cases // No need of the function if you do not have specific cases
@@ -276,8 +269,6 @@ function plugin_example_addSelect($type, $ID, $num)
function plugin_example_addOrderBy($type, $ID, $order, $key = 0) function plugin_example_addOrderBy($type, $ID, $order, $key = 0)
{ {
$searchopt = &Search::getOptions($type); $searchopt = &Search::getOptions($type);
$table = $searchopt[$ID]['table'];
$field = $searchopt[$ID]['field'];
// Example of standard OrderBy clause but use it ONLY for specific order by // Example of standard OrderBy clause but use it ONLY for specific order by
// No need of the function if you do not have specific cases // No need of the function if you do not have specific cases
@@ -299,7 +290,7 @@ function plugin_example_MassiveActions($type)
switch ($type) { switch ($type) {
// New action for core and other plugin types : name = plugin_PLUGINNAME_actionname // New action for core and other plugin types : name = plugin_PLUGINNAME_actionname
case 'Computer': case 'Computer':
return [Example::class . MassiveAction::CLASS_ACTION_SEPARATOR . 'DoIt' => __('plugin_example_DoIt', 'example')]; return [Example::class . MassiveAction::CLASS_ACTION_SEPARATOR . 'DoIt' => __s('plugin_example_DoIt', 'example')];
// Actions for types provided by the plugin are included inside the classes // Actions for types provided by the plugin are included inside the classes
} }
@@ -316,13 +307,12 @@ function plugin_example_MassiveActionsFieldsDisplay($options = [])
$table = $options['options']['table']; $table = $options['options']['table'];
$field = $options['options']['field']; $field = $options['options']['field'];
$linkfield = $options['options']['linkfield'];
if ($table == getTableForItemType($options['itemtype'])) { if ($table == getTableForItemType($options['itemtype'])) {
// Table fields // Table fields
switch ($table . '.' . $field) { switch ($table . '.' . $field) {
case 'glpi_plugin_example_examples.serial': case 'glpi_plugin_example_examples.serial':
echo __('Not really specific - Just for example', 'example'); echo __s('Not really specific - Just for example', 'example');
// Dropdown::showYesNo($linkfield); // Dropdown::showYesNo($linkfield);
// Need to return true if specific display // Need to return true if specific display
@@ -332,13 +322,12 @@ function plugin_example_MassiveActionsFieldsDisplay($options = [])
// Linked Fields // Linked Fields
switch ($table . '.' . $field) { switch ($table . '.' . $field) {
case 'glpi_plugin_example_dropdowns.name': case 'glpi_plugin_example_dropdowns.name':
echo __('Not really specific - Just for example', 'example'); echo __s('Not really specific - Just for example', 'example');
// Need to return true if specific display // Need to return true if specific display
return true; return true;
} }
} }
// Need to return false on non display item // Need to return false on non display item
return false; return false;
} }
@@ -355,8 +344,8 @@ function plugin_example_searchOptionsValues($options = [])
// Table fields // Table fields
switch ($table . '.' . $field) { switch ($table . '.' . $field) {
case 'glpi_plugin_example_examples.serial': case 'glpi_plugin_example_examples.serial':
echo __('Not really specific - Use your own dropdown - Just for example', 'example'); echo __s('Not really specific - Use your own dropdown - Just for example', 'example');
GlpiDropdown::show( Dropdown::show(
getItemTypeForTable($options['searchoption']['table']), getItemTypeForTable($options['searchoption']['table']),
['value' => $options['value'], ['value' => $options['value'],
'name' => $options['name'], 'name' => $options['name'],
@@ -382,14 +371,14 @@ function plugin_pre_item_update_example($item)
} }
$item->input['comment'] .= addslashes("\nUpdate: ".date('r')); $item->input['comment'] .= addslashes("\nUpdate: ".date('r'));
*/ */
Session::addMessageAfterRedirect(__('Pre Update Computer Hook', 'example'), true); Session::addMessageAfterRedirect(__s('Pre Update Computer Hook', 'example'), true);
} }
// Hook done on update item case // Hook done on update item case
function plugin_item_update_example($item) function plugin_item_update_example($item)
{ {
Session::addMessageAfterRedirect(sprintf(__('Update Computer Hook (%s)', 'example'), implode(',', $item->updates)), true); Session::addMessageAfterRedirect(sprintf(__s('Update Computer Hook (%s)', 'example'), implode(',', $item->updates)), true);
return true; return true;
} }
@@ -399,7 +388,7 @@ function plugin_item_update_example($item)
function plugin_item_empty_example($item) function plugin_item_empty_example($item)
{ {
if (empty($_SESSION['Already displayed "Empty Computer Hook"'])) { if (empty($_SESSION['Already displayed "Empty Computer Hook"'])) {
Session::addMessageAfterRedirect(__('Empty Computer Hook', 'example'), true); Session::addMessageAfterRedirect(__s('Empty Computer Hook', 'example'), true);
$_SESSION['Already displayed "Empty Computer Hook"'] = true; $_SESSION['Already displayed "Empty Computer Hook"'] = true;
} }
@@ -411,14 +400,14 @@ function plugin_item_empty_example($item)
function plugin_pre_item_delete_example($object) function plugin_pre_item_delete_example($object)
{ {
// Manipulate data if needed // Manipulate data if needed
Session::addMessageAfterRedirect(__('Pre Delete Computer Hook', 'example'), true); Session::addMessageAfterRedirect(__s('Pre Delete Computer Hook', 'example'), true);
} }
// Hook done on delete item case // Hook done on delete item case
function plugin_item_delete_example($object) function plugin_item_delete_example($object)
{ {
Session::addMessageAfterRedirect(__('Delete Computer Hook', 'example'), true); Session::addMessageAfterRedirect(__s('Delete Computer Hook', 'example'), true);
return true; return true;
} }
@@ -428,14 +417,14 @@ function plugin_item_delete_example($object)
function plugin_pre_item_purge_example($object) function plugin_pre_item_purge_example($object)
{ {
// Manipulate data if needed // Manipulate data if needed
Session::addMessageAfterRedirect(__('Pre Purge Computer Hook', 'example'), true); Session::addMessageAfterRedirect(__s('Pre Purge Computer Hook', 'example'), true);
} }
// Hook done on purge item case // Hook done on purge item case
function plugin_item_purge_example($object) function plugin_item_purge_example($object)
{ {
Session::addMessageAfterRedirect(__('Purge Computer Hook', 'example'), true); Session::addMessageAfterRedirect(__s('Purge Computer Hook', 'example'), true);
return true; return true;
} }
@@ -445,7 +434,7 @@ function plugin_item_purge_example($object)
function plugin_pre_item_restore_example($item) function plugin_pre_item_restore_example($item)
{ {
// Manipulate data if needed // Manipulate data if needed
Session::addMessageAfterRedirect(__('Pre Restore Computer Hook', 'example')); Session::addMessageAfterRedirect(__s('Pre Restore Computer Hook', 'example'));
} }
@@ -453,14 +442,14 @@ function plugin_pre_item_restore_example($item)
function plugin_pre_item_restore_example2($item) function plugin_pre_item_restore_example2($item)
{ {
// Manipulate data if needed // Manipulate data if needed
Session::addMessageAfterRedirect(__('Pre Restore Phone Hook', 'example')); Session::addMessageAfterRedirect(__s('Pre Restore Phone Hook', 'example'));
} }
// Hook done on restore item case // Hook done on restore item case
function plugin_item_restore_example($item) function plugin_item_restore_example($item)
{ {
Session::addMessageAfterRedirect(__('Restore Computer Hook', 'example')); Session::addMessageAfterRedirect(__s('Restore Computer Hook', 'example'));
return true; return true;
} }
@@ -471,7 +460,7 @@ function plugin_item_transfer_example($parm)
{ {
//TRANS: %1$s is the source type, %2$d is the source ID, %3$d is the destination ID //TRANS: %1$s is the source type, %2$d is the source ID, %3$d is the destination ID
Session::addMessageAfterRedirect(sprintf( Session::addMessageAfterRedirect(sprintf(
__('Transfer Computer Hook %1$s %2$d -> %3$d', 'example'), __s('Transfer Computer Hook %1$s %2$d -> %3$d', 'example'),
$parm['type'], $parm['type'],
$parm['id'], $parm['id'],
$parm['newID'], $parm['newID'],
@@ -551,7 +540,7 @@ function plugin_example_install()
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;";
$DB->query($query) or die('error creating glpi_plugin_example_examples ' . $DB->error()); $DB->doQuery($query);
$query = "INSERT INTO `glpi_plugin_example_examples` $query = "INSERT INTO `glpi_plugin_example_examples`
(`id`, `name`, `serial`, `plugin_example_dropdowns_id`, `is_deleted`, (`id`, `name`, `serial`, `plugin_example_dropdowns_id`, `is_deleted`,
@@ -559,7 +548,7 @@ function plugin_example_install()
VALUES (1, 'example 1', 'serial 1', 1, 0, 0, NULL), VALUES (1, 'example 1', 'serial 1', 1, 0, 0, NULL),
(2, 'example 2', 'serial 2', 2, 0, 0, NULL), (2, 'example 2', 'serial 2', 2, 0, 0, NULL),
(3, 'example 3', 'serial 3', 1, 0, 0, NULL)"; (3, 'example 3', 'serial 3', 1, 0, 0, NULL)";
$DB->query($query) or die('error populate glpi_plugin_example ' . $DB->error()); $DB->doQuery($query);
} }
if (!$DB->tableExists('glpi_plugin_example_dropdowns')) { if (!$DB->tableExists('glpi_plugin_example_dropdowns')) {
@@ -571,14 +560,14 @@ function plugin_example_install()
KEY `name` (`name`) KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;";
$DB->query($query) or die('error creating glpi_plugin_example_dropdowns' . $DB->error()); $DB->doQuery($query);
$query = "INSERT INTO `glpi_plugin_example_dropdowns` $query = "INSERT INTO `glpi_plugin_example_dropdowns`
(`id`, `name`, `comment`) (`id`, `name`, `comment`)
VALUES (1, 'dp 1', 'comment 1'), VALUES (1, 'dp 1', 'comment 1'),
(2, 'dp2', 'comment 2')"; (2, 'dp2', 'comment 2')";
$DB->query($query) or die('error populate glpi_plugin_example_dropdowns' . $DB->error()); $DB->doQuery($query);
} }
if (!$DB->tableExists('glpi_plugin_example_devicecameras')) { if (!$DB->tableExists('glpi_plugin_example_devicecameras')) {
@@ -592,7 +581,7 @@ function plugin_example_install()
KEY `manufacturers_id` (`manufacturers_id`) KEY `manufacturers_id` (`manufacturers_id`)
) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;";
$DB->query($query) or die('error creating glpi_plugin_example_examples ' . $DB->error()); $DB->doQuery($query);
} }
if (!$DB->tableExists('glpi_plugin_example_items_devicecameras')) { if (!$DB->tableExists('glpi_plugin_example_items_devicecameras')) {
@@ -610,13 +599,12 @@ function plugin_example_install()
KEY `is_dynamic` (`is_dynamic`) KEY `is_dynamic` (`is_dynamic`)
) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;";
$DB->query($query) or die('error creating glpi_plugin_example_examples ' . $DB->error()); $DB->doQuery($query);
} }
// To be called for each task the plugin manage // To be called for each task the plugin manage
// task in class // task in class
CronTask::Register(Example::class, 'Sample', DAY_TIMESTAMP, ['param' => 50]); CronTask::Register(Example::class, 'Sample', DAY_TIMESTAMP, ['param' => 50]);
return true; return true;
} }
@@ -645,28 +633,28 @@ function plugin_example_uninstall()
// Old version tables // Old version tables
if ($DB->tableExists('glpi_dropdown_plugin_example')) { if ($DB->tableExists('glpi_dropdown_plugin_example')) {
$query = 'DROP TABLE `glpi_dropdown_plugin_example`'; $query = 'DROP TABLE `glpi_dropdown_plugin_example`';
$DB->query($query) or die('error deleting glpi_dropdown_plugin_example'); $DB->doQuery($query);
} }
if ($DB->tableExists('glpi_plugin_example')) { if ($DB->tableExists('glpi_plugin_example')) {
$query = 'DROP TABLE `glpi_plugin_example`'; $query = 'DROP TABLE `glpi_plugin_example`';
$DB->query($query) or die('error deleting glpi_plugin_example'); $DB->doQuery($query);
} }
// Current version tables // Current version tables
if ($DB->tableExists('glpi_plugin_example_example')) { if ($DB->tableExists('glpi_plugin_example_example')) {
$query = 'DROP TABLE `glpi_plugin_example_example`'; $query = 'DROP TABLE `glpi_plugin_example_example`';
$DB->query($query) or die('error deleting glpi_plugin_example_example'); $DB->doQuery($query);
} }
if ($DB->tableExists('glpi_plugin_example_dropdowns')) { if ($DB->tableExists('glpi_plugin_example_dropdowns')) {
$query = 'DROP TABLE `glpi_plugin_example_dropdowns`;'; $query = 'DROP TABLE `glpi_plugin_example_dropdowns`;';
$DB->query($query) or die('error deleting glpi_plugin_example_dropdowns'); $DB->doQuery($query);
} }
if ($DB->tableExists('glpi_plugin_example_devicecameras')) { if ($DB->tableExists('glpi_plugin_example_devicecameras')) {
$query = 'DROP TABLE `glpi_plugin_example_devicecameras`;'; $query = 'DROP TABLE `glpi_plugin_example_devicecameras`;';
$DB->query($query) or die('error deleting glpi_plugin_example_devicecameras'); $DB->doQuery($query);
} }
if ($DB->tableExists('glpi_plugin_example_items_devicecameras')) { if ($DB->tableExists('glpi_plugin_example_items_devicecameras')) {
$query = 'DROP TABLE `glpi_plugin_example_items_devicecameras`;'; $query = 'DROP TABLE `glpi_plugin_example_items_devicecameras`;';
$DB->query($query) or die('error deleting glpi_plugin_example_items_devicecameras'); $DB->doQuery($query);
} }
return true; return true;
@@ -683,13 +671,13 @@ function plugin_example_AssignToTicket($types)
function plugin_example_get_events(NotificationTargetTicket $target) function plugin_example_get_events(NotificationTargetTicket $target)
{ {
$target->events['plugin_example'] = __('Example event', 'example'); $target->events['plugin_example'] = __s('Example event', 'example');
} }
function plugin_example_get_datas(NotificationTargetTicket $target) function plugin_example_get_datas(NotificationTargetTicket $target)
{ {
$target->data['##ticket.example##'] = __('Example datas', 'example'); $target->data['##ticket.example##'] = __s('Example datas', 'example');
} }
@@ -710,7 +698,7 @@ function plugin_example_postinit()
* *
* @param $datas array * @param $datas array
* *
* @return un tableau * @return array
**/ **/
function plugin_retrieve_more_data_from_ldap_example(array $datas) function plugin_retrieve_more_data_from_ldap_example(array $datas)
{ {
@@ -723,7 +711,7 @@ function plugin_retrieve_more_data_from_ldap_example(array $datas)
* *
* @param $fields array * @param $fields array
* *
* @return un tableau * @return array
**/ **/
function plugin_retrieve_more_field_from_ldap_example($fields) function plugin_retrieve_more_field_from_ldap_example($fields)
{ {
@@ -736,6 +724,7 @@ function plugin_example_Status($param)
// Do checks (no check for example) // Do checks (no check for example)
$ok = true; $ok = true;
echo 'example plugin: example'; echo 'example plugin: example';
if ($ok) { if ($ok) {
echo '_OK'; echo '_OK';
} else { } else {
@@ -744,7 +733,6 @@ function plugin_example_Status($param)
$param['ok'] = false; $param['ok'] = false;
} }
echo "\n"; echo "\n";
return $param; return $param;
} }
@@ -752,7 +740,7 @@ function plugin_example_display_central()
{ {
echo "<tr><th colspan='2'>"; echo "<tr><th colspan='2'>";
echo "<div style='text-align:center; font-size:2em'>"; echo "<div style='text-align:center; font-size:2em'>";
echo __('Plugin example displays on central page', 'example'); echo __s('Plugin example displays on central page', 'example');
echo '</div>'; echo '</div>';
echo '</th></tr>'; echo '</th></tr>';
} }
@@ -760,21 +748,20 @@ function plugin_example_display_central()
function plugin_example_display_login() function plugin_example_display_login()
{ {
echo "<div style='text-align:center; font-size:2em'>"; echo "<div style='text-align:center; font-size:2em'>";
echo __('Plugin example displays on login page', 'example'); echo __s('Plugin example displays on login page', 'example');
echo '</div>'; echo '</div>';
} }
function plugin_example_infocom_hook($params) function plugin_example_infocom_hook($params)
{ {
echo "<tr><th colspan='4'>"; echo "<tr><th colspan='4'>";
echo __('Plugin example displays on central page', 'example'); echo __s('Plugin example displays on central page', 'example');
echo '</th></tr>'; echo '</th></tr>';
} }
function plugin_example_filter_actors(array $params = []): array function plugin_example_filter_actors(array $params = []): array
{ {
$itemtype = $params['params']['itemtype']; $itemtype = $params['params']['itemtype'];
$items_id = $params['params']['items_id'];
// remove users_id = 1 for assignee list // remove users_id = 1 for assignee list
if ($itemtype == 'Ticket' && $params['params']['actortype'] == 'assign') { if ($itemtype == 'Ticket' && $params['params']['actortype'] == 'assign') {
@@ -790,12 +777,15 @@ function plugin_example_filter_actors(array $params = []): array
function plugin_example_set_impact_icon(array $params) function plugin_example_set_impact_icon(array $params)
{ {
/** @var array $CFG_GLPI */
global $CFG_GLPI;
$itemtype = $params['itemtype']; $itemtype = $params['itemtype'];
$items_id = $params['items_id']; $items_id = $params['items_id'];
$item = getItemForItemtype($itemtype); $item = getItemForItemtype($itemtype);
if ($item instanceof Computer && $item->getFromDB($items_id)) { if ($item instanceof Computer && $item->getFromDB($items_id)) {
return Plugin::getWebDir('example', true, false) . '/public/computer_icon.svg'; return $CFG_GLPI['root_doc'] . '/plugins/example/public/computer_icon.svg';
} }
return null; return null;

19
phpstan.neon Normal file
View File

@@ -0,0 +1,19 @@
parameters:
parallel:
maximumNumberOfProcesses: 2
level: 5
paths:
- front
- src
- hook.php
- report.php
- setup.php
- stat.php
scanDirectories:
- ../../inc
- ../../src
- ../../front
bootstrapFiles:
- ../../stubs/glpi_constants.php
- ../../vendor/autoload.php

24
psalm.xml Normal file
View File

@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<psalm
runTaintAnalysis="true"
>
<projectFiles>
<directory name="front" />
<directory name="src" />
<file name="hook.php" />
<file name="report.php" />
<file name="setup.php" />
<file name="stat.php" />
</projectFiles>
<issueHandlers>
<!--
Too many false positives.
- many are already secured by ForbidDynamicInstantiationRule, but Psalm does not seems to consider `is_a()` checks safe enough;
- many are related dynamic call to plugin functions/classes, we need a lot of refactor to indicate to Psalm these can be ignored;
- the rest is likely to not be exploitable, due to the really low probability to have a classname
that can be abused and that implements the specific static method called on a dynamic classname.
-->
<TaintedCallable errorLevel="suppress" />
</issueHandlers>
</psalm>

97
rector.php Normal file
View File

@@ -0,0 +1,97 @@
<?php
/**
* -------------------------------------------------------------------------
* Example plugin for GLPI
* -------------------------------------------------------------------------
*
* LICENSE
*
* This file is part of Example.
*
* Example 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 2 of the License, or
* (at your option) any later version.
*
* Example 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 Example. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2006-2022 by Example plugin team.
* @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
* @link https://github.com/pluginsGLPI/example
* -------------------------------------------------------------------------
*/
require_once __DIR__ . '/../../src/Plugin.php';
use Rector\Caching\ValueObject\Storage\FileCacheStorage;
use Rector\CodeQuality\Rector as CodeQuality;
use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector as DeadCode;
use Rector\ValueObject\PhpVersion;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/front',
__DIR__ . '/src',
])
->withPhpVersion(PhpVersion::PHP_82)
->withCache(
cacheClass: FileCacheStorage::class,
cacheDirectory: sys_get_temp_dir() . '/example-rector',
)
->withRootFiles()
->withParallel(timeoutSeconds: 300)
->withImportNames(removeUnusedImports: true)
->withRules([
CodeQuality\Assign\CombinedAssignRector::class,
CodeQuality\BooleanAnd\RemoveUselessIsObjectCheckRector::class,
CodeQuality\BooleanAnd\SimplifyEmptyArrayCheckRector::class,
CodeQuality\BooleanNot\ReplaceMultipleBooleanNotRector::class,
CodeQuality\Catch_\ThrowWithPreviousExceptionRector::class,
CodeQuality\Empty_\SimplifyEmptyCheckOnEmptyArrayRector::class,
CodeQuality\Expression\InlineIfToExplicitIfRector::class,
CodeQuality\Expression\TernaryFalseExpressionToIfRector::class,
CodeQuality\For_\ForRepeatedCountToOwnVariableRector::class,
CodeQuality\Foreach_\ForeachItemsAssignToEmptyArrayToAssignRector::class,
CodeQuality\Foreach_\ForeachToInArrayRector::class,
CodeQuality\Foreach_\SimplifyForeachToCoalescingRector::class,
CodeQuality\Foreach_\UnusedForeachValueToArrayKeysRector::class,
CodeQuality\FuncCall\ChangeArrayPushToArrayAssignRector::class,
CodeQuality\FuncCall\CompactToVariablesRector::class,
CodeQuality\FuncCall\InlineIsAInstanceOfRector::class,
CodeQuality\FuncCall\IsAWithStringWithThirdArgumentRector::class,
CodeQuality\FuncCall\RemoveSoleValueSprintfRector::class,
CodeQuality\FuncCall\SetTypeToCastRector::class,
CodeQuality\FuncCall\SimplifyFuncGetArgsCountRector::class,
CodeQuality\FuncCall\SimplifyInArrayValuesRector::class,
CodeQuality\FuncCall\SimplifyStrposLowerRector::class,
CodeQuality\FuncCall\UnwrapSprintfOneArgumentRector::class,
CodeQuality\Identical\BooleanNotIdenticalToNotIdenticalRector::class,
CodeQuality\Identical\SimplifyArraySearchRector::class,
CodeQuality\Identical\SimplifyConditionsRector::class,
CodeQuality\Identical\StrlenZeroToIdenticalEmptyStringRector::class,
CodeQuality\If_\CombineIfRector::class,
CodeQuality\If_\CompleteMissingIfElseBracketRector::class,
CodeQuality\If_\ConsecutiveNullCompareReturnsToNullCoalesceQueueRector::class,
CodeQuality\If_\ExplicitBoolCompareRector::class,
CodeQuality\If_\ShortenElseIfRector::class,
CodeQuality\If_\SimplifyIfElseToTernaryRector::class,
CodeQuality\If_\SimplifyIfNotNullReturnRector::class,
CodeQuality\If_\SimplifyIfNullableReturnRector::class,
CodeQuality\If_\SimplifyIfReturnBoolRector::class,
CodeQuality\Include_\AbsolutizeRequireAndIncludePathRector::class,
CodeQuality\LogicalAnd\AndAssignsToSeparateLinesRector::class,
CodeQuality\LogicalAnd\LogicalToBooleanRector::class,
CodeQuality\NotEqual\CommonNotEqualRector::class,
CodeQuality\Ternary\UnnecessaryTernaryExpressionRector::class,
DeadCode\Assign\RemoveUnusedVariableAssignRector::class,
])
->withPhpSets(php74: true) // apply PHP sets up to PHP 7.4
;

View File

@@ -27,24 +27,24 @@
* @link https://github.com/pluginsGLPI/example * @link https://github.com/pluginsGLPI/example
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
use Glpi\Plugin\Hooks; use Glpi\Plugin\Hooks;
use GlpiPlugin\Example\Computer; use GlpiPlugin\Example\Computer;
use GlpiPlugin\Example\Config; use GlpiPlugin\Example\Config;
use GlpiPlugin\Example\Dropdown;
use GlpiPlugin\Example\DeviceCamera; use GlpiPlugin\Example\DeviceCamera;
use GlpiPlugin\Example\Dropdown;
use GlpiPlugin\Example\Example; use GlpiPlugin\Example\Example;
use GlpiPlugin\Example\Filters\ComputerModelFilter; use GlpiPlugin\Example\Filters\ComputerModelFilter;
use GlpiPlugin\Example\ItemForm; use GlpiPlugin\Example\ItemForm;
use GlpiPlugin\Example\Profile;
use GlpiPlugin\Example\RuleTestCollection; use GlpiPlugin\Example\RuleTestCollection;
use GlpiPlugin\Example\Showtabitem; use GlpiPlugin\Example\Showtabitem;
define('PLUGIN_EXAMPLE_VERSION', '0.0.1'); define('PLUGIN_EXAMPLE_VERSION', '0.1.0');
// Minimal GLPI version, inclusive // Minimal GLPI version, inclusive
define('PLUGIN_EXAMPLE_MIN_GLPI', '10.0.0'); define('PLUGIN_EXAMPLE_MIN_GLPI', '11.0.0');
// Maximum GLPI version, exclusive // Maximum GLPI version, exclusive
define('PLUGIN_EXAMPLE_MAX_GLPI', '10.0.99'); define('PLUGIN_EXAMPLE_MAX_GLPI', '11.0.99');
/** /**
* Init hooks of the plugin. * Init hooks of the plugin.
@@ -86,13 +86,11 @@ function plugin_init_example()
['device_types' => true], ['device_types' => true],
); );
if (version_compare(GLPI_VERSION, '9.1', 'ge')) { if (version_compare(GLPI_VERSION, '9.1', 'ge') && class_exists(Example::class)) {
if (class_exists(Example::class)) {
Link::registerTag(Example::$tags); Link::registerTag(Example::$tags);
} }
}
// Display a menu entry ? // Display a menu entry ?
Plugin::registerClass(\GlpiPlugin\Example\Profile::class, ['addtabon' => ['Profile']]); Plugin::registerClass(Profile::class, ['addtabon' => ['Profile']]);
if (Example::canView()) { // Right set in change_profile hook if (Example::canView()) { // Right set in change_profile hook
$PLUGIN_HOOKS['menu_toadd']['example'] = ['plugins' => Example::class, $PLUGIN_HOOKS['menu_toadd']['example'] = ['plugins' => Example::class,
'tools' => Example::class]; 'tools' => Example::class];
@@ -250,9 +248,6 @@ function plugin_init_example()
$PLUGIN_HOOKS['status']['example'] = 'plugin_example_Status'; $PLUGIN_HOOKS['status']['example'] = 'plugin_example_Status';
// CSRF compliance : All actions must be done via POST and forms closed by Html::closeForm();
$PLUGIN_HOOKS[Hooks::CSRF_COMPLIANT]['example'] = true;
$PLUGIN_HOOKS[Hooks::DISPLAY_CENTRAL]['example'] = 'plugin_example_display_central'; $PLUGIN_HOOKS[Hooks::DISPLAY_CENTRAL]['example'] = 'plugin_example_display_central';
$PLUGIN_HOOKS[Hooks::DISPLAY_LOGIN]['example'] = 'plugin_example_display_login'; $PLUGIN_HOOKS[Hooks::DISPLAY_LOGIN]['example'] = 'plugin_example_display_login';
$PLUGIN_HOOKS[Hooks::INFOCOM]['example'] = 'plugin_example_infocom_hook'; $PLUGIN_HOOKS[Hooks::INFOCOM]['example'] = 'plugin_example_infocom_hook';
@@ -267,11 +262,8 @@ function plugin_init_example()
$PLUGIN_HOOKS[Hooks::PRE_ITEM_FORM]['example'] = [ItemForm::class, 'preItemForm']; $PLUGIN_HOOKS[Hooks::PRE_ITEM_FORM]['example'] = [ItemForm::class, 'preItemForm'];
$PLUGIN_HOOKS[Hooks::POST_ITEM_FORM]['example'] = [ItemForm::class, 'postItemForm']; $PLUGIN_HOOKS[Hooks::POST_ITEM_FORM]['example'] = [ItemForm::class, 'postItemForm'];
//TODO: remove check when GLPI 11.0.0 is released
if (version_compare(GLPI_VERSION, '11.0.0', 'ge')) {
$PLUGIN_HOOKS[Hooks::PRE_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'preSection']; $PLUGIN_HOOKS[Hooks::PRE_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'preSection'];
$PLUGIN_HOOKS[Hooks::POST_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'postSection']; $PLUGIN_HOOKS[Hooks::POST_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'postSection'];
}
// Add new actions to timeline // Add new actions to timeline
$PLUGIN_HOOKS[Hooks::TIMELINE_ACTIONS]['example'] = [ $PLUGIN_HOOKS[Hooks::TIMELINE_ACTIONS]['example'] = [
@@ -297,12 +289,9 @@ function plugin_init_example()
ComputerModelFilter::class, ComputerModelFilter::class,
]; ];
//TODO: remove check when GLPI 11.0.0 is released
if (version_compare(GLPI_VERSION, '11.0.0', 'ge')) {
// Icon in the impact analysis // Icon in the impact analysis
$PLUGIN_HOOKS[Hooks::SET_ITEM_IMPACT_ICON]['example'] = 'plugin_example_set_impact_icon'; $PLUGIN_HOOKS[Hooks::SET_ITEM_IMPACT_ICON]['example'] = 'plugin_example_set_impact_icon';
} }
}
/** /**
@@ -337,11 +326,7 @@ function plugin_version_example()
*/ */
function plugin_example_check_prerequisites() function plugin_example_check_prerequisites()
{ {
if (false) { return !false;
return false;
}
return true;
} }
/** /**
@@ -358,8 +343,7 @@ function plugin_example_check_config($verbose = false)
} }
if ($verbose) { if ($verbose) {
echo __('Installed / not configured', 'example'); echo __s('Installed / not configured', 'example');
} }
return false; return false;
} }

View File

@@ -59,25 +59,25 @@ class Child extends CommonDBChild
// - CommonDBConnexity::HAVE_SAME_RIGHT_ON_ITEM we must have at least update right // - CommonDBConnexity::HAVE_SAME_RIGHT_ON_ITEM we must have at least update right
// on the item // on the item
// * $mustBeAttached: some CommonDBChild can be free, without any parent. // * $mustBeAttached: some CommonDBChild can be free, without any parent.
public static function canCreate() public static function canCreate(): bool
{ {
return (Session::haveRight('internet', UPDATE) return (Session::haveRight('internet', UPDATE)
&& parent::canCreate()); && parent::canCreate());
} }
public static function canView() public static function canView(): bool
{ {
return (Session::haveRight('internet', READ) return (Session::haveRight('internet', READ)
&& parent::canView()); && parent::canView());
} }
public static function canUpdate() public static function canUpdate(): bool
{ {
return (Session::haveRight('internet', UPDATE) return (Session::haveRight('internet', UPDATE)
&& parent::canUpdate()); && parent::canUpdate());
} }
public static function canDelete() public static function canDelete(): bool
{ {
return (Session::haveRight('internet', DELETE) return (Session::haveRight('internet', DELETE)
&& parent::canDelete()); && parent::canDelete());

View File

@@ -37,23 +37,17 @@ namespace GlpiPlugin\Example;
use CommonDBTM; use CommonDBTM;
// Class of the defined type
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access directly to this file");
}
class Computer extends CommonDBTM class Computer extends CommonDBTM
{ {
public static function showInfo() public static function showInfo()
{ {
echo '<table class="tab_glpi" width="100%">'; echo '<table class="tab_glpi" width="100%">';
echo '<tr>'; echo '<tr>';
echo '<th>' . __('More information') . '</th>'; echo '<th>' . __s('More information') . '</th>';
echo '</tr>'; echo '</tr>';
echo '<tr class="tab_bg_1">'; echo '<tr class="tab_bg_1">';
echo '<td>'; echo '<td>';
echo __('Test successful'); echo __s('Test successful');
echo '</td>'; echo '</td>';
echo '</tr>'; echo '</tr>';
echo '</table>'; echo '</table>';
@@ -71,7 +65,7 @@ class Computer extends CommonDBTM
public static function add_default_where($in) public static function add_default_where($in)
{ {
list($itemtype, $condition) = $in; [$itemtype, $condition] = $in;
if ($itemtype == 'Computer') { if ($itemtype == 'Computer') {
$table = getTableForItemType($itemtype); $table = getTableForItemType($itemtype);
$condition .= ' (' . $table . '.groups_id NOT IN (' . implode(',', $_SESSION['glpigroups']) . '))'; $condition .= ' (' . $table . '.groups_id NOT IN (' . implode(',', $_SESSION['glpigroups']) . '))';

View File

@@ -44,10 +44,8 @@ class Config extends CommonDBTM
public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
{ {
if (!$withtemplate) { if (!$withtemplate && $item->getType() == 'Config') {
if ($item->getType() == 'Config') { return __s('Example plugin');
return __('Example plugin');
}
} }
return ''; return '';
@@ -73,10 +71,10 @@ class Config extends CommonDBTM
echo "<form name='form' action=\"" . Toolbox::getItemTypeFormURL('Config') . "\" method='post'>"; echo "<form name='form' action=\"" . Toolbox::getItemTypeFormURL('Config') . "\" method='post'>";
echo "<div class='center' id='tabsbody'>"; echo "<div class='center' id='tabsbody'>";
echo "<table class='tab_cadre_fixe'>"; echo "<table class='tab_cadre_fixe'>";
echo "<tr><th colspan='4'>" . __('Example setup') . '</th></tr>'; echo "<tr><th colspan='4'>" . __s('Example setup') . '</th></tr>';
echo '<td >' . __('My boolean choice :') . '</td>'; echo '<td >' . __s('My boolean choice :') . '</td>';
echo "<td colspan='3'>"; echo "<td colspan='3'>";
echo "<input type='hidden' name='config_class' value='" . __CLASS__ . "'>"; echo "<input type='hidden' name='config_class' value='" . self::class . "'>";
echo "<input type='hidden' name='config_context' value='plugin:Example'>"; echo "<input type='hidden' name='config_context' value='plugin:Example'>";
Dropdown::showYesNo('configuration', $my_config['configuration']); Dropdown::showYesNo('configuration', $my_config['configuration']);
echo '</td></tr>'; echo '</td></tr>';
@@ -96,5 +94,6 @@ class Config extends CommonDBTM
$config = new self(); $config = new self();
$config->showFormExample(); $config->showFormExample();
} }
return true;
} }
} }

View File

@@ -37,17 +37,11 @@ namespace GlpiPlugin\Example;
use CommonDevice; use CommonDevice;
// Class of the defined type
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access directly to this file");
}
/// Class DeviceCamera /// Class DeviceCamera
class DeviceCamera extends CommonDevice class DeviceCamera extends CommonDevice
{ {
public static function getTypeName($nb = 0) public static function getTypeName($nb = 0)
{ {
return _n('Camera', 'Cameras', $nb); return _sn('Camera', 'Cameras', $nb);
} }
} }

View File

@@ -1,30 +1,31 @@
<?php <?php
/* /**
------------------------------------------------------------------------- * -------------------------------------------------------------------------
GLPI - Gestionnaire Libre de Parc Informatique * Example plugin for GLPI
Copyright (C) 2003-2011 by the INDEPNET Development Team. * -------------------------------------------------------------------------
*
http://indepnet.net/ http://glpi-project.org * LICENSE
------------------------------------------------------------------------- *
* This file is part of Example.
LICENSE *
* Example is free software; you can redistribute it and/or modify
This file is part of GLPI. * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
GLPI is free software; you can redistribute it and/or modify * (at your option) any later version.
it under the terms of the GNU General Public License as published by *
the Free Software Foundation; either version 2 of the License, or * Example is distributed in the hope that it will be useful,
(at your option) any later version. * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GLPI is distributed in the hope that it will be useful, * GNU General Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License
GNU General Public License for more details. * along with Example. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
You should have received a copy of the GNU General Public License * @copyright Copyright (C) 2006-2022 by Example plugin team.
along with GLPI. If not, see <http://www.gnu.org/licenses/>. * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
-------------------------------------------------------------------------- * @link https://github.com/pluginsGLPI/example
* -------------------------------------------------------------------------
*/ */
/** /**
@@ -58,10 +59,6 @@ namespace GlpiPlugin\Example;
use Document as GlpiDocument; use Document as GlpiDocument;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
class Document extends GlpiDocument class Document extends GlpiDocument
{ {
/** /**
@@ -74,9 +71,9 @@ class Document extends GlpiDocument
public static function getTable($classname = null) public static function getTable($classname = null)
{ {
if ($classname === null) { if ($classname === null) {
$classname = get_called_class(); $classname = static::class;
} }
if ($classname == get_called_class()) { if ($classname == static::class) {
return parent::getTable(Document::class); return parent::getTable(Document::class);
} }
@@ -128,11 +125,9 @@ class Document extends GlpiDocument
public function post_getFromDB() public function post_getFromDB()
{ {
// Check the user can view this itemtype and can view this item // Check the user can view this itemtype and can view this item
if ($this->canView() && $this->canViewItem()) { if ($this->canView() && $this->canViewItem() && (isset($_SERVER['HTTP_ACCEPT']) && $_SERVER['HTTP_ACCEPT'] == 'application/octet-stream' || isset($_GET['alt']) && $_GET['alt'] == 'media')) {
if (isset($_SERVER['HTTP_ACCEPT']) && $_SERVER['HTTP_ACCEPT'] == 'application/octet-stream' $this->sendFile();
|| isset($_GET['alt']) && $_GET['alt'] == 'media') { // and terminate script
$this->sendFile(); // and terminate script
}
} }
} }
@@ -167,8 +162,7 @@ class Document extends GlpiDocument
} }
// set range if specified by the client // set range if specified by the client
if (isset($_SERVER['HTTP_RANGE'])) { if (isset($_SERVER['HTTP_RANGE']) && preg_match('/bytes=\h*(\d+)?-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) {
if (preg_match('/bytes=\h*(\d+)?-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) {
if (!empty($matches[1])) { if (!empty($matches[1])) {
$begin = intval($matches[1]); $begin = intval($matches[1]);
} }
@@ -176,7 +170,6 @@ class Document extends GlpiDocument
$end = min(intval($matches[2]), $end); $end = min(intval($matches[2]), $end);
} }
} }
}
// seek to the begining of the range // seek to the begining of the range
$currentPosition = $begin; $currentPosition = $begin;

View File

@@ -43,9 +43,9 @@ class Dropdown extends CommonDropdown
public static function getTypeName($nb = 0) public static function getTypeName($nb = 0)
{ {
if ($nb > 0) { if ($nb > 0) {
return __('Plugin Example Dropdowns', 'example'); return __s('Plugin Example Dropdowns', 'example');
} }
return __('Plugin Example Dropdowns', 'example'); return __s('Plugin Example Dropdowns', 'example');
} }
} }

View File

@@ -35,13 +35,19 @@
namespace GlpiPlugin\Example; namespace GlpiPlugin\Example;
use Central;
use CommonDBTM; use CommonDBTM;
use CommonGLPI; use CommonGLPI;
use Computer; use Computer;
use Html; use Html;
use Item_Disk;
use Log; use Log;
use MassiveAction; use MassiveAction;
use Notification;
use Phone;
use Preference;
use Session; use Session;
use Supplier;
// Class of the defined type // Class of the defined type
class Example extends CommonDBTM class Example extends CommonDBTM
@@ -57,7 +63,7 @@ class Example extends CommonDBTM
public static function getMenuName() public static function getMenuName()
{ {
return __('Example plugin'); return __s('Example plugin');
} }
public static function getAdditionalMenuLinks() public static function getAdditionalMenuLinks()
@@ -90,7 +96,7 @@ class Example extends CommonDBTM
echo "<tr class='tab_bg_1'>"; echo "<tr class='tab_bg_1'>";
echo '<td>' . __('ID') . '</td>'; echo '<td>' . __s('ID') . '</td>';
echo '<td>'; echo '<td>';
echo $ID; echo $ID;
echo '</td>'; echo '</td>';
@@ -106,28 +112,28 @@ class Example extends CommonDBTM
$tab[] = [ $tab[] = [
'id' => 'common', 'id' => 'common',
'name' => __('Header Needed'), 'name' => __s('Header Needed'),
]; ];
$tab[] = [ $tab[] = [
'id' => '1', 'id' => '1',
'table' => 'glpi_plugin_example_examples', 'table' => 'glpi_plugin_example_examples',
'field' => 'name', 'field' => 'name',
'name' => __('Name'), 'name' => __s('Name'),
]; ];
$tab[] = [ $tab[] = [
'id' => '2', 'id' => '2',
'table' => 'glpi_plugin_example_dropdowns', 'table' => 'glpi_plugin_example_dropdowns',
'field' => 'name', 'field' => 'name',
'name' => __('Dropdown'), 'name' => __s('Dropdown'),
]; ];
$tab[] = [ $tab[] = [
'id' => '3', 'id' => '3',
'table' => 'glpi_plugin_example_examples', 'table' => 'glpi_plugin_example_examples',
'field' => 'serial', 'field' => 'serial',
'name' => __('Serial number'), 'name' => __s('Serial number'),
'usehaving' => true, 'usehaving' => true,
'searchtype' => 'equals', 'searchtype' => 'equals',
]; ];
@@ -136,7 +142,7 @@ class Example extends CommonDBTM
'id' => '30', 'id' => '30',
'table' => 'glpi_plugin_example_examples', 'table' => 'glpi_plugin_example_examples',
'field' => 'id', 'field' => 'id',
'name' => __('ID'), 'name' => __s('ID'),
'usehaving' => true, 'usehaving' => true,
'searchtype' => 'equals', 'searchtype' => 'equals',
]; ];
@@ -155,8 +161,8 @@ class Example extends CommonDBTM
{ {
switch ($name) { switch ($name) {
case 'Sample': case 'Sample':
return ['description' => __('Cron description for example', 'example'), return ['description' => __s('Cron description for example', 'example'),
'parameter' => __('Cron parameter for example', 'example')]; 'parameter' => __s('Cron parameter for example', 'example')];
} }
return []; return [];
@@ -167,7 +173,7 @@ class Example extends CommonDBTM
* *
* @param $task Object of CronTask class for log / stat * @param $task Object of CronTask class for log / stat
* *
* @return interger * @return int
* >0 : done * >0 : done
* <0 : to be run again (not finished) * <0 : to be run again (not finished)
* 0 : nothing to do * 0 : nothing to do
@@ -211,33 +217,34 @@ class Example extends CommonDBTM
public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
{ {
if (!$withtemplate) { if (!$withtemplate) {
switch ($item->getType()) { if ($item instanceof Profile) {
case 'Profile':
if ($item->getField('central')) { if ($item->getField('central')) {
return __('Example', 'example'); return __s('Example', 'example');
} }
break;
case 'Phone': } elseif ($item instanceof Phone) {
if ($_SESSION['glpishow_count_on_tabs']) { if ($_SESSION['glpishow_count_on_tabs']) {
return self::createTabEntry( return self::createTabEntry(
__('Example', 'example'), __s('Example', 'example'),
countElementsInTable($this->getTable()), countElementsInTable($this->getTable()),
); );
} }
return __('Example', 'example'); return __s('Example', 'example');
case 'ComputerDisk': } elseif ($item instanceof Item_Disk || $item instanceof Supplier) {
case 'Supplier': return [
return [1 => __('Test Plugin', 'example'), 1 => __s('Test Plugin', 'example'),
2 => __('Test Plugin 2', 'example')]; 2 => __s('Test Plugin 2', 'example'),
];
case 'Computer': } elseif ($item instanceof Computer
case 'Central': || $item instanceof Central
case 'Preference': || $item instanceof Preference
case 'Notification': || $item instanceof Notification) {
return [1 => __('Test Plugin', 'example')]; return [
1 => __s('Test Plugin', 'example'),
];
} }
} }
@@ -246,16 +253,13 @@ class Example extends CommonDBTM
public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0)
{ {
switch ($item->getType()) { if ($item instanceof Phone) {
case 'Phone': echo __s('Plugin Example on Phone', 'example');
echo __('Plugin Example on Phone', 'example');
break;
case 'Central': } elseif ($item instanceof Central) {
echo __('Plugin central action', 'example'); echo __s('Plugin central action', 'example');
break;
case 'Preference': } elseif ($item instanceof Preference) {
// Complete form display // Complete form display
$data = plugin_version_example(); $data = plugin_version_example();
@@ -272,27 +276,23 @@ class Example extends CommonDBTM
echo '</table>'; echo '</table>';
echo '</form>'; echo '</form>';
break;
case 'Notification': } elseif ($item instanceof Notification) {
echo __('Plugin mailing action', 'example'); echo __s('Plugin mailing action', 'example');
break;
case 'ComputerDisk': } elseif ($item instanceof Item_Disk || $item instanceof Supplier) {
case 'Supplier':
if ($tabnum == 1) { if ($tabnum == 1) {
echo __('First tab of Plugin example', 'example'); echo __s('First tab of Plugin example', 'example');
} else { } else {
echo __('Second tab of Plugin example', 'example'); echo __s('Second tab of Plugin example', 'example');
} }
break;
default: } else {
//TRANS: %1$s is a class name, %2$d is an item ID //TRANS: %1$s is a class name, %2$d is an item ID
printf(__('Plugin example CLASS=%1$s id=%2$d', 'example'), $item->getType(), $item->getField('id')); printf(__s('Plugin example CLASS=%1$s', 'example'), get_class($item));
break;
} }
return true; return true;
} }
@@ -320,7 +320,7 @@ class Example extends CommonDBTM
$key = $parm['begin'] . '$$$' . 'plugin_example1'; $key = $parm['begin'] . '$$$' . 'plugin_example1';
$output[$key]['begin'] = date('Y-m-d 17:00:00'); $output[$key]['begin'] = date('Y-m-d 17:00:00');
$output[$key]['end'] = date('Y-m-d 18:00:00'); $output[$key]['end'] = date('Y-m-d 18:00:00');
$output[$key]['name'] = __('test planning example 1', 'example'); $output[$key]['name'] = __s('test planning example 1', 'example');
// Specify the itemtype to be able to use specific display system // Specify the itemtype to be able to use specific display system
$output[$key]['itemtype'] = Example::class; $output[$key]['itemtype'] = Example::class;
// Set the ID using the ID of the item in the database to have unique ID // Set the ID using the ID of the item in the database to have unique ID
@@ -337,7 +337,7 @@ class Example extends CommonDBTM
* @param $type position of the item in the time block (in, through, begin or end) * @param $type position of the item in the time block (in, through, begin or end)
* @param $complete complete display (more details) * @param $complete complete display (more details)
* *
* @return Nothing (display function) * @return void (display function)
**/ **/
public static function displayPlanningItem(array $val, $who, $type = '', $complete = 0) public static function displayPlanningItem(array $val, $who, $type = '', $complete = 0)
{ {
@@ -347,7 +347,7 @@ class Example extends CommonDBTM
case 'in': case 'in':
//TRANS: %1$s is the start time of a planned item, %2$s is the end //TRANS: %1$s is the start time of a planned item, %2$s is the end
printf( printf(
__('From %1$s to %2$s :'), __s('From %1$s to %2$s :'),
date('H:i', strtotime($val['begin'])), date('H:i', strtotime($val['begin'])),
date('H:i', strtotime($val['end'])), date('H:i', strtotime($val['end'])),
); );
@@ -359,12 +359,12 @@ class Example extends CommonDBTM
case 'begin': case 'begin':
//TRANS: %s is the start time of a planned item //TRANS: %s is the start time of a planned item
printf(__('Start at %s:'), date('H:i', strtotime($val['begin']))); printf(__s('Start at %s:'), date('H:i', strtotime($val['begin'])));
break; break;
case 'end': case 'end':
//TRANS: %s is the end time of a planned item //TRANS: %s is the end time of a planned item
printf(__('End at %s:'), date('H:i', strtotime($val['end']))); printf(__s('End at %s:'), date('H:i', strtotime($val['end'])));
break; break;
} }
echo '<br>'; echo '<br>';
@@ -384,7 +384,7 @@ class Example extends CommonDBTM
{ {
switch ($data['linked_action'] - Log::HISTORY_PLUGIN) { switch ($data['linked_action'] - Log::HISTORY_PLUGIN) {
case 0: case 0:
return __('History from plugin example', 'example'); return __s('History from plugin example', 'example');
} }
return ''; return '';
@@ -397,7 +397,7 @@ class Example extends CommonDBTM
$actions = parent::getSpecificMassiveActions($checkitem); $actions = parent::getSpecificMassiveActions($checkitem);
$actions['Document_Item' . MassiveAction::CLASS_ACTION_SEPARATOR . 'add'] = _x('button', 'Add a document'); // GLPI core one $actions['Document_Item' . MassiveAction::CLASS_ACTION_SEPARATOR . 'add'] = _x('button', 'Add a document'); // GLPI core one
$actions[__CLASS__ . MassiveAction::CLASS_ACTION_SEPARATOR . 'do_nothing'] = __('Do Nothing - just for fun', 'example'); // Specific one $actions[self::class . MassiveAction::CLASS_ACTION_SEPARATOR . 'do_nothing'] = __s('Do Nothing - just for fun', 'example'); // Specific one
return $actions; return $actions;
} }
@@ -408,12 +408,12 @@ class Example extends CommonDBTM
case 'DoIt': case 'DoIt':
echo "&nbsp;<input type='hidden' name='toto' value='1'>" . echo "&nbsp;<input type='hidden' name='toto' value='1'>" .
Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']) . Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']) .
' ' . __('Write in item history', 'example'); ' ' . __s('Write in item history', 'example');
return true; return true;
case 'do_nothing': case 'do_nothing':
echo '&nbsp;' . Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']) . echo '&nbsp;' . Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']) .
' ' . __('but do nothing :)', 'example'); ' ' . __s('but do nothing :)', 'example');
return true; return true;
} }
@@ -436,8 +436,8 @@ class Example extends CommonDBTM
switch ($ma->getAction()) { switch ($ma->getAction()) {
case 'DoIt': case 'DoIt':
if ($item->getType() == 'Computer') { if ($item->getType() == 'Computer') {
Session::addMessageAfterRedirect(__('Right it is the type I want...', 'example')); Session::addMessageAfterRedirect(__s('Right it is the type I want...', 'example'));
Session::addMessageAfterRedirect(__('Write in item history', 'example')); Session::addMessageAfterRedirect(__s('Write in item history', 'example'));
$changes = [0, 'old value', 'new value']; $changes = [0, 'old value', 'new value'];
foreach ($ids as $id) { foreach ($ids as $id) {
if ($item->getFromDB($id)) { if ($item->getFromDB($id)) {
@@ -464,8 +464,8 @@ class Example extends CommonDBTM
case 'do_nothing': case 'do_nothing':
if ($item->getType() == Example::class) { if ($item->getType() == Example::class) {
Session::addMessageAfterRedirect(__('Right it is the type I want...', 'example')); Session::addMessageAfterRedirect(__s('Right it is the type I want...', 'example'));
Session::addMessageAfterRedirect(__( Session::addMessageAfterRedirect(__s(
'But... I say I will do nothing for:', 'But... I say I will do nothing for:',
'example', 'example',
)); ));
@@ -487,27 +487,27 @@ class Example extends CommonDBTM
parent::processMassiveActionsForOneItemtype($ma, $item, $ids); parent::processMassiveActionsForOneItemtype($ma, $item, $ids);
} }
public static function generateLinkContents($link, CommonDBTM $item) public static function generateLinkContents($link, CommonDBTM $item, bool $safe_url = true)
{ {
if (strstr($link, '[EXAMPLE_ID]')) { if (strstr($link, '[EXAMPLE_ID]')) {
$link = str_replace('[EXAMPLE_ID]', $item->getID(), $link); $link = str_replace('[EXAMPLE_ID]', (string) $item->getID(), $link);
return [$link]; return [$link];
} }
return parent::generateLinkContents($link, $item); return parent::generateLinkContents($link, $item, $safe_url);
} }
public static function dashboardTypes() public static function dashboardTypes()
{ {
return [ return [
'example' => [ 'example' => [
'label' => __('Plugin Example', 'example'), 'label' => __s('Plugin Example', 'example'),
'function' => Example::class . '::cardWidget', 'function' => Example::class . '::cardWidget',
'image' => 'https://via.placeholder.com/100x86?text=example', 'image' => 'https://via.placeholder.com/100x86?text=example',
], ],
'example_static' => [ 'example_static' => [
'label' => __('Plugin Example (static)', 'example'), 'label' => __s('Plugin Example (static)', 'example'),
'function' => Example::class . '::cardWidgetWithoutProvider', 'function' => Example::class . '::cardWidgetWithoutProvider',
'image' => 'https://via.placeholder.com/100x86?text=example+static', 'image' => 'https://via.placeholder.com/100x86?text=example+static',
], ],
@@ -522,16 +522,16 @@ class Example extends CommonDBTM
$new_cards = [ $new_cards = [
'plugin_example_card' => [ 'plugin_example_card' => [
'widgettype' => ['example'], 'widgettype' => ['example'],
'label' => __('Plugin Example card'), 'label' => __s('Plugin Example card'),
'provider' => Example::class . '::cardDataProvider', 'provider' => Example::class . '::cardDataProvider',
], ],
'plugin_example_card_without_provider' => [ 'plugin_example_card_without_provider' => [
'widgettype' => ['example_static'], 'widgettype' => ['example_static'],
'label' => __('Plugin Example card without provider'), 'label' => __s('Plugin Example card without provider'),
], ],
'plugin_example_card_with_core_widget' => [ 'plugin_example_card_with_core_widget' => [
'widgettype' => ['bigNumber'], 'widgettype' => ['bigNumber'],
'label' => __('Plugin Example card with core provider'), 'label' => __s('Plugin Example card with core provider'),
'provider' => Example::class . '::cardBigNumberProvider', 'provider' => Example::class . '::cardBigNumberProvider',
], ],
]; ];
@@ -605,14 +605,8 @@ class Example extends CommonDBTM
public static function cardBigNumberProvider(array $params = []) public static function cardBigNumberProvider(array $params = [])
{ {
$default_params = [
'label' => null,
'icon' => null,
];
$params = array_merge($default_params, $params);
return [ return [
'number' => rand(), 'number' => random_int(0, mt_getrandmax()),
'url' => 'https://www.linux.org/', 'url' => 'https://www.linux.org/',
'label' => 'plugin example - some text', 'label' => 'plugin example - some text',
'icon' => 'fab fa-linux', // font awesome icon 'icon' => 'fab fa-linux', // font awesome icon

View File

@@ -38,7 +38,7 @@ class ComputerModelFilter extends AbstractFilter
{ {
public static function getName(): string public static function getName(): string
{ {
return __('Computer model'); return __s('Computer model');
} }
public static function getId(): string public static function getId(): string
@@ -48,6 +48,7 @@ class ComputerModelFilter extends AbstractFilter
public static function canBeApplied(string $table): bool public static function canBeApplied(string $table): bool
{ {
/** @var DBmysql $DB */
global $DB; global $DB;
return $DB->fieldExists($table, ComputerModel::getForeignKeyField()); return $DB->fieldExists($table, ComputerModel::getForeignKeyField());

View File

@@ -50,9 +50,6 @@ class ItemForm
*/ */
public static function preSection($params) public static function preSection($params)
{ {
$item = $params['item'];
$options = $params['options'];
echo TemplateRenderer::getInstance()->renderFromStringTemplate(<<<TWIG echo TemplateRenderer::getInstance()->renderFromStringTemplate(<<<TWIG
<section class="accordion-item" aria-label="a label"> <section class="accordion-item" aria-label="a label">
<h2 class="accordion-header" id="example-heading" title="example-heading-id" data-bs-toggle="tooltip"> <h2 class="accordion-header" id="example-heading" title="example-heading-id" data-bs-toggle="tooltip">
@@ -81,9 +78,6 @@ TWIG, []);
*/ */
public static function postSection($params) public static function postSection($params)
{ {
$item = $params['item'];
$options = $params['options'];
echo TemplateRenderer::getInstance()->renderFromStringTemplate(<<<TWIG echo TemplateRenderer::getInstance()->renderFromStringTemplate(<<<TWIG
<section class="accordion-item" aria-label="a label"> <section class="accordion-item" aria-label="a label">
<h2 class="accordion-header" id="example-heading" title="example-heading-id" data-bs-toggle="tooltip"> <h2 class="accordion-header" id="example-heading" title="example-heading-id" data-bs-toggle="tooltip">
@@ -119,25 +113,25 @@ TWIG, []);
$out = '<tr><th colspan="' . (isset($options['colspan']) ? $options['colspan'] * 2 : '4') . '">'; $out = '<tr><th colspan="' . (isset($options['colspan']) ? $options['colspan'] * 2 : '4') . '">';
$out .= sprintf( $out .= sprintf(
__('Start %1$s hook call for %2$s type'), __s('Start %1$s hook call for %2$s type'),
'pre_item_form', 'pre_item_form',
$item::getType(), $item::getType(),
); );
$out .= '</th></tr>'; $out .= '</th></tr>';
$out .= "<tr><$firstelt>"; $out .= "<tr><$firstelt>";
$out .= '<label for="example_pre_form_hook">' . __('First pre form hook') . '</label>'; $out .= '<label for="example_pre_form_hook">' . __s('First pre form hook') . '</label>';
$out .= "</$firstelt><td>"; $out .= "</$firstelt><td>";
$out .= '<input type="text" name="example_pre_form_hook" id="example_pre_form_hook"/>'; $out .= '<input type="text" name="example_pre_form_hook" id="example_pre_form_hook"/>';
$out .= "</td><$firstelt>"; $out .= "</td><$firstelt>";
$out .= '<label for="example_pre_form_hook2">' . __('Second pre form hook') . '</label>'; $out .= '<label for="example_pre_form_hook2">' . __s('Second pre form hook') . '</label>';
$out .= "</$firstelt><td>"; $out .= "</$firstelt><td>";
$out .= '<input type="text" name="example_pre_form_hook2" id="example_pre_form_hook2"/>'; $out .= '<input type="text" name="example_pre_form_hook2" id="example_pre_form_hook2"/>';
$out .= '</td></tr>'; $out .= '</td></tr>';
$out .= '<tr><th colspan="' . (isset($options['colspan']) ? $options['colspan'] * 2 : '4') . '">'; $out .= '<tr><th colspan="' . (isset($options['colspan']) ? $options['colspan'] * 2 : '4') . '">';
$out .= sprintf( $out .= sprintf(
__('End %1$s hook call for %2$s type'), __s('End %1$s hook call for %2$s type'),
'pre_item_form', 'pre_item_form',
$item::getType(), $item::getType(),
); );
@@ -162,25 +156,25 @@ TWIG, []);
$out = '<tr><th colspan="' . (isset($options['colspan']) ? $options['colspan'] * 2 : '4') . '">'; $out = '<tr><th colspan="' . (isset($options['colspan']) ? $options['colspan'] * 2 : '4') . '">';
$out .= sprintf( $out .= sprintf(
__('Start %1$s hook call for %2$s type'), __s('Start %1$s hook call for %2$s type'),
'post_item_form', 'post_item_form',
$item::getType(), $item::getType(),
); );
$out .= '</th></tr>'; $out .= '</th></tr>';
$out .= "<tr><$firstelt>"; $out .= "<tr><$firstelt>";
$out .= '<label for="example_post_form_hook">' . __('First post form hook') . '</label>'; $out .= '<label for="example_post_form_hook">' . __s('First post form hook') . '</label>';
$out .= "</$firstelt><td>"; $out .= "</$firstelt><td>";
$out .= '<input type="text" name="example_post_form_hook" id="example_post_form_hook"/>'; $out .= '<input type="text" name="example_post_form_hook" id="example_post_form_hook"/>';
$out .= "</td><$firstelt>"; $out .= "</td><$firstelt>";
$out .= '<label for="example_post_form_hook2">' . __('Second post form hook') . '</label>'; $out .= '<label for="example_post_form_hook2">' . __s('Second post form hook') . '</label>';
$out .= "</$firstelt><td>"; $out .= "</$firstelt><td>";
$out .= '<input type="text" name="example_post_form_hook2" id="example_post_form_hook2"/>'; $out .= '<input type="text" name="example_post_form_hook2" id="example_post_form_hook2"/>';
$out .= '</td></tr>'; $out .= '</td></tr>';
$out .= '<tr><th colspan="' . (isset($options['colspan']) ? $options['colspan'] * 2 : '4') . '">'; $out .= '<tr><th colspan="' . (isset($options['colspan']) ? $options['colspan'] * 2 : '4') . '">';
$out .= sprintf( $out .= sprintf(
__('End %1$s hook call for %2$s type'), __s('End %1$s hook call for %2$s type'),
'post_item_form', 'post_item_form',
$item::getType(), $item::getType(),
); );
@@ -209,7 +203,7 @@ JAVASCRIPT;
echo "<li class='followup' id='email_transfer_$rand'> echo "<li class='followup' id='email_transfer_$rand'>
<i class='far fa-envelope'></i>" . <i class='far fa-envelope'></i>" .
__('Send a notification') . __s('Send a notification') .
Html::scriptBlock($JS) . ' Html::scriptBlock($JS) . '
</li>'; </li>';
} }

View File

@@ -40,10 +40,6 @@ namespace GlpiPlugin\Example;
use GlpiPlugin\Example\DeviceCamera; use GlpiPlugin\Example\DeviceCamera;
use Item_Devices; use Item_Devices;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access directly to this file");
}
/** /**
* Relation between item and devices * Relation between item and devices
**/ **/

View File

@@ -32,10 +32,6 @@ namespace GlpiPlugin\Example;
use NotificationTarget; use NotificationTarget;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access directly to this file");
}
// Class NotificationTarget // Class NotificationTarget
class NotificationTargetExample extends NotificationTarget class NotificationTargetExample extends NotificationTarget
{ {
@@ -46,8 +42,6 @@ class NotificationTargetExample extends NotificationTarget
public function addDataForTemplate($event, $options = []) public function addDataForTemplate($event, $options = [])
{ {
global $DB, $CFG_GLPI; $this->data['##example.name##'] = __s('Example', 'example');
$this->data['##example.name##'] = __('Example', 'example');
} }
} }

View File

@@ -34,18 +34,28 @@ use CommonGLPI;
use Html; use Html;
use Session; use Session;
final class Profile extends \Profile class Profile extends \Profile
{ {
public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
{ {
return __('Example plugin'); if (
$item instanceof \Profile
&& $item->getField('id')
) {
return self::createTabEntry(__s('Example plugin'));
}
return '';
} }
public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0)
{ {
if ($item instanceof self) {
$profile = new self(); $profile = new self();
$profile->showFormExample($item->getID()); $profile->showFormExample($item->getID());
} }
return true;
}
public function showFormExample(int $profiles_id): void public function showFormExample(int $profiles_id): void
{ {

View File

@@ -37,11 +37,6 @@ namespace GlpiPlugin\Example;
use Rule; use Rule;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access directly to this file");
}
/** /**
* Rule class store all informations about a GLPI rule : * Rule class store all informations about a GLPI rule :
* - description * - description
@@ -69,7 +64,7 @@ class RuleTest extends Rule
{ {
$criterias = []; $criterias = [];
$criterias['name']['field'] = 'name'; $criterias['name']['field'] = 'name';
$criterias['name']['name'] = __('Software'); $criterias['name']['name'] = __s('Software');
$criterias['name']['table'] = 'glpi_softwares'; $criterias['name']['table'] = 'glpi_softwares';
return $criterias; return $criterias;
@@ -78,7 +73,7 @@ class RuleTest extends Rule
public function getActions() public function getActions()
{ {
$actions = []; $actions = [];
$actions['softwarecategories_id']['name'] = __('Category (class)', 'example'); $actions['softwarecategories_id']['name'] = __s('Category (class)', 'example');
$actions['softwarecategories_id']['type'] = 'dropdown'; $actions['softwarecategories_id']['type'] = 'dropdown';
$actions['softwarecategories_id']['table'] = 'glpi_softwarecategories'; $actions['softwarecategories_id']['table'] = 'glpi_softwarecategories';

View File

@@ -37,11 +37,6 @@ namespace GlpiPlugin\Example;
use RuleCollection; use RuleCollection;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access directly to this file");
}
class RuleTestCollection extends RuleCollection class RuleTestCollection extends RuleCollection
{ {
// From RuleCollection // From RuleCollection

View File

@@ -68,14 +68,15 @@ class Showtabitem
{ {
switch ($params['item']->getType()) { switch ($params['item']->getType()) {
case 'Ticket': case 'Ticket':
if ($params['options']['itemtype'] == 'TicketValidation' && $params['options']['tabnum'] == 2) {
// if tasks are not all done // if tasks are not all done
// then prevent solution div to show // then prevent solution div to show
// this is an example to prevent solving of ticket // this is an example to prevent solving of ticket
if (true) { // here you should test if some tasks are in todo status. if ($params['options']['itemtype'] == 'TicketValidation' && $params['options']['tabnum'] == 2 && true) {
$params['options']['prevent_solution'] = true; // this will be passed to the post_show hook // here you should test if some tasks are in todo status.
echo "<div id='toHideSolution' style='display: none;'>"; // in order to hide the default solution div $params['options']['prevent_solution'] = true;
} // this will be passed to the post_show hook
echo "<div id='toHideSolution' style='display: none;'>";
// in order to hide the default solution div
} }
} }
} }