";
161 | if (($canedit = Session::haveRightsOr(self::$rightname, [CREATE, UPDATE, PURGE]))
162 | && $openform) {
163 | $profile = new \Profile();
164 | echo "
";
185 | }
186 |
187 | /**
188 | * @param bool $all
189 | *
190 | * @return array
191 | */
192 | static function getAllRights($all = false)
193 | {
194 | $rights = [
195 | ['itemtype' => Typology::class,
196 | 'label' => _n('Typology', 'Typologies', 2, 'typology'),
197 | 'field' => 'plugin_typology'
198 | ],
199 | ];
200 |
201 | return $rights;
202 | }
203 |
204 | /**
205 | * Init profiles
206 | *
207 | **/
208 |
209 | static function translateARight($old_right)
210 | {
211 | switch ($old_right) {
212 | case '':
213 | return 0;
214 | case 'r':
215 | return READ;
216 | case 'w':
217 | return ALLSTANDARDRIGHT + READNOTE + UPDATENOTE;
218 | case '0':
219 | case '1':
220 | return $old_right;
221 |
222 | default:
223 | return 0;
224 | }
225 | }
226 |
227 | /**
228 | * @since 0.85
229 | * Migration rights from old system to the new one for one profile
230 | * @param $profiles_id
231 | */
232 | static function migrateOneProfile($profiles_id)
233 | {
234 | global $DB;
235 | //Cannot launch migration if there's nothing to migrate...
236 | if (!$DB->tableExists('glpi_plugin_typology_profiles')) {
237 | return true;
238 | }
239 |
240 | foreach ($DB->request([
241 | 'FROM' => 'glpi_plugin_typology_profiles',
242 | 'WHERE' => ['profiles_id' => $profiles_id]
243 | ]) as $profile_data) {
244 | $matching = ['typology' => 'plugin_typology'];
245 | $current_rights = ProfileRight::getProfileRights($profiles_id, array_values($matching));
246 | foreach ($matching as $old => $new) {
247 | if (!isset($current_rights[$old])) {
248 | $query = "UPDATE `glpi_profilerights`
249 | SET `rights`='".self::translateARight($profile_data[$old])."'
250 | WHERE `name`='$new' AND `profiles_id`='$profiles_id'";
251 | $DB->doQuery($query);
252 | }
253 | }
254 | }
255 | }
256 |
257 | /**
258 | * Initialize profiles, and migrate it necessary
259 | */
260 | static function initProfile()
261 | {
262 | global $DB;
263 | $profile = new self();
264 | $dbu = new DbUtils();
265 | //Add new rights in glpi_profilerights table
266 | foreach ($profile->getAllRights(true) as $data) {
267 | if ($dbu->countElementsInTable(
268 | "glpi_profilerights",
269 | ["name" => $data['field']]
270 | ) == 0) {
271 | ProfileRight::addProfileRights([$data['field']]);
272 | }
273 | }
274 |
275 | //Migration old rights in new ones
276 | foreach ($DB->request([
277 | 'SELECT' => ['id'],
278 | 'FROM' => 'glpi_profiles'
279 | ]) as $prof) {
280 | self::migrateOneProfile($prof['id']);
281 | }
282 | foreach ($DB->request([
283 | 'SELECT' => '*',
284 | 'FROM' => 'glpi_profilerights',
285 | 'WHERE' => [
286 | 'profiles_id' => $_SESSION['glpiactiveprofile']['id'],
287 | 'name' => ['LIKE' => '%plugin_typology%']
288 | ]
289 | ]) as $prof) {
290 | $_SESSION['glpiactiveprofile'][$prof['name']] = $prof['rights'];
291 | }
292 | }
293 |
294 |
295 | static function removeRightsFromSession()
296 | {
297 | foreach (self::getAllRights(true) as $right) {
298 | if (isset($_SESSION['glpiactiveprofile'][$right['field']])) {
299 | unset($_SESSION['glpiactiveprofile'][$right['field']]);
300 | }
301 | }
302 | }
303 | }
304 |
--------------------------------------------------------------------------------
/src/NotificationTargetTypology.php:
--------------------------------------------------------------------------------
1 | .
28 | --------------------------------------------------------------------------
29 | */
30 |
31 | namespace GlpiPlugin\Typology;
32 |
33 | use DbUtils;
34 | use Dropdown;
35 | use Notification;
36 | use Notification_NotificationTemplate;
37 | use NotificationTarget;
38 | use NotificationTemplate;
39 | use NotificationTemplateTranslation;
40 | use Toolbox;
41 |
42 | /**
43 | * Class NotificationTargetTypology
44 | */
45 | class NotificationTargetTypology extends NotificationTarget
46 | {
47 | /**
48 | * Return main notification events for the object type
49 | * Internal use only => should use getAllEvents
50 | *
51 | * @return array which contains : event => event label
52 | **/
53 | public function getEvents()
54 | {
55 |
56 | return ['AlertNotValidatedTypology' => __('Elements not match with the typology', 'typology')];
57 | }
58 |
59 | /**
60 | * Get all data needed for template processing
61 | * Provides minimum information for alerts
62 | * Can be overridden by each NotificationTartget class if needed
63 | *
64 | * @param string $event Event name
65 | * @param array $options Options
66 | *
67 | * @return void
68 | **/
69 | public function addDataForTemplate($event, $options = [])
70 | {
71 | global $CFG_GLPI;
72 |
73 | if ($event == 'AlertNotValidatedTypology') {
74 | $this->data['##typology.entity##']
75 | = Dropdown::getDropdownName(
76 | 'glpi_entities',
77 | $options['entities_id']
78 | );
79 | $this->data['##lang.typology.entity##'] = __('Entity');
80 | $this->data['##typology.action##'] = __('Elements not match with the typology', 'typology');
81 |
82 | $this->data['##lang.typology.name##'] = Typology::getTypeName(1);
83 | $this->data['##lang.typology.itemtype##'] = __('Type');
84 | $this->data['##lang.typology.items_id##'] = __('Name');
85 | $this->data['##lang.typology.error##'] = __('Error');
86 | $this->data['##lang.typology.url##'] = __('Link to the typology', 'typology');
87 | $this->data['##lang.typology.itemurl##'] = __('Link to the element', 'typology');
88 | $this->data['##lang.typology.itemuser##'] = __('User');
89 | $this->data['##lang.typology.itemlocation##'] = __('Location');
90 |
91 | $dbu = new DbUtils();
92 | foreach ($options['items'] as $id => $item) {
93 | $tmp = [];
94 |
95 | $tmp['##typology.name##'] = $item['name'];
96 | $itemtype = new $item['itemtype']();
97 | $itemtype->getFromDB($item["items_id"]);
98 | $tmp['##typology.itemtype##'] = $itemtype->getTypeName();
99 | $tmp['##typology.items_id##'] = $itemtype->getName();
100 | $tmp['##typology.error##'] = Typology_Item::displayErrors($item['error'], false);
101 | $tmp['##typology.url##'] = urldecode($CFG_GLPI["url_base"] . "/index.php?redirect=GlpiPlugin\Typology\Typology_"
102 | . $item['plugin_typology_typologies_id']);
103 | $tmp['##typology.itemurl##'] = urldecode($CFG_GLPI["url_base"] . "/index.php?redirect="
104 | . Toolbox::strtolower($item['itemtype']) . "_" . $item["items_id"]);
105 | $tmp['##typology.itemuser##'] = $dbu->getUserName($itemtype->fields["users_id"]);
106 | $tmp['##typology.itemlocation##'] = Dropdown::getDropdownName(
107 | "glpi_locations",
108 | $itemtype->fields['locations_id']
109 | );
110 |
111 | $this->data['typologyitems'][] = $tmp;
112 | }
113 | }
114 | }
115 |
116 | /**
117 | * @return array|void
118 | */
119 | public function getTags()
120 | {
121 |
122 | $tags = ['typology.name' => Typology::getTypeName(1),
123 | 'typology.itemtype' => __('Type'),
124 | 'typology.items_id' => __('Name'),
125 | 'typology.error' => __('Error'),
126 | 'typology.url' => __('Link to the typology', 'typology'),
127 | 'typology.itemurl' => __('Link to the element', 'typology'),
128 | 'typology.itemuser' => __('User'),
129 | 'typology.itemlocation' => __('Location')];
130 | foreach ($tags as $tag => $label) {
131 | $this->addTagToList(['tag' => $tag,'label' => $label,
132 | 'value' => true]);
133 | }
134 | asort($this->tag_descriptions);
135 | }
136 |
137 | public static function install()
138 | {
139 | global $DB;
140 |
141 | $template = new NotificationTemplate();
142 | $query_id = "SELECT `id`
143 | FROM `glpi_notificationtemplates`
144 | WHERE `itemtype`='GlpiPlugin\\Typology\\Typology'
145 | AND `name` = 'Alert no validated typology'";
146 | $result = $DB->doQuery($query_id) or die($DB->error());
147 |
148 | if ($DB->numrows($result) > 0) {
149 | $templates_id = $DB->result($result, 0, 'id');
150 | } else {
151 | $tmp = [
152 | 'name' => 'Alert no validated typology',
153 | 'itemtype' => Typology::class,
154 | 'date_mod' => $_SESSION['glpi_currenttime'],
155 | 'comment' => '',
156 | 'css' => '',
157 | ];
158 | $templates_id = $template->add($tmp);
159 | }
160 |
161 | if ($templates_id) {
162 | $dbu = new DbUtils();
163 | $translation = new NotificationTemplateTranslation();
164 | if (!$dbu->countElementsInTable(
165 | $translation->getTable(),
166 | ["notificationtemplates_id" => $templates_id]
167 | )) {
168 | $tmp['notificationtemplates_id'] = $templates_id;
169 | $tmp['language'] = '';
170 | $tmp['subject'] = '##typology.action## : ##typology.entity##';
171 | $tmp['content_text'] = '##FOREACHitems##
172 | ##lang.typology.name## : ##typology.name##
173 | ##lang.typology.itemtype## : ##typology.itemtype##
174 | ##lang.typology.items_id## : ##typology.items_id##
175 | ##lang.typology.itemlocation## : ##typology.itemlocation##
176 | ##lang.typology.itemuser## : ##typology.itemuser##
177 | ##lang.typology.error## : ##typology.error##
178 | ##ENDFOREACHitems##';
179 | $tmp['content_html'] = '<table class="tab_cadre" border="1" cellspacing="2" cellpadding="3">
180 | <tbody>
181 | <tr>
182 | <td style="text-align: left;" bgcolor="#cccccc"><span style="font-family: Verdana; font-size: 11px; text-align: left;">##lang.typology.name##</span></td>
183 | <td style="text-align: left;" bgcolor="#cccccc"><span style="font-family: Verdana; font-size: 11px; text-align: left;">##lang.typology.itemtype##</span></td>
184 | <td style="text-align: left;" bgcolor="#cccccc"><span style="font-family: Verdana; font-size: 11px; text-align: left;">##lang.typology.items_id##</span></td>
185 | <td style="text-align: left;" bgcolor="#cccccc"><span style="font-family: Verdana; font-size: 11px; text-align: left;">##lang.typology.itemlocation##</span></td>
186 | <td style="text-align: left;" bgcolor="#cccccc"><span style="font-family: Verdana; font-size: 11px; text-align: left;">##lang.typology.itemuser##</span></td>
187 | <td style="text-align: left;" bgcolor="#cccccc"><span style="font-family: Verdana; font-size: 11px; text-align: left;">##lang.typology.error##</span></td>
188 | </tr>
189 | ##FOREACHtypologyitems##
190 | <tr>
191 | <td><a href="##typology.url##" target="_blank"><span style="font-family: Verdana; font-size: 11px; text-align: left;">##typology.name##</span></a></td>
192 | <td><span style="font-family: Verdana; font-size: 11px; text-align: left;">##typology.itemtype##</span></td>
193 | <td><a href="##typology.itemurl##" target="_blank"><span style="font-family: Verdana; font-size: 11px; text-align: left;">##typology.items_id##</span></a></td>
194 | <td><span style="font-family: Verdana; font-size: 11px; text-align: left;">##typology.itemlocation##</span></td>
195 | <td><span style="font-family: Verdana; font-size: 11px; text-align: left;">##typology.itemuser##</span></td>
196 | <td><span style="font-family: Verdana; font-size: 11px; text-align: left;">##typology.error##</span></td>
197 | </tr>
198 | ##ENDFOREACHtypologyitems##
199 | </tbody>
200 | </table>';
201 |
202 | $translation->add($tmp);
203 | }
204 |
205 | $notifs = [
206 | 'Alert no validated typology' => 'AlertNotValidatedTypology',
207 | ];
208 | $notification = new Notification();
209 | $notificationtemplate = new Notification_NotificationTemplate();
210 | $dbu = new DbUtils();
211 | foreach ($notifs as $label => $name) {
212 | if (!$dbu->countElementsInTable(
213 | "glpi_notifications",
214 | ["itemtype" => Typology::class,
215 | "event" => $name]
216 | )) {
217 | $tmp = [
218 | 'name' => $label,
219 | 'entities_id' => 0,
220 | 'itemtype' => Typology::class,
221 | 'event' => $name,
222 | 'comment' => '',
223 | 'is_recursive' => 1,
224 | 'is_active' => 1,
225 | 'date_mod' => $_SESSION['glpi_currenttime'],
226 | ];
227 | $notification_id = $notification->add($tmp);
228 |
229 | $notificationtemplate->add(['notificationtemplates_id' => $templates_id,
230 | 'mode' => 'mailing',
231 | 'notifications_id' => $notification_id]);
232 | }
233 | }
234 | }
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/hook.php:
--------------------------------------------------------------------------------
1 | .
28 | --------------------------------------------------------------------------
29 | */
30 |
31 | use GlpiPlugin\Typology\NotificationTargetTypology;
32 | use GlpiPlugin\Typology\Profile;
33 | use GlpiPlugin\Typology\RuleTypology;
34 | use GlpiPlugin\Typology\Typology;
35 | use GlpiPlugin\Typology\Typology_Item;
36 |
37 | function plugin_typology_install()
38 | {
39 | global $DB;
40 |
41 | if (!$DB->tableExists("glpi_plugin_typology_typologies")) {
42 | $update = false;
43 | // table sql creation
44 | $DB->runFile(PLUGIN_TYPOLOGY_DIR . "/sql/empty-4.0.0.sql");
45 |
46 | // Add record notification
47 | call_user_func([NotificationTargetTypology::class, 'install']);
48 | }
49 |
50 | if ($DB->tableExists("glpi_plugin_typology_typologycriterias")) {
51 | $query = "UPDATE `glpi_plugin_typology_typologycriterias`
52 | SET `itemtype`='IPAddress'
53 | WHERE `itemtype`='NetworkPort'";
54 | $DB->doQuery($query);
55 |
56 | $query = "UPDATE `glpi_plugin_typology_typologycriteriadefinitions`
57 | SET `field`='name;glpi_ipaddresses;itemlink'
58 | WHERE `field` LIKE '%glpi_networkports%'";
59 | $DB->doQuery($query);
60 | }
61 |
62 | if ($DB->tableExists("glpi_plugin_typology_profiles")) {
63 | $notepad_tables = ['glpi_plugin_typology_typologies'];
64 | $dbu = new DbUtils();
65 | foreach ($notepad_tables as $t) {
66 | // Migrate data
67 | $iterator = $DB->request([
68 | 'SELECT' => [
69 | 'notepad',
70 | 'id',
71 | ],
72 | 'FROM' => $t,
73 | 'WHERE' => [
74 | 'NOT' => ['notepad' => null],
75 | 'notepad' => ['<>', ''],
76 | ],
77 | ]);
78 | if (count($iterator) > 0) {
79 | foreach ($iterator as $data) {
80 | $iq = "INSERT INTO `glpi_notepads`
81 | (`itemtype`, `items_id`, `content`, `date`, `date_mod`)
82 | VALUES ('" . $dbu->getItemTypeForTable($t) . "', '" . $data['id'] . "',
83 | '" . addslashes($data['notepad']) . "', NOW(), NOW())";
84 | $DB->doQuery($iq, "0.85 migrate notepad data");
85 | }
86 | }
87 | $query = "ALTER TABLE `glpi_plugin_typology_typologies` DROP COLUMN `notepad`;";
88 | $DB->doQuery($query);
89 | }
90 | }
91 |
92 | CronTask::Register(Typology::class, 'UpdateTypology', DAY_TIMESTAMP);
93 | CronTask::Register(Typology::class, 'NotValidated', DAY_TIMESTAMP);
94 |
95 | Profile::initProfile();
96 | Profile::createFirstAccess($_SESSION['glpiactiveprofile']['id']);
97 | $migration = new Migration("2.3.0");
98 | $migration->dropTable('glpi_plugin_typology_profiles');
99 |
100 | return true;
101 | }
102 |
103 | // Uninstall process for plugin : need to return true if succeeded
104 | /**
105 | * @return bool
106 | */
107 | function plugin_typology_uninstall()
108 | {
109 | global $DB;
110 |
111 | //drop rules
112 | $Rule = new Rule();
113 | $a_rules = $Rule->find(['sub_type' => RuleTypology::class]);
114 | foreach ($a_rules as $data) {
115 | $Rule->delete($data);
116 | }
117 |
118 | // Plugin tables deletion
119 | $tables = ["glpi_plugin_typology_typologies",
120 | "glpi_plugin_typology_typologycriterias",
121 | "glpi_plugin_typology_typologycriteriadefinitions",
122 | "glpi_plugin_typology_typologies_items"];
123 |
124 | foreach ($tables as $table) {
125 | $DB->dropTable($table, true);
126 | }
127 |
128 | $tables_glpi = ["glpi_displaypreferences",
129 | "glpi_documents_items",
130 | "glpi_savedsearches",
131 | "glpi_notepads",
132 | "glpi_alerts",
133 | "glpi_links_itemtypes",
134 | "glpi_items_tickets",
135 | "glpi_dropdowntranslations",
136 | "glpi_impactitems"];
137 |
138 | foreach ($tables_glpi as $table_glpi) {
139 | $DB->delete($table_glpi, ['itemtype' => Typology::class]);
140 | }
141 |
142 |
143 | $notif = new Notification();
144 | $options = ['itemtype' => Typology::class,
145 | 'event' => 'AlertNotValidatedTypology'];
146 | foreach ($DB->request([
147 | 'FROM' => 'glpi_notifications',
148 | 'WHERE' => $options,
149 | ]) as $data) {
150 | $notif->delete($data);
151 | }
152 |
153 | //Delete rights associated with the plugin
154 | $profileRight = new ProfileRight();
155 | foreach (Profile::getAllRights() as $right) {
156 | $profileRight->deleteByCriteria(['name' => $right['field']]);
157 | }
158 | Typology::removeRightsFromSession();
159 |
160 | Profile::removeRightsFromSession();
161 |
162 | return true;
163 | }
164 |
165 | function plugin_typology_postinit()
166 | {
167 | global $PLUGIN_HOOKS;
168 |
169 | $PLUGIN_HOOKS['item_purge']['typology'] = [];
170 | $PLUGIN_HOOKS['item_add']['typology'] = [];
171 |
172 | foreach (Typology::getTypes(true) as $type) {
173 | $PLUGIN_HOOKS['item_purge']['typology'][$type]
174 | = [Typology_Item::class,'cleanItemTypology'];
175 | $PLUGIN_HOOKS['item_add']['typology'][$type]
176 | = [Typology_Item::class, 'addItem'];
177 | $PLUGIN_HOOKS['item_update']['typology'][$type]
178 | = [Typology_Item::class, 'updateItem'];
179 | CommonGLPI::registerStandardTab($type, Typology_Item::class);
180 | }
181 | }
182 |
183 | // Define dropdown relations
184 | /**
185 | * @return array
186 | */
187 | function plugin_typology_getDatabaseRelations()
188 | {
189 |
190 | if (Plugin::isPluginActive("typology")) {
191 | return ["glpi_entities" => ["glpi_plugin_typology_typologies" => "entities_id",
192 | "glpi_plugin_typology_typologycriterias" => "entities_id",
193 | "glpi_plugin_typology_typologycriteriadefinitions" => "entities_id"],
194 | "glpi_plugin_typology_typologies" => [
195 | "glpi_plugin_typology_typologycriterias" => "plugin_typology_typologies_id",
196 | "glpi_plugin_typology_typologies_items" => "plugin_typology_typologies_id"],
197 | "glpi_plugin_typology_typologycriterias" => [
198 | "glpi_plugin_typology_typologycriteriadefinitions" => "plugin_typology_typologycriterias_id"]];
199 | } else {
200 | return [];
201 | }
202 | }
203 |
204 | ////// SPECIFIC MODIF MASSIVE FUNCTIONS ///////
205 |
206 | // Define actions :
207 | /**
208 | * @param $type
209 | *
210 | * @return array
211 | */
212 | function plugin_typology_MassiveActions($type)
213 | {
214 |
215 | if (Plugin::isPluginActive('typology')) {
216 | switch ($type) {
217 | default:
218 | // Actions from items lists
219 | if (in_array($type, Typology::getTypes(true))) {
220 | return [
221 | 'GlpiPlugin\Typology\Typology_Item' . MassiveAction::CLASS_ACTION_SEPARATOR . 'add_item' => __('Assign a typology to this material', 'typology'),
222 | 'GlpiPlugin\Typology\Typology_Item' . MassiveAction::CLASS_ACTION_SEPARATOR . 'delete_item' => __('Delete the typology of this material', 'typology'),
223 | 'GlpiPlugin\Typology\Typology_Item' . MassiveAction::CLASS_ACTION_SEPARATOR . 'update_allitem' => __('Recalculate typology for the elements', 'typology')];
224 | }
225 | break;
226 | }
227 | }
228 | return [];
229 | }
230 |
231 | ////// SEARCH FUNCTIONS ///////(){
232 |
233 | // Define search option for types of the plugins
234 | /**
235 | * @param $itemtype
236 | *
237 | * @return array
238 | */
239 | function plugin_typology_getAddSearchOptions($itemtype)
240 | {
241 |
242 | $sopt = [];
243 |
244 | if (Plugin::isPluginActive('typology')
245 | && Session::haveRight("plugin_typology", READ)) {
246 | if (in_array($itemtype, Typology::getTypes(true))) {
247 | $sopt[4650]['table'] = 'glpi_plugin_typology_typologies';
248 | $sopt[4650]['field'] = 'name';
249 | $sopt[4650]['name'] = Typology::getTypeName(1) . " - "
250 | . __('Typology\'s name', 'typology');
251 | $sopt[4650]['forcegroupby'] = true;
252 | $sopt[4650]['datatype'] = 'itemlink';
253 | $sopt[4650]['massiveaction'] = false;
254 | $sopt[4650]['itemlink_type'] = Typology::class;
255 | $sopt[4650]['joinparams'] = ['beforejoin'
256 | => ['table' => 'glpi_plugin_typology_typologies_items',
257 | 'joinparams' => ['jointype' => 'itemtype_item']]];
258 |
259 | $sopt[4651]['table'] = 'glpi_plugin_typology_typologies_items';
260 | $sopt[4651]['field'] = 'is_validated';
261 | $sopt[4651]['datatype'] = 'bool';
262 | $sopt[4651]['massiveaction'] = false;
263 | $sopt[4651]['name'] = Typology::getTypeName(1) . " - "
264 | . __('Responding to typology\'s criteria', 'typology');
265 | $sopt[4651]['forcegroupby'] = true;
266 | $sopt[4651]['joinparams'] = ['jointype' => 'itemtype_item'];
267 |
268 | $sopt[4652]['table'] = 'glpi_plugin_typology_typologies_items';
269 | $sopt[4652]['field'] = 'error';
270 | $sopt[4652]['name'] = Typology::getTypeName(1) . " - "
271 | . __('Result details');
272 | $sopt[4652]['forcegroupby'] = true;
273 | $sopt[4652]['massiveaction'] = false;
274 | $sopt[4652]['joinparams'] = ['jointype' => 'itemtype_item'];
275 | }
276 | }
277 | return $sopt;
278 | }
279 |
280 | /**
281 | * @param $type
282 | * @param $ID
283 | * @param $data
284 | * @param $num
285 | *
286 | * @return
287 | */
288 | function plugin_typology_giveItem($type, $ID, $data, $num)
289 | {
290 |
291 | $options = Search::getOptions($type);
292 | $searchopt = & $options;
293 | $table = $searchopt[$ID]["table"];
294 | $field = $searchopt[$ID]["field"];
295 |
296 | switch ($type) {
297 | case 'Computer':
298 | switch ($table . '.' . $field) {
299 |
300 | case "glpi_plugin_typology_typologies_items.is_validated":
301 | if (empty($data[$num][0]['name'])) {
302 | $out = '';
303 | } else {
304 | $validated = explode("$$", $data[$num][0]['name']);
305 | $out = Dropdown::getYesNo($validated[0]);
306 | }
307 | return $out;
308 | case "glpi_plugin_typology_typologies_items.error":
309 | $list = explode("$$", $data[$num][0]['name']);
310 | $out = Typology_Item::displayErrors($list[0]);
311 | return $out;
312 | }
313 | break;
314 | }
315 | return "";
316 | }
317 |
318 | // Do special actions for dynamic report
319 | /**
320 | * @param $parm
321 | *
322 | * @return bool
323 | */
324 | function plugin_typology_dynamicReport($parm)
325 | {
326 |
327 | // Return false if no specific display is done, then use standard display
328 | return false;
329 | }
330 |
--------------------------------------------------------------------------------