Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0834bf2
first commit
stonebuzz Nov 26, 2025
f767cf7
sanitizer
stonebuzz Nov 26, 2025
9d28d3e
rector
stonebuzz Nov 26, 2025
29de0b4
remove uselss var folder
stonebuzz Nov 26, 2025
097bae7
update gitignore
stonebuzz Nov 26, 2025
cdb67c0
cs fixer
stonebuzz Nov 26, 2025
48a22b0
use public/ folder
stonebuzz Nov 26, 2025
d0af817
remove includes
stonebuzz Nov 26, 2025
a83c963
global
stonebuzz Nov 26, 2025
290aee2
doQuery
stonebuzz Nov 26, 2025
92db61d
get_plugin_web_dir twig template
stonebuzz Nov 26, 2025
a2f8e30
CFG_GLPI.root_doc
stonebuzz Nov 26, 2025
89058b2
exit -> return
stonebuzz Nov 26, 2025
fb0a3b1
NotFoundException
stonebuzz Nov 26, 2025
46c0c17
fix twig cs
stonebuzz Nov 26, 2025
d7327d9
start phpstan fix
stonebuzz Nov 26, 2025
076718f
adapt changelog
stonebuzz Nov 26, 2025
12e0770
clean
stonebuzz Nov 26, 2025
2bfa0ee
remove useless specific CI (with glpi 10)
stonebuzz Nov 26, 2025
7d85290
fix header
stonebuzz Nov 26, 2025
982897a
fix CS
stonebuzz Nov 26, 2025
73672c5
fix phpunit
stonebuzz Nov 26, 2025
e7b880a
fix phpunit
stonebuzz Nov 26, 2025
96133cd
add missing use statement
stonebuzz Nov 26, 2025
1dbe723
psaml : add missing front folder
stonebuzz Nov 26, 2025
ced5889
phpstan
stonebuzz Nov 27, 2025
0ae8eff
fix CS
stonebuzz Nov 27, 2025
f03f0cc
fix
stonebuzz Nov 27, 2025
096f173
fix tab icon and url
stonebuzz Nov 27, 2025
7e36707
fix CS
stonebuzz Nov 27, 2025
2f0fdc2
start fix phpunit
stonebuzz Nov 27, 2025
4cc0c7a
fix phphunit
stonebuzz Nov 27, 2025
5266473
fix
stonebuzz Nov 27, 2025
b2c48fe
fix phpunit
stonebuzz Nov 27, 2025
5e31867
fix CS
stonebuzz Nov 27, 2025
cc9b3d4
fix
stonebuzz Nov 27, 2025
8dea044
update header
stonebuzz Nov 27, 2025
b2bc0f0
fix header
stonebuzz Nov 27, 2025
08308b5
eslint
Rom1-B Nov 28, 2025
ee469ea
fix
stonebuzz Nov 28, 2025
f3f2f78
fix visibility states condition
stonebuzz Nov 28, 2025
4509228
fix CS
stonebuzz Nov 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 0 additions & 27 deletions .github/workflows/ci.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
name: "Generate CI matrix"
uses: "glpi-project/plugin-ci-workflows/.github/workflows/generate-ci-matrix.yml@v1"
with:
glpi-version: "10.0.x"
glpi-version: "11.0.x"
ci:
name: "GLPI ${{ matrix.glpi-version }} - php:${{ matrix.php-version }} - ${{ matrix.db-image }}"
needs: "generate-ci-matrix"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
vendor
.phpunit.result.cache
var/
6 changes: 3 additions & 3 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
$config = new Config();

$rules = [
'@PER-CS2.0' => true,
'trailing_comma_in_multiline' => ['elements' => ['arguments', 'array_destructuring', 'arrays']], // For PHP 7.4 compatibility
'@PER-CS' => true, // Latest PER rules.
];

return $config
->setRules($rules)
->setFinder($finder)
->setUsingCache(false);
->setCacheFile(__DIR__ . '/var/php-cs-fixer/.php-cs-fixer.cache')
;
10 changes: 6 additions & 4 deletions .twig_cs.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

declare(strict_types=1);

use FriendsOfTwig\Twigcs;
use FriendsOfTwig\Twigcs\Finder\TemplateFinder;
use FriendsOfTwig\Twigcs\Config\Config;
use Glpi\Tools\GlpiTwigRuleset;

$finder = Twigcs\Finder\TemplateFinder::create()
$finder = TemplateFinder::create()
->in(__DIR__ . '/templates')
->name('*.html.twig')
->ignoreVCSIgnored(true);

return Twigcs\Config\Config::create()
return Config::create()
->setFinder($finder)
->setRuleSet(\Glpi\Tools\GlpiTwigRuleset::class)
->setRuleSet(GlpiTwigRuleset::class)
;
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [UNRELEASED]

- GLPI 11 compatibility

