├── .gitignore ├── LICENSE ├── README.md ├── fpsoftware.xml ├── front ├── config.form.php └── user_softwarelicense.form.php ├── hook.php ├── inc ├── common.class.php ├── config.class.php ├── licensehelper.class.php ├── userdetails.class.php ├── userslicenses.class.php └── versionhelper.class.php └── setup.php /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE files 2 | .idea/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Future Processing Sp. z o.o. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # glpi-fpsoftware 2 | GLPI plugin that allows to assign software to users. 3 | 4 | ## General Information 5 | By default GLPI does not allow to assign software to a user. As we all know a lot of software is currently licensed in per user model. FP Software plugin allows you to assign software to a user and view all his/hers licenses. 6 | 7 | It changes how software/license asset looks like by providing new tab to license where you can assign users to software and another tab to software so you can see all users using the software (no matter which licenses they are using). 8 | 9 | Global view of all licenses lists all users along with their machines, in that case if user has more than one PC he/she is listed more than once. This view can be modified to aggregate computers per license per user, by switching plugin's configuration option "Calculate licenses number per user instead of per computer". To do that, please go to plugins list, click "FP Software" plugin name and select desired option. 10 | 11 | 12 | ![License view – new “Users” tab](https://cloud.githubusercontent.com/assets/3634020/8588884/ca0d363a-260f-11e5-9a7c-8be8b4600eb2.png) 13 | 14 | **(License view – new “Users” tab)** 15 | 16 | ![Software view – new “Licenses – Users” tab](https://cloud.githubusercontent.com/assets/3634020/8588883/ca0995ca-260f-11e5-9e55-31dd860081ea.png) 17 | 18 | **(Software view – new “Licenses – Users” tab)** 19 | 20 | ![User view – new “Licenses” tab](https://cloud.githubusercontent.com/assets/3634020/8588885/ca1083b2-260f-11e5-85e3-0182aa70e4b4.png) 21 | 22 | **(User view – new “Licenses” tab)** 23 | 24 | In general this plugin makes GLPI more user-oriented instead of PC-oriented. 25 | 26 | ### Requirements 27 | GLPI 0.85.x, 0.90.x, 9.1.x - 9.4.x 28 | 29 | ### Install instructions 30 | 1. Copy plugin to plugins directory. 31 | 2. Install/enable plugin from Administration/Plugins 32 | section. 33 | 34 | Please be sure that name of the folder that contains plugin file is fpsoftware. 35 | 36 | If you want to display a sum of assigned computers and users in "Affected Computers" column you need to: 37 | - open inc/softwwarelicense.class.php (take a backup of this file before making any changes!); 38 | - look for following function - static function showForSoftware (Software $software); 39 | - around lines 780-787 modify following line of code: 40 | 41 | ``` 42 | $nb_assoc = Computer_SoftwareLicense::countForLicense($data['id']); 43 | ``` 44 | 45 | to 46 | 47 | ``` 48 | $nb_assoc = Computer_SoftwareLicense::countForLicense($data['id']) + PluginFpsoftwareCommon::countForLicense($data['id']); 49 | ``` 50 | 51 | ### What can be improved? 52 | * plugin does not validate total number of licenses with number of assigned licenses to users; 53 | -------------------------------------------------------------------------------- /fpsoftware.xml: -------------------------------------------------------------------------------- 1 | 2 | FP Software 3 | fpsoftware 4 | stable 5 | https://cloud.githubusercontent.com/assets/7323944/10058664/fc694b1e-6246-11e5-9047-64583a3d04ae.png 6 | 7 | 8 | 9 | 10 | 11 | It 13 | changes how software/license asset looks like by providing new tab to license where you can assign users to software and 14 | another tab to software so you can see all users using the software (no matter which licenses they are using).
In 15 | general this plugin makes GLPI more user-oriented instead of 16 | PC-oriented.

Changelog:

17 | 2022.01:

18 | - added sorting to both licenses in Software and User sections;
19 | - improved adding users to licenses by excluding users who are already assigned to it;
20 | - added validation - assigned user vs. no. of available licenses

21 | 2017.05:

22 | - plugin is now compatible with GLPI 9.1.3

23 | 2017.04:

24 | - plugin is now compatible with GLPI 9.1.2

25 | 2015.12:

26 | - Licenses - Users tab now shows proper per user license usage and groups PCs owned by a user;
27 | - "Affected Computers" can show how many licenses are assigned to both users and computers (please read manual on our GitHub)
28 | - plugin is now compatible with GLPI 0.90