### Fixes

- SQL error when merging the Jamf device linked to a GLPI asset
Expand Down
5 changes: 0 additions & 5 deletions RoboFile.php

This file was deleted.

10 changes: 7 additions & 3 deletions ajax/cron.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,27 @@
* You should have received a copy of the GNU General Public License
* along with JAMF plugin for GLPI. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2024-2024 by Teclib'
* @copyright Copyright (C) 2024-2025 by Teclib'
* @copyright Copyright (C) 2019-2024 by Curtis Conard
* @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
* @link https://github.com/pluginsGLPI/jamf
* -------------------------------------------------------------------------
*/

include('../../../inc/includes.php');
use Glpi\Exception\Http\NotFoundHttpException;

use function Safe\file_get_contents;

$plugin = new Plugin();
if (!$plugin->isActivated('jamf')) {
Html::displayNotFoundError();
throw new NotFoundHttpException();
}

Html::header_nocache();

Session::checkLoginUser();

/** @var DBmysql $DB */
global $DB;

// Get AJAX input and load it into $_REQUEST
Expand All @@ -55,4 +58,5 @@
if (!in_array($_REQUEST['crontask'], $accepted_tasks)) {
throw new RuntimeException('Unacceptable cron task!');
}

CronTask::launch(-CronTask::MODE_EXTERNAL, 1, $_REQUEST['crontask']);
11 changes: 8 additions & 3 deletions ajax/getMDMCommandForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@
* You should have received a copy of the GNU General Public License
* along with JAMF plugin for GLPI. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2024-2024 by Teclib'
* @copyright Copyright (C) 2024-2025 by Teclib'
* @copyright Copyright (C) 2019-2024 by Curtis Conard
* @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
* @link https://github.com/pluginsGLPI/jamf
* -------------------------------------------------------------------------
*/

include('../../../inc/includes.php');
use Glpi\Exception\Http\NotFoundHttpException;

$plugin = new Plugin();
if (!$plugin->isActivated('jamf')) {
Html::displayNotFoundError();
throw new NotFoundHttpException();
}

Session::checkLoginUser();
Expand All @@ -45,12 +45,17 @@

if (isset($_GET['itemtype'], $_GET['items_id'])) {
$className = 'PluginJamf' . $_GET['itemtype'];
if (is_a($className, 'CommonDBTM', true) === false) {
throw new RuntimeException('Invalid itemtype!');
}

$device = new $className();
if (!$device->getFromDB($_GET['items_id'])) {
throw new RuntimeException('Invalid itemtype/items_id!');
}
} else {
$device = null;
}

$form = PluginJamfMDMCommand::getFormForCommand($_GET['command'], $device);
echo $form;
9 changes: 6 additions & 3 deletions ajax/import.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,27 @@
* You should have received a copy of the GNU General Public License
* along with JAMF plugin for GLPI. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2024-2024 by Teclib'
* @copyright Copyright (C) 2024-2025 by Teclib'
* @copyright Copyright (C) 2019-2024 by Curtis Conard
* @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
* @link https://github.com/pluginsGLPI/jamf
* -------------------------------------------------------------------------
*/

include('../../../inc/includes.php');
use Glpi\Exception\Http\NotFoundHttpException;

use function Safe\file_get_contents;

$plugin = new Plugin();
if (!$plugin->isActivated('jamf')) {
Html::displayNotFoundError();
throw new NotFoundHttpException();
}

Html::header_nocache();

Session::checkLoginUser();

/** @var DBmysql $DB */
global $DB;

// Get AJAX input and load it into $_REQUEST
Expand Down
31 changes: 22 additions & 9 deletions ajax/merge.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,27 @@
* You should have received a copy of the GNU General Public License
* along with JAMF plugin for GLPI. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2024-2024 by Teclib'
* @copyright Copyright (C) 2024-2025 by Teclib'
* @copyright Copyright (C) 2019-2024 by Curtis Conard
* @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
* @link https://github.com/pluginsGLPI/jamf
* -------------------------------------------------------------------------
*/

include('../../../inc/includes.php');
use Glpi\Exception\Http\NotFoundHttpException;

use function Safe\file_get_contents;

$plugin = new Plugin();
if (!$plugin->isActivated('jamf')) {
Html::displayNotFoundError();
throw new NotFoundHttpException();
}

Html::header_nocache();

Session::checkLoginUser();

/** @var DBmysql $DB */
global $DB;

// Get AJAX input and load it into $_REQUEST
Expand All @@ -50,6 +53,7 @@
if (!isset($_REQUEST['action'])) {
throw new RuntimeException('Required argument missing!');
}

if ($_REQUEST['action'] === 'merge') {
// Trigger extension attribute definition sync
PluginJamfMobileSync::syncExtensionAttributeDefinitions();
Expand All @@ -62,17 +66,19 @@
if (!isset($data['jamf_id'], $data['itemtype'])) {
continue;
}

$jamf_id = $data['jamf_id'];
$itemtype = $data['itemtype'];

if (($itemtype !== 'Computer') && ($itemtype !== 'Phone')) {
// Invalid itemtype for a mobile device
throw new RuntimeException('Invalid itemtype!');
}

$item = new $itemtype();
/** @var PluginJamfAbstractDevice $plugin_itemtype */
/** @var class-string<PluginJamfAbstractDevice> $plugin_itemtype */
$plugin_itemtype = 'PluginJamf' . $data['jamf_type'];
/** @var PluginJamfDeviceSync $plugin_sync_itemtype */
/** @var class-string<PluginJamfDeviceSync> $plugin_sync_itemtype */
$plugin_sync_itemtype = 'PluginJamf' . $data['jamf_type'] . 'Sync';
if ($data['jamf_type'] === 'MobileDevice') {
$plugin_sync_itemtype = 'PluginJamfMobileSync';
Expand Down Expand Up @@ -102,7 +108,7 @@
'supervised' => $jamf_item['supervised'] ?? $os_details['supervised'],
];
$ruleinput = $rules->processAllRules($ruleinput, $ruleinput, ['recursive' => true]);
$import = isset($ruleinput['_import']) ? $ruleinput['_import'] : 'NS';
$import = $ruleinput['_import'] ?? 'NS';

if (isset($ruleinput['_import']) && !$ruleinput['_import']) {
// Dropped by rules
Expand All @@ -120,9 +126,15 @@
'jamf_items_id' => $data['jamf_id'],
]);
if ($r === false) {
throw new \RuntimeException('Failed to import the device data!');
throw new RuntimeException('Failed to import the device data!');
}

// Link

if (is_a($plugin_itemtype, 'CommonDBTM', true) === false) {
throw new RuntimeException('Invalid plugin itemtype!');
}

$plugin_item = new $plugin_itemtype();
$plugin_items_id = $plugin_item->add([
'glpi_plugin_jamf_devices_id' => $DB->insertId(),
Expand Down Expand Up @@ -155,8 +167,9 @@
$DB->rollBack();
}
}
if ($failures) {
Session::addMessageAfterRedirect(sprintf(__('An error occurred while merging %d devices!', 'jamf'), $failures), false, ERROR);

if ($failures !== 0) {
Session::addMessageAfterRedirect(sprintf(__s('An error occurred while merging %d devices!', 'jamf'), $failures), false, ERROR);
}
} else {
throw new RuntimeException('Required argument missing!');
Expand Down
27 changes: 14 additions & 13 deletions ajax/sendMDMCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,19 @@
* You should have received a copy of the GNU General Public License
* along with JAMF plugin for GLPI. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2024-2024 by Teclib'
* @copyright Copyright (C) 2024-2025 by Teclib'
* @copyright Copyright (C) 2019-2024 by Curtis Conard
* @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
* @link https://github.com/pluginsGLPI/jamf
* -------------------------------------------------------------------------
*/

include('../../../inc/includes.php');
use Glpi\Exception\Http\BadRequestHttpException;
use Glpi\Exception\Http\NotFoundHttpException;

$plugin = new Plugin();
if (!$plugin->isActivated('jamf')) {
Html::displayNotFoundError();
throw new NotFoundHttpException();
}

Html::header_nocache();
Expand Down Expand Up @@ -61,19 +62,18 @@
$valid_types = ['MobileDevice'];

if (!in_array($_POST['itemtype'], $valid_types, true)) {
die('Invalid itemtype. Cannot send Jamf MDM command.');
throw new BadRequestHttpException();
}

$items = [];
if ($_POST['itemtype'] === 'MobileDevice') {
foreach ($_POST['items_id'] as $items_id) {
/** @var PluginJamfMobileDevice $item */
$item = new PluginJamfMobileDevice();
$item->getFromDB((int) $items_id);
$items[] = $item;
}
foreach ($_POST['items_id'] as $items_id) {
/** @var PluginJamfMobileDevice $item */
$item = new PluginJamfMobileDevice();
$item->getFromDB((int) $items_id);
$items[] = $item;
}


foreach ($items as $k => $item) {
$commands = PluginJamfItem_MDMCommand::getApplicableCommands($item);
$command_names = array_keys($commands);
Expand All @@ -83,9 +83,9 @@
}
}

if (!count($items)) {
if ($items === []) {
// No applicable items or no right to send command
exit();
return;
}

// The API endpoint for sending MDM commands only accepts XML, so we need to build the XML payload
Expand All @@ -101,4 +101,5 @@
$m = $mobile_devices->addChild('mobile_device');
$m->addChild('id', $jamf_id);
}

echo PluginJamfAPI::sendMDMCommand($payload->asXML(), true);
Loading