29 | Company website]]>
30 |
31 |
32 | https://github.com/FutureProcessing/glpi-fpsoftware 33 | https://github.com/FutureProcessing/glpi-fpsoftware/archive/refs/tags/v.1.6.1.zip 34 | https://github.com/FutureProcessing/glpi-fpsoftware/issues 35 | https://github.com/FutureProcessing/glpi-fpsoftware/blob/master/README.md 36 | 37 | Future Processing 38 | 39 | 40 | 41 | 1.6.1 42 | 9.5.x 43 | 44 | 45 | 1.4 46 | 9.4.x 47 | 48 | 49 | 1.3 50 | 9.3.x 51 | 52 | 53 | 1.2 54 | 9.1.3 55 | 56 | 57 | 1.1 58 | 9.1.2 59 | 9.1.1 60 | 9.1 61 | 62 | 63 | 1.0 64 | 0.90 65 | 0.85 66 | 67 | 68 | 69 | en_GB 70 | 71 | 72 | 73 | 74 | Inventory 75 | 76 | 77 | Inventory 78 | 79 | 80 | 81 | https://cloud.githubusercontent.com/assets/3634020/8588884/ca0d363a-260f-11e5-9a7c-8be8b4600eb2.png 82 | https://cloud.githubusercontent.com/assets/3634020/8588883/ca0995ca-260f-11e5-9e55-31dd860081ea.png 83 | https://cloud.githubusercontent.com/assets/3634020/8588885/ca1083b2-260f-11e5-85e3-0182aa70e4b4.png 84 | 85 |
86 | -------------------------------------------------------------------------------- /front/config.form.php: -------------------------------------------------------------------------------- 1 | (int)(bool)$_POST['group_by_users'])); 11 | } 12 | HTML::back(); 13 | } 14 | 15 | 16 | HTML::header('Configuration of FP Software plugin'); 17 | 18 | $config->showFormDisplay(); 19 | 20 | HTML::footer(); 21 | 22 | -------------------------------------------------------------------------------- /front/user_softwarelicense.form.php: -------------------------------------------------------------------------------- 1 | 0 ) { 11 | if ($usl->add($_POST)) { 12 | Glpi\Event::log($_POST['softwarelicenses_id'], "softwarelicense", 4, "inventory", 13 | //TRANS: %s is the user login 14 | sprintf(__('%s associates an user and a license'), $_SESSION["glpiname"])); 15 | } 16 | } 17 | Html::back(); 18 | 19 | } 20 | 21 | Html::displayErrorAndDie('Lost'); 22 | 23 | ?> -------------------------------------------------------------------------------- /hook.php: -------------------------------------------------------------------------------- 1 | . 25 | 26 | ------------------------------------------------------------------------ 27 | 28 | @package FPFutures 29 | @author Future Processing 30 | @co-author 31 | @copyright Copyright (c) 2014 by Future Processing 32 | @license AGPL License 3.0 or (at your option) any later version 33 | http://www.gnu.org/licenses/agpl-3.0-standalone.html 34 | @since 2014 35 | 36 | ------------------------------------------------------------------------ 37 | */ 38 | 39 | /** 40 | * It is in these functions that you need to put your SQL queries used for creating your specific tables. 41 | * 42 | * Here, you can now see your plugin in the list of plugins. 43 | * 44 | * @return boolean Needs to return true if success 45 | */ 46 | 47 | function plugin_fpsoftware_install() { 48 | global $DB; 49 | 50 | if ( ! $DB->tableExists("glpi_users_softwarelicenses")) { 51 | $query = "CREATE TABLE IF NOT EXISTS `glpi_users_softwarelicenses` ( 52 | `id` int(11) NOT NULL AUTO_INCREMENT, 53 | `users_id` int(11) NOT NULL, 54 | `softwarelicenses_id` int(11) NOT NULL, 55 | `added` datetime NOT NULL, 56 | PRIMARY KEY (`id`) 57 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"; 58 | 59 | $DB->queryOrDie($query, "create glpi_users_softwarelicenses table"); 60 | } 61 | 62 | return true; 63 | } 64 | 65 | /** 66 | * Because we've created a table, do not forget to destroy if the plugin is uninstalled. 67 | * 68 | * @return boolean Needs to return true if success 69 | */ 70 | function plugin_fpsoftware_uninstall() { 71 | global $DB; 72 | 73 | if ($DB->tableExists("glpi_users_softwarelicenses")) { 74 | $query = "DROP TABLE glpi_users_softwarelicenses;"; 75 | 76 | $DB->queryOrDie($query, "drop glpi_users_softwarelicenses table"); 77 | } 78 | 79 | return true; 80 | } 81 | -------------------------------------------------------------------------------- /inc/common.class.php: -------------------------------------------------------------------------------- 1 | getTable(); 24 | $tab[2]['field'] = 'id'; 25 | $tab[2]['name'] = __('ID'); 26 | $tab[2]['massiveaction'] = false; 27 | $tab[2]['datatype'] = 'number'; 28 | 29 | $tab[4]['table'] = 'glpi_softwarelicenses'; 30 | $tab[4]['field'] = 'name'; 31 | $tab[4]['name'] = _n('License', 'Licenses', 1); 32 | $tab[4]['datatype'] = 'dropdown'; 33 | $tab[4]['massiveaction'] = false; 34 | 35 | $tab[5]['table'] = 'glpi_users'; 36 | $tab[5]['field'] = 'name'; 37 | $tab[5]['name'] = _n('User', 'Users', 1); 38 | $tab[5]['massiveaction'] = false; 39 | $tab[5]['datatype'] = 'dropdown'; 40 | 41 | return $tab; 42 | } 43 | 44 | /** 45 | * Add relationship user -> license to database 46 | * @param array $input 47 | * @param array $options 48 | * @param bool $history 49 | * @return bool 50 | */ 51 | function add(array $input, $options=array(), $history=true) { 52 | if ( (int) $input['softwarelicenses_id'] <= 0 || (int) $input['users_id'] <= 0) { 53 | return false; 54 | } 55 | 56 | global $DB; 57 | 58 | $users_id = (int) $input['users_id']; 59 | $softwarelicenses_id = (int) $input['softwarelicenses_id']; 60 | $added = date("Y-m-d H:i:s"); 61 | 62 | $query = "INSERT INTO glpi_users_softwarelicenses (users_id, softwarelicenses_id,added) VALUES($users_id,$softwarelicenses_id,'$added')"; 63 | $DB->query($query); 64 | 65 | return true; 66 | } 67 | 68 | /** 69 | * @see CommonDBTM::processMassiveActionsForOneItemtype() 70 | * @param MassiveAction $ma 71 | * @param CommonDBTM $item 72 | * @param array $ids 73 | * @return void 74 | */ 75 | static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $item, array $ids) { 76 | switch ($ma->getAction()) { 77 | case 'deleteSelected': 78 | if (isset($_POST['items']['PluginFpsoftwareCommon']) && is_array($_POST['items']['PluginFpsoftwareCommon'])) { 79 | foreach($_POST['items']['PluginFpsoftwareCommon'] as $id => $val) { 80 | self::deleteItem($id); 81 | $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); 82 | } 83 | } 84 | break; 85 | } 86 | } 87 | 88 | /** 89 | * @see CommonDBTM::doSpecificMassiveActions() 90 | * @param array $input 91 | * @return array 92 | */ 93 | function doSpecificMassiveActions($input=array()) { 94 | $res = array( 95 | 'ok' => 0, 96 | 'ko' => 0, 97 | 'noright' => 0 98 | ); 99 | switch ($input['action']) { 100 | case 'deleteSelected': 101 | if (isset($_POST['itemtype']) 102 | && $_POST['itemtype'] == 'PluginFpsoftwareCommon' 103 | && isset($_POST['item']) 104 | && is_array($_POST['item'])) { 105 | foreach($_POST['item'] as $id => $val) { 106 | self::deleteItem($id); 107 | $res['ok']++; 108 | } 109 | } else { 110 | $res['ko']++; 111 | } 112 | break; 113 | default : 114 | return parent::doSpecificMassiveActions($input); 115 | } 116 | return $res; 117 | } 118 | 119 | 120 | 121 | /** 122 | * Delete from database 123 | * @param int $id 124 | */ 125 | static function deleteItem($id) { 126 | global $DB; 127 | 128 | $id = (int) $id; 129 | 130 | if ($id > 0) { 131 | $query = "DELETE FROM glpi_users_softwarelicenses WHERE id = $id LIMIT 1"; 132 | $DB->query($query); 133 | } 134 | } 135 | 136 | /** 137 | * Count how many users have this license assigned. 138 | * 139 | * @global type $DB 140 | * @param type $softwarelicenses_id 141 | * @return int 142 | */ 143 | static function countForLicense($softwarelicenses_id) { 144 | global $DB; 145 | 146 | $query = "SELECT COUNT(`glpi_users_softwarelicenses`.`id`) 147 | FROM `glpi_users_softwarelicenses` 148 | INNER JOIN `glpi_users` 149 | ON (`glpi_users_softwarelicenses`.`users_id` = `glpi_users`.`id`) 150 | WHERE `glpi_users_softwarelicenses`.`softwarelicenses_id` = '$softwarelicenses_id'"; 151 | 152 | $result = $DB->query($query); 153 | 154 | if ($DB->numrows($result) != 0) { 155 | return $DB->result($result, 0, 0); 156 | } 157 | return 0; 158 | } 159 | 160 | /** 161 | * Returns the list of users not assigned to a license. 162 | * 163 | * @param int $license_id 164 | * 165 | * @return array 166 | */ 167 | private static function usersUnassignedToALicense(int $license_id): array 168 | { 169 | global $DB; 170 | 171 | $result = $DB->request( 172 | 'glpi_users_softwarelicenses', 173 | ['softwarelicenses_id' => $license_id] 174 | ); 175 | 176 | $users_assigned_to_a_license = []; 177 | 178 | foreach ($result as $data => $content) { 179 | $users_assigned_to_a_license[] = $content['users_id']; 180 | } 181 | 182 | if (empty($users_assigned_to_a_license)) { 183 | $result = $DB->request('glpi_users'); 184 | } else { 185 | $result = $DB->request( 186 | 'glpi_users', 187 | ['NOT' => ['id' => $users_assigned_to_a_license]] 188 | ); 189 | } 190 | 191 | $users_unassigned_to_a_license = []; 192 | 193 | foreach ($result as $data => $content) { 194 | $users_unassigned_to_a_license[] = $content['id']; 195 | } 196 | 197 | return $users_unassigned_to_a_license; 198 | } 199 | 200 | /** 201 | * Returns form with users assigned to license. 202 | * 203 | * @param SoftwareLicense $license 204 | * @param int $number_of_assigned_licenses 205 | * @param bool $can_edit 206 | * 207 | * @throws GlpitestSQLError 208 | */ 209 | private static function usersAssignedToLicenseForm( 210 | SoftwareLicense $license, 211 | int $number_of_assigned_licenses, 212 | bool $can_edit 213 | ): void { 214 | global $DB; 215 | global $CFG_GLPI; 216 | 217 | $start = isset($_GET['start']) ? $_GET['start'] : 0; 218 | $order = isset($_GET['order']) && ($_GET['order'] === 'DESC') ? $_GET['order'] : 'ASC'; 219 | $sort = !empty($_GET['sort']) ? $_GET['sort'] : 'username'; 220 | 221 | $license_id = $license->getField('id'); 222 | $query = "SELECT `glpi_users_softwarelicenses`.*, 223 | `glpi_users`.`name` AS username, 224 | `glpi_users`.`id` AS userid, 225 | `glpi_users`.`realname` AS userrealname, 226 | `glpi_users`.`firstname` AS userfirstname, 227 | `glpi_softwarelicenses`.`name` AS license, 228 | `glpi_softwarelicenses`.`id` AS lID 229 | FROM `glpi_users_softwarelicenses` 230 | INNER JOIN `glpi_softwarelicenses` 231 | ON (`glpi_users_softwarelicenses`.`softwarelicenses_id` 232 | = `glpi_softwarelicenses`.`id`) 233 | INNER JOIN `glpi_users` 234 | ON (`glpi_users_softwarelicenses`.`users_id` = `glpi_users`.`id`) 235 | WHERE `glpi_softwarelicenses`.`id` = '$license_id' 236 | ORDER BY $sort $order 237 | LIMIT ".intval($start)."," . intval($_SESSION['glpilist_limit']); 238 | 239 | $rand = mt_rand(); 240 | if ($result = $DB->query($query)) { 241 | if ($data = $DB->fetchAssoc($result)) { 242 | $parameters = "sort=$sort&order=$order"; 243 | $license_page_url = $CFG_GLPI['url_base'] . '/front/softwarelicense.form.php' . '?id=' . 244 | $license_id; 245 | Html::printPager($start, $number_of_assigned_licenses, $license_page_url, $parameters); 246 | 247 | if ($can_edit) { 248 | Html::openMassiveActionsForm('mass' . __CLASS__ . $rand); 249 | list($higher_version, $massive_action_params) = 250 | PluginFpsoftwareVersionhelper::massiveActionParams($rand, __CLASS__); 251 | 252 | $massive_action_params['extraparams']['options']['move']['used'] = [$license_id]; 253 | $massive_action_params['extraparams']['options']['move']['softwares_id'] 254 | = $license->fields['softwares_id']; 255 | Html::showMassiveActions($higher_version ? $massive_action_params : __CLASS__); 256 | } 257 | 258 | $software = new Software(); 259 | $software->getFromDB($license->fields['softwares_id']); 260 | 261 | $text = sprintf(__('%1$s = %2$s'), Software::getTypeName(1), $software->fields["name"]); 262 | $text = sprintf(__('%1$s - ID %2$s'), $text, $license->fields['softwares_id']); 263 | Session::initNavigateListItems('User', $text); 264 | 265 | echo ""; 266 | $columns = [ 267 | 'username' => __('Username'), 268 | 'userrealname' => __('Surname'), 269 | 'userfirstname' => __('First name'), 270 | 'added' => __('Added') 271 | ]; 272 | 273 | $header_begin = ""; 274 | $header_top = ''; 275 | $header_bottom = ''; 276 | $header_end = ''; 277 | if ($can_edit) { 278 | $header_begin .= ""; 282 | } 283 | 284 | foreach ($columns as $key => $value) { 285 | $header_end .= ""; 293 | } 294 | 295 | $header_end .= "\n"; 296 | echo $header_begin . $header_top . $header_end; 297 | 298 | do { 299 | Session::addToNavigateListItems('User', $data["userid"]); 300 | echo ""; 301 | if ($can_edit) { 302 | echo ""; 303 | } 304 | 305 | $can_show_user = User::canView(); 306 | if ($can_show_user) { 307 | echo ""; 308 | } else { 309 | echo ""; 310 | } 311 | 312 | echo ""; 313 | echo ""; 314 | echo ""; 315 | echo "\n"; 316 | } while ($data = $DB->fetchAssoc($result)); 317 | 318 | echo $header_begin . $header_bottom . $header_end; 319 | echo "
"; 279 | $header_top .= Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); 280 | $header_bottom .= Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); 281 | $header_end .= "" . $value . "
" . Html::getMassiveActionCheckBox(__CLASS__, $data["id"]) . "" . $data['username'] . "" . $data['username'] . "" . $data['userrealname'] . "" . $data['userfirstname'] . "" . $data['added'] . "
\n"; 320 | 321 | if ($can_edit) { 322 | $massive_action_params['ontop'] = false; 323 | Html::showMassiveActions($massive_action_params); 324 | Html::closeForm(); 325 | } 326 | } else { 327 | _e('No item found'); 328 | } 329 | } 330 | 331 | echo "\n"; 332 | } 333 | 334 | /** 335 | * Returns number of users assigned to license. 336 | * 337 | * @param int $license_id 338 | * 339 | * @return int 340 | * @throws GlpitestSQLError 341 | */ 342 | private static function numberOfUsersAssignedToLicense(int $license_id): int 343 | { 344 | global $DB; 345 | 346 | $query_number = "SELECT COUNT(*) AS cpt 347 | FROM `glpi_users_softwarelicenses` 348 | INNER JOIN `glpi_users` 349 | ON (`glpi_users_softwarelicenses`.`users_id` 350 | = `glpi_users`.`id`) 351 | WHERE `glpi_users_softwarelicenses`.`softwarelicenses_id` = '$license_id'"; 352 | 353 | $number = 0; 354 | if ($result = $DB->query($query_number)) { 355 | $number = $DB->result($result, 0, 0); 356 | } 357 | 358 | return $number; 359 | } 360 | 361 | /** 362 | * Displays form with available users. 363 | * 364 | * @param int $license_id 365 | */ 366 | private static function addUserForm(int $license_id): void 367 | { 368 | global $CFG_GLPI; 369 | 370 | $users = self::usersUnassignedToALicense($license_id); 371 | 372 | echo "
"; 374 | echo ""; 375 | 376 | echo ""; 377 | echo ""; 378 | echo ""; 388 | echo ""; 393 | 394 | echo "
"; 379 | Dropdown::show( 380 | 'User', 381 | [ 382 | 'width' => '80%', 383 | 'addicon' => false, 384 | 'condition' => ['id' => $users] 385 | ] 386 | ); 387 | echo ""; 392 | echo "
"; 395 | Html::closeForm(); 396 | } 397 | 398 | /** 399 | * Displays content for Users tab on license page. 400 | * 401 | * @param $license SoftwareLicense object 402 | * 403 | * @return void 404 | * 405 | * @throws GlpitestSQLError 406 | */ 407 | static function showForLicense(SoftwareLicense $license): void 408 | { 409 | $license_id = $license->getField('id'); 410 | if (!Software::canView() || !$license_id) { 411 | return; 412 | } 413 | 414 | $can_edit = PluginFpsoftwareVersionhelper::checkRights( 415 | "software", 416 | [CREATE, UPDATE, DELETE, PURGE], 417 | "Or" 418 | ); 419 | 420 | $license_helper = new PluginFpsoftwareLicenseHelper($license_id); 421 | if ($can_edit) { 422 | if ($license_helper->unlimited_licenses === false && 423 | $license_helper->getNumberOfAvailableLicenses() <= 0) { 424 | self::displayInfoAboutLicensesLimit(); 425 | } else { 426 | self::addUserForm($license_id); 427 | } 428 | } 429 | 430 | $number_of_assigned_licenses = $license_helper->getNumberOfAssignedLicenses(); 431 | if ($number_of_assigned_licenses < 1) { 432 | echo "
"; 433 | echo ""; 434 | echo "
" . __('No item found') . "
" . PHP_EOL; 435 | 436 | return; 437 | } 438 | 439 | self::usersAssignedToLicenseForm($license, $number_of_assigned_licenses, $can_edit); 440 | } 441 | 442 | /** 443 | * @see CommonGLPI::getTabNameForItem() 444 | **/ 445 | function getTabNameForItem(CommonGLPI $item, $withtemplate=0) { 446 | 447 | switch ($item->getType()) { 448 | case 'SoftwareLicense' : 449 | if (!$withtemplate) { 450 | $nb = 0; 451 | if ($_SESSION['glpishow_count_on_tabs']) { 452 | $nb = self::countForLicense($item->getID()); 453 | } 454 | 455 | return array( 456 | 1 => self::createTabEntry(User::getTypeName(2), $nb) 457 | ); 458 | } 459 | break; 460 | } 461 | 462 | return ''; 463 | } 464 | 465 | 466 | /** 467 | * DON'T KNOW IF $TABNUM IS USED ANYWHERE, IT SHOULD CHANGE DISPLAYING (MAKE 468 | * IT BY ENTITY), BUT THE METHOD IS NOT PREPARED. $WITHTEMPLATE IS NOT USED 469 | * EITHER. 470 | **/ 471 | static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) { 472 | if ($item->getType() == 'SoftwareLicense') { 473 | self::showForLicense($item); 474 | } 475 | return true; 476 | } 477 | 478 | public static function getFrontUrl(): string 479 | { 480 | return self::$front_url; 481 | } 482 | 483 | private static function displayInfoAboutLicensesLimit(): void 484 | { 485 | echo "
" . __( 486 | "You can't assign a license to next user. No licenses available. 487 | If you want to increase the number of licenses, go to the License tab." 488 | ) . "
"; 489 | } 490 | } 491 | -------------------------------------------------------------------------------- /inc/config.class.php: -------------------------------------------------------------------------------- 1 | 0, 9 | ); 10 | 11 | /** 12 | * Get configuration values 13 | * 14 | * @param array $options 15 | * 16 | * @return array 17 | */ 18 | public static function getConfigValues($options) 19 | { 20 | $config = Config::getConfigurationValues(self::$configContext, $options); 21 | 22 | return $config + self::$defaultValues; 23 | } 24 | 25 | /** 26 | * Set configuration value 27 | * 28 | * @param array $options 29 | */ 30 | public static function setConfigValues($options) 31 | { 32 | Config::setConfigurationValues(self::$configContext, $options); 33 | } 34 | 35 | /** 36 | * Print the config form for display 37 | * 38 | */ 39 | function showFormDisplay() 40 | { 41 | 42 | $options = self::getConfigValues(array('group_by_users')); 43 | 44 | echo ""; 45 | echo "
"; 46 | echo ""; 47 | 48 | echo ""; 49 | echo ""; 50 | echo ""; 53 | 54 | echo ""; 55 | echo ""; 58 | 59 | echo "
".__('FP Software config')."
".__('Calculate licenses number per user instead of per computer').""; 51 | Dropdown::showYesNo('group_by_users', $options['group_by_users']); 52 | echo "
"; 56 | echo ""; 57 | echo "
"; 60 | Html::closeForm(); 61 | } 62 | } -------------------------------------------------------------------------------- /inc/licensehelper.class.php: -------------------------------------------------------------------------------- 1 | license_id = $license_id; 18 | $this->unlimited_licenses = $this->setUnlimitedLicenses(); 19 | } 20 | 21 | private function setUnlimitedLicenses(): bool 22 | { 23 | return $this->getNumberOfLicenses() === -1; 24 | } 25 | 26 | private function getNumberOfLicenses(): int 27 | { 28 | global $DB; 29 | 30 | $result = $DB->request( 31 | [ 32 | 'SELECT' => 'number', 33 | 'FROM' => SoftwareLicense::getTable(), 34 | 'WHERE' => 35 | ['id' => $this->license_id] 36 | ] 37 | ); 38 | 39 | $number_of_licenses = []; 40 | foreach ($result as $data => $content) { 41 | $number_of_licenses[] = $content['number']; 42 | } 43 | 44 | return $number_of_licenses[0]; 45 | } 46 | 47 | public function getNumberOfAssignedLicenses(): int 48 | { 49 | global $DB; 50 | 51 | $query_number = "SELECT COUNT(*) AS cpt 52 | FROM `glpi_users_softwarelicenses` 53 | INNER JOIN `glpi_users` 54 | ON (`glpi_users_softwarelicenses`.`users_id` 55 | = `glpi_users`.`id`) 56 | WHERE `glpi_users_softwarelicenses`.`softwarelicenses_id` = '$this->license_id'"; 57 | 58 | $number = 0; 59 | if ($result = $DB->query($query_number)) { 60 | $number = $DB->result($result, 0, 0); 61 | } 62 | 63 | return $number; 64 | } 65 | 66 | /** 67 | * Returns the number of available licenses. 68 | * 69 | * Should only be used when unlimited_licenses is equal false. 70 | * 71 | * @return int|null 72 | */ 73 | public function getNumberOfAvailableLicenses(): ?int 74 | { 75 | if ($this->unlimited_licenses) { 76 | return null; 77 | } 78 | 79 | return $this->getNumberOfLicenses() - $this->getNumberOfAssignedLicenses(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /inc/userdetails.class.php: -------------------------------------------------------------------------------- 1 | query($query); 25 | 26 | if ($DB->numrows($result) != 0) { 27 | return $DB->result($result, 0, 0); 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | /** 34 | * Displays a table with the licenses linked with the user. 35 | * 36 | * @param User $user 37 | * 38 | * @return bool 39 | * @throws GlpitestSQLError 40 | */ 41 | static function showLicenses(User $user): bool 42 | { 43 | global $DB; 44 | 45 | $id = $user->getField('id'); 46 | self::addLicenseForm($id); 47 | 48 | $order = isset($_GET['order']) && ($_GET['order'] === 'DESC') ? $_GET['order'] : 'ASC'; 49 | $sort = !empty($_GET['sort']) ? $_GET['sort'] : 'software_name'; 50 | 51 | $query = "SELECT 52 | ul.added, 53 | sl.name AS licenses_name, 54 | s.name AS software_name, 55 | sl.id AS licenses_id, 56 | s.id AS software_id, 57 | ul.id AS softwarelicenses_id 58 | FROM 59 | glpi_users_softwarelicenses ul 60 | JOIN glpi_softwarelicenses sl ON (sl.id = ul.softwarelicenses_id) 61 | JOIN glpi_softwares s ON (s.id = sl.softwares_id) 62 | WHERE 63 | ul.users_id = '$id' 64 | ORDER BY 65 | $sort $order"; 66 | 67 | $result = $DB->query($query); 68 | if ($DB->numrows($result) <= 0) { 69 | echo '
' . __( 70 | 'No items found.' 71 | ) . '
'; 72 | 73 | return true; 74 | } 75 | 76 | $rand = mt_rand(); 77 | Html::openMassiveActionsForm('mass' . __CLASS__ . $rand); 78 | list($higher_version, $massive_action_params) = 79 | PluginFpsoftwareVersionhelper::massiveActionParams($rand, __CLASS__); 80 | Html::showMassiveActions($higher_version ? $massive_action_params : __CLASS__); 81 | echo '
'; 82 | $columns = [ 83 | 'software_name' => __('Software'), 84 | 'licenses_name' => __('Licenses'), 85 | 'added' => __('Added') 86 | ]; 87 | 88 | $header_begin = ""; 89 | $header_begin .= ""; 93 | 94 | foreach ($columns as $key => $value) { 95 | $header_end .= ""; 103 | } 104 | 105 | $header_end .= ""; 106 | echo $header_begin . $header_top . $header_end; 107 | 108 | while ($data = $DB->fetchAssoc($result)) { 109 | echo ''; 110 | echo ''; 114 | $software_link = '"software.form.php?id=' . $data['software_id'] . '"'; 115 | $license_link = '"softwarelicense.form.php?id=' . $data['licenses_id'] . '"'; 116 | echo ''; 117 | echo ''; 118 | echo ''; 119 | echo ''; 120 | } 121 | 122 | echo $header_begin . $header_bottom . $header_end; 123 | echo "
"; 90 | $header_top = Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); 91 | $header_bottom = Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); 92 | $header_end = "" . $value . "
' . Html::getMassiveActionCheckBox( 111 | __CLASS__, 112 | $data['softwarelicenses_id'] 113 | ) . '' . $data['software_name'] . '' . $data['licenses_name'] . '' . $data['added'] . '
"; 124 | $massive_action_params['ontop'] = false; 125 | Html::showMassiveActions($massive_action_params); 126 | Html::closeForm(); 127 | echo '
' . PHP_EOL; 128 | 129 | return true; 130 | } 131 | 132 | /** 133 | * Displays form with available licenses. 134 | * 135 | * @param int $user_id User id 136 | */ 137 | private static function addLicenseForm(int $user_id): void 138 | { 139 | global $CFG_GLPI; 140 | 141 | $licenses = PluginFpsoftwareUsersLicenses::getLicensesUnassignedToUser($user_id); 142 | 143 | foreach ($licenses as $key => $license_id) { 144 | $license_helper = new PluginFpsoftwareLicenseHelper($license_id); 145 | if ($license_helper->unlimited_licenses === false && 146 | $license_helper->getNumberOfAvailableLicenses() <= 0) { 147 | unset($licenses[$key]); 148 | } 149 | } 150 | 151 | echo ""; 154 | echo ""; 155 | echo ""; 156 | echo ""; 157 | echo ""; 169 | echo ""; 174 | echo "
"; 158 | 159 | Dropdown::show( 160 | 'SoftwareLicense', 161 | [ 162 | 'width' => '80%', 163 | 'addicon' => false, 164 | 'condition' => ['id' => $licenses] 165 | ] 166 | ); 167 | 168 | echo ""; 173 | echo "
"; 175 | Html::closeForm(); 176 | } 177 | 178 | /** 179 | * @see CommonGLPI::getTabNameForItem() 180 | **/ 181 | function getTabNameForItem(CommonGLPI $item, $withtemplate=0) { 182 | 183 | switch ($item->getType()) { 184 | case 'User' : 185 | if (!$withtemplate) { 186 | $nb = 0; 187 | if ($_SESSION['glpishow_count_on_tabs']) { 188 | $nb = self::countForUserLicense($item->getID()); 189 | } 190 | 191 | return array( 192 | 1 => self::createTabEntry(SoftwareLicense::getTypeName(2), $nb) 193 | ); 194 | } 195 | break; 196 | } 197 | 198 | return ''; 199 | } 200 | 201 | /** 202 | * @see CommonGLPI::displayTabContentForItem() 203 | */ 204 | static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) { 205 | if ($item->getType() == 'User') { 206 | self::showLicenses($item); 207 | } 208 | 209 | return true; 210 | } 211 | 212 | static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $item, array $ids) 213 | { 214 | if ($ma->getAction() === 'deleteSelected' && isset($_POST['items']['PluginFpsoftwareUserdetails']) && is_array( 215 | $_POST['items']['PluginFpsoftwareUserdetails'])) { 216 | foreach (array_keys($_POST['items']['PluginFpsoftwareUserdetails']) as $id) { 217 | PluginFpsoftwareCommon::deleteItem($id); 218 | $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); 219 | } 220 | } 221 | } 222 | 223 | } 224 | -------------------------------------------------------------------------------- /inc/userslicenses.class.php: -------------------------------------------------------------------------------- 1 | getType() == 'Software' && $item instanceof Software; 25 | } 26 | 27 | private static function getCountQuery($softwareId=0) { 28 | $options = PluginFpsoftwareConfig::getConfigValues(array('group_by_users')); 29 | 30 | if ($options['group_by_users']) { 31 | return "SELECT 32 | COUNT(*) AS rows_number 33 | FROM 34 | glpi_users_softwarelicenses users_softwarelicenses 35 | JOIN glpi_softwarelicenses softwarelicenses ON users_softwarelicenses.softwarelicenses_id = softwarelicenses.id 36 | JOIN glpi_users users ON users_softwarelicenses.users_id = users.id 37 | LEFT JOIN glpi_softwarelicensetypes softwarelicensetypes ON softwarelicenses.softwarelicensetypes_id = softwarelicensetypes.id 38 | WHERE 39 | softwarelicenses.softwares_id = '$softwareId'"; 40 | } 41 | else { 42 | return "SELECT 43 | COUNT(*) AS rows_number 44 | FROM 45 | glpi_users_softwarelicenses users_softwarelicenses 46 | JOIN glpi_softwarelicenses softwarelicenses ON users_softwarelicenses.softwarelicenses_id = softwarelicenses.id 47 | JOIN glpi_users users ON users_softwarelicenses.users_id = users.id 48 | LEFT JOIN glpi_computers computers ON users.id = computers.users_id 49 | LEFT JOIN glpi_locations locations ON computers.locations_id = locations.id 50 | LEFT JOIN glpi_softwarelicensetypes softwarelicensetypes ON softwarelicenses.softwarelicensetypes_id = softwarelicensetypes.id 51 | WHERE 52 | softwarelicenses.softwares_id = '$softwareId'"; 53 | } 54 | } 55 | 56 | private static function getDataQuery($softwareId=0, $start, $sort, $order) { 57 | $options = PluginFpsoftwareConfig::getConfigValues(array('group_by_users')); 58 | 59 | if ($options['group_by_users']) { 60 | return "SELECT 61 | softwarelicenses.id AS license_id, 62 | softwarelicenses.name AS license_name, 63 | softwarelicenses.serial AS license_serial, 64 | softwarelicensetypes.name AS license_type, 65 | users.id AS user_id, 66 | users.name AS user_name, 67 | GROUP_CONCAT(computers.id SEPARATOR ';|;') AS computer_ids, 68 | GROUP_CONCAT(computers.name SEPARATOR ';|;') AS computer_names, 69 | locations.id AS location_id, 70 | locations.name AS location_name 71 | FROM 72 | glpi_users_softwarelicenses users_softwarelicenses 73 | JOIN glpi_softwarelicenses softwarelicenses ON users_softwarelicenses.softwarelicenses_id = softwarelicenses.id 74 | JOIN glpi_users users ON users_softwarelicenses.users_id = users.id 75 | LEFT JOIN glpi_computers computers ON users.id = computers.users_id 76 | LEFT JOIN glpi_locations locations ON computers.locations_id = locations.id 77 | LEFT JOIN glpi_softwarelicensetypes softwarelicensetypes ON softwarelicenses.softwarelicensetypes_id = softwarelicensetypes.id 78 | WHERE 79 | softwarelicenses.softwares_id = '$softwareId' 80 | GROUP BY user_id 81 | ORDER BY $sort $order 82 | LIMIT ".intval($start).",".intval($_SESSION['glpilist_limit']); 83 | } else { 84 | return "SELECT 85 | softwarelicenses.id AS license_id, 86 | softwarelicenses.name AS license_name, 87 | softwarelicenses.serial AS license_serial, 88 | softwarelicensetypes.name AS license_type, 89 | users.id AS user_id, 90 | users.name AS user_name, 91 | computers.id AS computer_id, 92 | computers.name AS computer_name, 93 | locations.id AS location_id, 94 | locations.name AS location_name 95 | FROM 96 | glpi_users_softwarelicenses users_softwarelicenses 97 | JOIN glpi_softwarelicenses softwarelicenses ON users_softwarelicenses.softwarelicenses_id = softwarelicenses.id 98 | JOIN glpi_users users ON users_softwarelicenses.users_id = users.id 99 | LEFT JOIN glpi_computers computers ON users.id = computers.users_id 100 | LEFT JOIN glpi_locations locations ON computers.locations_id = locations.id 101 | LEFT JOIN glpi_softwarelicensetypes softwarelicensetypes ON softwarelicenses.softwarelicensetypes_id = softwarelicensetypes.id 102 | WHERE 103 | softwarelicenses.softwares_id = '$softwareId' 104 | ORDER BY $sort $order 105 | LIMIT " . intval($start). "," . intval($_SESSION['glpilist_limit']); 106 | } 107 | } 108 | 109 | private static function countLicenses(Software $software) { 110 | global $DB; 111 | 112 | $softwareId = $software->getField("id"); 113 | $result = $DB->query(self::getCountQuery($softwareId)); 114 | $row = $DB->fetchAssoc($result); 115 | 116 | return $row ? $row['rows_number'] : 0; 117 | } 118 | 119 | private static function printTableBegin() { 120 | return "
"; 121 | } 122 | 123 | private static function getColumns() { 124 | return array( 125 | 'license_name' => __('License'), 126 | 'user_name' => __('User'), 127 | 'computer_name' => __('Computer'), 128 | 'location_name' => __('Location') 129 | ); 130 | } 131 | 132 | private static function printGridColumnsHeaders($sortingOrder, $sortingColumn) { 133 | global $CFG_GLPI; 134 | 135 | $sortingOrderIndicatorImage = ""; 137 | 138 | $htmlOutput = ""; 139 | 140 | foreach (self::getColumns() as $key => $value) { 141 | $htmlOutput .= 142 | ""; 148 | } 149 | 150 | return $htmlOutput; 151 | } 152 | 153 | private static function printTableEnd() { 154 | return "
" 143 | .(($sortingColumn == "`$key`") ?$sortingOrderIndicatorImage:"") 144 | ."$value" 147 | ."
"; 155 | } 156 | 157 | /** 158 | * Show table with linked licenses to user 159 | * @param Software $software 160 | * @return bool 161 | */ 162 | private static function showUsersLicenses(Software $software) { 163 | global $DB; 164 | 165 | $softwareId = $software->getField("id"); 166 | $totalRecordsCount = self::countLicenses($software); 167 | $currentPage = isset($_GET["start"]) ? $_GET["start"] : 0; 168 | $sortingOrder = SortingOrder::getFromString($_GET["order"]); 169 | $columnKeys = array_keys(self::getColumns()); 170 | $sortingColumn = array_key_exists($_GET["sort"], self::getColumns()) ? $_GET["sort"] : reset($columnKeys); 171 | $queryResult = $DB->query(self::getDataQuery($softwareId, $currentPage, $sortingColumn, $sortingOrder)); 172 | 173 | $options = PluginFpsoftwareConfig::getConfigValues(array('group_by_users')); 174 | 175 | Html::printAjaxPager(self::getTypeName(2), $currentPage, $totalRecordsCount); 176 | echo self::printTableBegin(); 177 | echo self::printGridColumnsHeaders($sortingOrder, $sortingColumn); 178 | 179 | if ($totalRecordsCount > 0) { 180 | while ($data = $DB->fetchAssoc($queryResult)) { 181 | echo ""; 182 | echo "".$data["license_name"]." - ".$data["license_serial"]." (".$data["license_type"].") ".""; 183 | echo "".$data["user_name"].""; 184 | if ($options['group_by_users']) { 185 | $computers = array(); 186 | if ($data['computer_ids']) { 187 | $computer_ids = explode(';|;', $data['computer_ids']); 188 | $computer_names = explode(';|;', $data['computer_names']); 189 | foreach ($computer_ids as $index => $computer_id) { 190 | $computers[] = " ".$computer_names[$index].""; 191 | } 192 | } 193 | echo ""; 194 | echo implode("

", $computers).""; 195 | } 196 | else { 197 | echo "".$data["computer_name"].""; 198 | } 199 | echo "".$data["location_name"].""; 200 | echo ""; 201 | } 202 | } else { 203 | echo "No results."; 204 | } 205 | 206 | Html::printAjaxPager(self::getTypeName(2), $currentPage, $totalRecordsCount); 207 | echo self::printTableEnd(); 208 | 209 | return true; 210 | } 211 | 212 | /** 213 | * @see CommonGLPI::getTabNameForItem() 214 | **/ 215 | public function getTabNameForItem(CommonGLPI $item, $withtemplate=0) { 216 | if ($withtemplate || !self::isSoftwareTabActive($item)) { 217 | return ''; 218 | } 219 | 220 | $recordsCount = $_SESSION['glpishow_count_on_tabs'] ? self::countLicenses($item) : 0; 221 | 222 | return self::createTabEntry(SoftwareLicense::getTypeName(2) . ' - ' . User::getTypeName(2), $recordsCount); 223 | } 224 | 225 | /** 226 | * DON'T KNOW IF $TABNUM IS USED ANYWHERE, IT SHOULD CHANGE DISPLAYING (MAKE 227 | * IT BY ENTITY), BUT THE METHOD IS NOT PREPARED. $WITHTEMPLATE IS NOT USED 228 | * EITHER. 229 | **/ 230 | public static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) { 231 | if (self::isSoftwareTabActive($item)) { 232 | self::showUsersLicenses($item); 233 | } 234 | 235 | return true; 236 | } 237 | 238 | /** 239 | * Returns the ids of user's licenses. 240 | * 241 | * @param int $user_id 242 | * 243 | * @return array 244 | */ 245 | public static function getUserLicenses(int $user_id): array 246 | { 247 | global $DB; 248 | 249 | $result = $DB->request( 250 | ['FROM' => 'glpi_users_softwarelicenses', 'WHERE' => ['users_id' => $user_id]] 251 | ); 252 | 253 | $user_licenses = []; 254 | foreach ($result as $data => $content) { 255 | $user_licenses[] = $content['softwarelicenses_id']; 256 | } 257 | 258 | return $user_licenses; 259 | } 260 | 261 | /** 262 | * Returns the ids of licenses unassigned to user. 263 | * 264 | * @param int $user_id 265 | * 266 | * @return array 267 | */ 268 | public static function getLicensesUnassignedToUser(int $user_id): array 269 | { 270 | global $DB; 271 | 272 | $user_licenses = self::getUserLicenses($user_id); 273 | if (empty($user_licenses)) { 274 | $result = $DB->request('glpi_softwarelicenses'); 275 | } else { 276 | $result = $DB->request( 277 | 'glpi_softwarelicenses', 278 | ['NOT' => ['id' => $user_licenses]] 279 | ); 280 | } 281 | 282 | $licenses = []; 283 | foreach ($result as $data => $content) { 284 | $licenses[] = $content['id']; 285 | } 286 | 287 | return $licenses; 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /inc/versionhelper.class.php: -------------------------------------------------------------------------------- 1 | $_SESSION['glpilist_limit'], 59 | 'container' => 'mass'.$class.$rand, 60 | 'specific_actions' 61 | => array($class.MassiveAction::CLASS_ACTION_SEPARATOR.'deleteSelected' 62 | => _x('button', 'Delete') 63 | ) 64 | ) 65 | ); 66 | } else { 67 | return array($higher_version, 68 | array( 69 | 'num_displayed' => $_SESSION['glpilist_limit'], 70 | 'specific_actions' => array('deleteSelected' => _x('button', 'Delete')) 71 | ) 72 | ); 73 | } 74 | 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /setup.php: -------------------------------------------------------------------------------- 1 | . 25 | 26 | ------------------------------------------------------------------------ 27 | 28 | @package FPFutures 29 | @author Future Processing 30 | @co-author 31 | @copyright Copyright (c) 2014 by Future Processing 32 | @license AGPL License 3.0 or (at your option) any later version 33 | http://www.gnu.org/licenses/agpl-3.0-standalone.html 34 | @since 2014 35 | 36 | ------------------------------------------------------------------------ 37 | */ 38 | 39 | /** 40 | * Definition of the plugin version and its compatibility with the version of core 41 | * 42 | * @return array 43 | */ 44 | function plugin_version_fpsoftware() 45 | { 46 | return array( 47 | 'name' => "FP Software", 48 | 'version' => '2.0.0', 49 | 'author' => 'Future Processing', 50 | 'license' => 'GPLv2+', 51 | 'homepage' => 'http://www.future-processing.com', 52 | 'minGlpiVersion' => '9.5' 53 | ); 54 | } 55 | 56 | /** 57 | * Control of the configuration 58 | * 59 | * @param boolean $verbose 60 | * @return boolean 61 | */ 62 | function plugin_fpsoftware_check_config($verbose = false) 63 | { 64 | return true; 65 | } 66 | 67 | /** 68 | * Initialization of the plugin 69 | * 70 | * @global array $PLUGIN_HOOKS 71 | */ 72 | function plugin_init_fpsoftware() 73 | { 74 | global $PLUGIN_HOOKS; 75 | 76 | $PLUGIN_HOOKS['csrf_compliant']['fpsoftware'] = true; 77 | 78 | $PLUGIN_HOOKS['config_page']['fpsoftware'] = 'front/config.form.php'; 79 | 80 | Plugin::registerClass('PluginFpsoftwareCommon', array('addtabon' => array('SoftwareLicense'))); 81 | Plugin::registerClass('PluginFpsoftwareUserdetails', array('addtabon' => array('User'))); 82 | Plugin::registerClass('PluginFpsoftwareUsersLicenses', array('addtabon' => array('Software'))); 83 | Plugin::registerClass('PluginFpsoftwareVersionhelper'); 84 | Plugin::registerClass('PluginFpsoftwareConfig'); 85 | Plugin::registerClass('PluginFpsoftwareLicenseHelper'); 86 | } 87 | --------------------------------------------------------------------------------