diff --git a/composer.json b/composer.json
index 9a93afd3..fe493728 100644
--- a/composer.json
+++ b/composer.json
@@ -23,6 +23,7 @@
"ext-zip": "*",
"ext-openssl": "*",
"ext-sockets": "*",
+ "ext-simplexml": "*",
"sskaje/mqtt": "dev-master",
"tufanbarisyildirim/php-apk-parser": "dev-master",
"docopt/docopt": "^1.0",
diff --git a/composer.lock b/composer.lock
index 11f113e7..8a820adf 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "2baf0654d04493588f65818469372e81",
+ "content-hash": "e0a20f6a1ff8c50ac2cac05de2016b16",
"packages": [
{
"name": "docopt/docopt",
@@ -739,16 +739,16 @@
},
{
"name": "consolidation/self-update",
- "version": "1.0.0",
+ "version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/consolidation/self-update.git",
- "reference": "adbb784e58cc0836d8522851f7e38ee7ade0d553"
+ "reference": "de33822f907e0beb0ffad24cf4b1b4fae5ada318"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/consolidation/self-update/zipball/adbb784e58cc0836d8522851f7e38ee7ade0d553",
- "reference": "adbb784e58cc0836d8522851f7e38ee7ade0d553",
+ "url": "https://api.github.com/repos/consolidation/self-update/zipball/de33822f907e0beb0ffad24cf4b1b4fae5ada318",
+ "reference": "de33822f907e0beb0ffad24cf4b1b4fae5ada318",
"shasum": ""
},
"require": {
@@ -756,6 +756,9 @@
"symfony/console": "^2.8|^3|^4",
"symfony/filesystem": "^2.5|^3|^4"
},
+ "bin": [
+ "scripts/release"
+ ],
"type": "library",
"extra": {
"branch-alias": {
@@ -772,13 +775,17 @@
"MIT"
],
"authors": [
+ {
+ "name": "Greg Anderson",
+ "email": "greg.1.anderson@greenknowe.org"
+ },
{
"name": "Alexander Menk",
"email": "menk@mestrona.net"
}
],
"description": "Provides a self:update command for Symfony Console applications.",
- "time": "2018-08-17T04:50:59+00:00"
+ "time": "2018-08-24T17:01:46+00:00"
},
{
"name": "container-interop/container-interop",
@@ -1600,7 +1607,7 @@
},
{
"name": "symfony/console",
- "version": "v3.4.14",
+ "version": "v3.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
@@ -1669,16 +1676,16 @@
},
{
"name": "symfony/debug",
- "version": "v3.4.14",
+ "version": "v3.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc"
+ "reference": "c4625e75341e4fb309ce0c049cbf7fb84b8897cd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/d5a058ff6ecad26b30c1ba452241306ea34c65cc",
- "reference": "d5a058ff6ecad26b30c1ba452241306ea34c65cc",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/c4625e75341e4fb309ce0c049cbf7fb84b8897cd",
+ "reference": "c4625e75341e4fb309ce0c049cbf7fb84b8897cd",
"shasum": ""
},
"require": {
@@ -1721,11 +1728,11 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2018-07-26T11:19:56+00:00"
+ "time": "2018-08-03T10:42:44+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v3.4.14",
+ "version": "v3.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@@ -1788,16 +1795,16 @@
},
{
"name": "symfony/filesystem",
- "version": "v3.4.14",
+ "version": "v3.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6"
+ "reference": "285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/a59f917e3c5d82332514cb4538387638f5bde2d6",
- "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c",
+ "reference": "285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c",
"shasum": ""
},
"require": {
@@ -1834,11 +1841,11 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2018-07-26T11:19:56+00:00"
+ "time": "2018-08-10T07:29:05+00:00"
},
{
"name": "symfony/finder",
- "version": "v3.4.14",
+ "version": "v3.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
@@ -1946,16 +1953,16 @@
},
{
"name": "symfony/process",
- "version": "v3.4.14",
+ "version": "v3.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f"
+ "reference": "4d6b125d5293cbceedc2aa10f2c71617e76262e7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/0414db29bd770ec5a4152683e655f55efd4fa60f",
- "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f",
+ "url": "https://api.github.com/repos/symfony/process/zipball/4d6b125d5293cbceedc2aa10f2c71617e76262e7",
+ "reference": "4d6b125d5293cbceedc2aa10f2c71617e76262e7",
"shasum": ""
},
"require": {
@@ -1991,20 +1998,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2018-07-26T11:19:56+00:00"
+ "time": "2018-08-03T10:42:44+00:00"
},
{
"name": "symfony/yaml",
- "version": "v3.4.14",
+ "version": "v3.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2"
+ "reference": "c2f4812ead9f847cb69e90917ca7502e6892d6b8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/810af2d35fc72b6cf5c01116806d2b65ccaaf2e2",
- "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/c2f4812ead9f847cb69e90917ca7502e6892d6b8",
+ "reference": "c2f4812ead9f847cb69e90917ca7502e6892d6b8",
"shasum": ""
},
"require": {
@@ -2050,7 +2057,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2018-07-26T11:19:56+00:00"
+ "time": "2018-08-10T07:34:36+00:00"
}
],
"aliases": [],
@@ -2066,7 +2073,8 @@
"ext-gd": "*",
"ext-zip": "*",
"ext-openssl": "*",
- "ext-sockets": "*"
+ "ext-sockets": "*",
+ "ext-simplexml": "*"
},
"platform-dev": {
"ext-bz2": "*"
diff --git a/front/fdroidapplication.form.php b/front/fdroidapplication.form.php
new file mode 100644
index 00000000..80c44f0b
--- /dev/null
+++ b/front/fdroidapplication.form.php
@@ -0,0 +1,81 @@
+isActivated('flyvemdm')) {
+ Html::displayNotFoundError();
+}
+
+Session::checkRight('flyvemdm:flyvemdm', PluginFlyvemdmProfile::RIGHT_FLYVEMDM_USE);
+
+if (!isset($_GET['id'])) {
+ $_GET['id'] = '';
+}
+
+if (!isset($_GET['withtemplate'])) {
+ $_GET['withtemplate'] = '';
+}
+
+$fdroidApplication = new PluginFlyvemdmFDroidApplication();
+if (isset($_POST['import'])) {
+ unset($_POST['_skip_checks']);
+ $fdroidApplication->update(['id' => $_POST['id'], 'import_status' => 'to_import']);
+ Html::back();
+} else if (isset($_POST['update'])) {
+ $fdroidApplication->check($_POST['id'], UPDATE);
+ $fdroidApplication->update(['id' => $_POST['id'], 'is_auto_upgradable' => $_POST['is_auto_upgradable']]);
+ Html::back();
+} else {
+ $fdroidApplication->check($_GET['id'], READ);
+ Html::header(
+ PluginFlyvemdmFDroidApplication::getTypeName(Session::getPluralNumber()),
+ '',
+ 'admin',
+ PluginFlyvemdmMenu::class,
+ 'fdroid application'
+ );
+
+ $menu = new PluginFlyvemdmMenu();
+ $menu->displayMenu('mini');
+
+ $fdroidApplication->display([
+ 'id' => $_GET['id'],
+ 'withtemplate' => $_GET['withtemplate']
+ ]);
+
+ // Footer
+ if (strstr($_SERVER['PHP_SELF'], 'popup')) {
+ Html::popFooter();
+ } else {
+ Html::footer();
+ }
+}
diff --git a/front/fdroidapplication.php b/front/fdroidapplication.php
new file mode 100644
index 00000000..8e972122
--- /dev/null
+++ b/front/fdroidapplication.php
@@ -0,0 +1,54 @@
+isActivated('flyvemdm')) {
+ Html::displayNotFoundError();
+}
+
+Session::checkRight("flyvemdm:flyvemdm", PluginFlyvemdmProfile::RIGHT_FLYVEMDM_USE);
+Session::checkRight("flyvemdm:fdroidapplication", READ);
+
+Html::header(
+ PluginFlyvemdmFDroidApplication::getTypeName(Session::getPluralNumber()),
+ '',
+ 'admin',
+ PluginFlyvemdmMenu::class,
+ 'fdroid application'
+);
+
+$menu = new PluginFlyvemdmMenu();
+$menu->displayMenu('mini');
+
+Search::show(PluginFlyvemdmFDroidApplication::class);
+
+Html::footer();
diff --git a/front/fdroidmarket.form.php b/front/fdroidmarket.form.php
new file mode 100644
index 00000000..b101694d
--- /dev/null
+++ b/front/fdroidmarket.form.php
@@ -0,0 +1,100 @@
+isActivated('flyvemdm')) {
+ Html::displayNotFoundError();
+}
+
+Session::checkRight('flyvemdm:flyvemdm', PluginFlyvemdmProfile::RIGHT_FLYVEMDM_USE);
+
+if (!isset($_GET['id'])) {
+ $_GET['id'] = '';
+}
+
+if (!isset($_GET['withtemplate'])) {
+ $_GET['withtemplate'] = '';
+}
+
+$market = new PluginFlyvemdmFDroidMarket();
+if (isset($_POST["add"])) {
+ $market->check(-1, CREATE, $_POST);
+ if ($newID = $market->add($_POST)) {
+ if ($_SESSION['glpibackcreated']) {
+ Html::redirect($market->getFormURL() . "?id=" . $newID);
+ }
+ }
+ Html::back();
+} else if (isset($_POST["update"])) {
+ $market->check($_POST['id'], UPDATE);
+ $market->update($_POST);
+ Html::back();
+} else if (isset($_POST["purge"])) {
+ $market->check($_POST['id'], PURGE);
+ $market->delete($_POST, 1);
+ $market->redirectToList();
+} else if (isset($_POST['refresh'])) {
+ $fdroidMarket = new PluginFlyvemdmFDroidMarket();
+ $fdroidMarket->getFromDB((int) $_POST['id']);
+ $volume = $fdroidMarket->updateRepository();
+ Html::back();
+} else {
+ if (isset($_GET['search'])) {
+ $criterias = array_intersect_key($_GET, ['criteria' => null, 'metacriteria' => null]);
+ $_SESSION['glpisearch'][PluginFlyvemdmFDroidApplication::class] = $criterias;
+ } else if (isset($_GET['reset'])) {
+ unset($_SESSION['glpisearch'][PluginFlyvemdmFDroidApplication::class]);
+ }
+ $market->check($_GET['id'], READ);
+ Html::header(
+ PluginFlyvemdmFDroidApplication::getTypeName(Session::getPluralNumber()),
+ '',
+ 'admin',
+ PluginFlyvemdmMenu::class,
+ 'fdroid market'
+ );
+
+ $menu = new PluginFlyvemdmMenu();
+ $menu->displayMenu('mini');
+
+ $market->display([
+ 'id' => $_GET['id'],
+ 'withtemplate' => $_GET['withtemplate']
+ ]);
+
+ // Footer
+ if (strstr($_SERVER['PHP_SELF'], 'popup')) {
+ Html::popFooter();
+ } else {
+ Html::footer();
+ }
+}
diff --git a/front/fdroidmarket.php b/front/fdroidmarket.php
new file mode 100644
index 00000000..13435763
--- /dev/null
+++ b/front/fdroidmarket.php
@@ -0,0 +1,54 @@
+isActivated('flyvemdm')) {
+ Html::displayNotFoundError();
+}
+
+Session::checkRight('flyvemdm:flyvemdm', PluginFlyvemdmProfile::RIGHT_FLYVEMDM_USE);
+Session::checkRight('flyvemdm:fdroidmarket', READ);
+
+Html::header(
+ PluginFlyvemdmFDroidMarket::getTypeName(Session::getPluralNumber()),
+ '',
+ 'admin',
+ PluginFlyvemdmMenu::class,
+ 'fdroid market');
+
+$menu = new PluginFlyvemdmMenu();
+$menu->displayMenu('mini');
+
+Search::show(PluginFlyvemdmFDroidMarket::class);
+
+Html::footer();
+
diff --git a/hook.php b/hook.php
index 06c8507a..4cc1a200 100644
--- a/hook.php
+++ b/hook.php
@@ -139,6 +139,9 @@ function plugin_Flyvemdm_addDefaultJoin($itemtype, $ref_table, $already_link_tab
case PluginFlyvemdmAgent::class:
return PluginFlyvemdmAgent::addDefaultJoin($ref_table, $already_link_tables);
+
+ case PluginFlyvemdmFDroidApplication::class:
+ return PluginFlyvemdmFDroidApplication::addDefaultJoin($ref_table, $already_link_tables);
}
}
@@ -154,8 +157,10 @@ function plugin_Flyvemdm_addDefaultWhere($itemtype) {
case PluginFlyvemdmAgent::class:
return PluginFlyvemdmAgent::addDefaultWhere();
- }
+ case PluginFlyvemdmFDroidApplication::class:
+ return PluginFlyvemdmFDroidApplication::addDefaultWhere();
+ }
}
/**
diff --git a/inc/agent.class.php b/inc/agent.class.php
index 9938523c..f6421a41 100644
--- a/inc/agent.class.php
+++ b/inc/agent.class.php
@@ -54,21 +54,12 @@ class PluginFlyvemdmAgent extends CommonDBTM implements PluginFlyvemdmNotifiable
*/
public static $rightname = 'flyvemdm:agent';
- /**
- * @var bool $dohistory maintain history
- */
+ /** @var bool $dohistory maintain history */
public $dohistory = true;
- /**
- * @var bool $usenotepad enable notepad for the itemtype (GLPi < 0.85)
- */
+ /** @var bool $usenotepad enable notepad for the itemtype */
protected $usenotepad = true;
- /**
- * @var bool $usenotepad enable notepad for the itemtype (GLPi >=0.85)
- */
- protected $usenotepadRights = true;
-
protected $topic = null;
/**
diff --git a/inc/entityconfig.class.php b/inc/entityconfig.class.php
index 07139e10..a4adc339 100644
--- a/inc/entityconfig.class.php
+++ b/inc/entityconfig.class.php
@@ -86,6 +86,17 @@ static function canUpdate() {
}
}
+ function getRights($interface = 'central') {
+ $values = [
+ READ => __('Read'),
+ self::RIGHT_FLYVEMDM_DEVICE_COUNT_LIMIT => __('Write device limit'),
+ self::RIGHT_FLYVEMDM_APP_DOWNLOAD_URL => __('Set agent download URL'),
+ self::RIGHT_FLYVEMDM_INVITATION_TOKEN_LIFE => __('Set invitation tiken lifetime'),
+ ];
+
+ return $values;
+ }
+
/**
* Actions done after the getFromDB method
*/
diff --git a/inc/fdroidapplication.class.php b/inc/fdroidapplication.class.php
new file mode 100644
index 00000000..a8f8448b
--- /dev/null
+++ b/inc/fdroidapplication.class.php
@@ -0,0 +1,448 @@
+ __('No import', 'flyvemdm'),
+ 'to_import' => __('To import', 'flyvemdm'),
+ 'imported' => __('Imported', 'flyvemdm'),
+ ];
+ }
+
+ /**
+ * Return the picture file for the menu
+ * @return string
+ */
+ public static function getMenuPicture() {
+ return '';
+ }
+
+ /**
+ * Returns the name of the type
+ * @param integer $count
+ * @return string
+ */
+ static function getTypeName($count = 0) {
+ return _n('F-Droid application', 'F-Droid applications', $count);
+ }
+
+ /**
+ * Define tabs available for this itemtype
+ */
+ public function defineTabs($options = []) {
+ $tab = [];
+ $this->addDefaultFormTab($tab);
+ $this->addStandardTab(Notepad::class, $tab, $options);
+ $this->addStandardTab(Log::class, $tab, $options);
+
+ return $tab;
+ }
+
+ /**
+ * @see CommonGLPI::getTabNameForItem()
+ *
+ * @since version 9.1
+ * @param CommonGLPI $item
+ * @param integer $withtemplate
+ * @return array|string
+ */
+ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
+ if (static::canView()) {
+ switch ($item->getType()) {
+ case PluginFlyvemdmFDroidMarket::class:
+ if (!$withtemplate) {
+ $nb = 0;
+ $fleetId = $item->getID();
+ $pluralNumber = Session::getPluralNumber();
+ if ($_SESSION['glpishow_count_on_tabs']) {
+ $DbUtil = new DbUtils();
+ $nb = $DbUtil->countElementsInTable(static::getTable(), ['plugin_flyvemdm_fdroidmarkets_id' => $fleetId]);
+ }
+ return self::createTabEntry(self::getTypeName($pluralNumber), $nb);
+ }
+ break;
+ }
+ }
+
+ return '';
+ }
+
+ static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
+ switch (get_class($item)) {
+ case PluginFlyvemdmFDroidMarket::class:
+ self::showForFDroidMarket($item);
+ return true;
+ break;
+ }
+
+ return false;
+ }
+
+ public function getAdditionalLinks() {
+ return [];
+ }
+
+ function getRights($interface = 'central') {
+ $values = [
+ READ => __('Read'),
+ UPDATE => __('Update'),
+ ];
+
+ return $values;
+ }
+
+ /**
+ * get Cron description parameter for this class
+ * @param $name string name of the task
+ * @return array of string
+ */
+ static function cronInfo($name) {
+ switch ($name) {
+ case 'DownloadApplications' :
+ return ['description' => __('download applications from the market')];
+ }
+ }
+
+ /**
+ * downloads all applications marked to import
+ * This algorithm is limited and cannot handle a huge quantity of applications
+ * @param CronTask $cronTask
+ * @return number
+ */
+ public static function cronDownloadApplications(CronTask $cronTask) {
+ global $DB;
+
+ $cronStatus = 0;
+
+ $cronTask->log('Download applications to import from F-Droid');
+
+ $request = [
+ 'FROM' => PluginFlyvemdmFDroidApplication::getTable(),
+ 'WHERE' => ['import_status' => 'to_import']
+ ];
+ $market = new PluginFlyvemdmFDroidMarket();
+ foreach ($DB->request($request) as $row) {
+ $fDroidApplication = new PluginFlyvemdmFDroidApplication();
+ $fDroidApplication->getFromDB($row['id']);
+ $fDroidApplication->downloadApplication();
+ $cronStatus = 1;
+ }
+
+ return $cronStatus;
+ }
+
+ /**
+ * Downloads an application and create a PluginFlyvemdmPackage in the database
+ * @return boolean true if success
+ */
+ public function downloadApplication() {
+ $package = new PluginFlyvemdmPackage();
+ $market = new PluginFlyvemdmFDroidMarket();
+ $market->getFromDB($this->fields[PluginFlyvemdmFDroidMarket::getForeignKeyField()]);
+ $baseUrl = dirname($market->fields['url']);
+
+ $file = GLPI_TMP_DIR . "/" . $this->fields['filename'];
+ file_put_contents($file, file_get_contents("$baseUrl/" . $this->fields['filename']));
+ $_POST['_file'][0] = $this->fields['filename'];
+ $_POST['_prefix_file'][0] = '';
+ $input = [
+ 'name' => $this->fields['name'],
+ 'package_name' => $this->fields['package_name'],
+ 'entities_id' => $this->fields['entities_id'],
+ 'alias' => $this->fields['alias'],
+ 'version' => $this->fields['version'],
+ 'version_code' => $this->fields['version_code'],
+ 'dl_filename' => $file,
+ ];
+ if ($package->getFromDBByCrit(['name' => $this->fields['name']])) {
+ $input['id'] = $package->getID();
+ if (!$package->update($input)) {
+ Toolbox::logInFile('php-errors', 'Failed to update an application from a F-Droid like market');
+ return false;
+ }
+ } else {
+ if (!$package->add($input)) {
+ Toolbox::logInFile('php-errors', 'Failed to import an application from a F-Droid like market');
+ return false;
+ }
+ }
+ unset($_POST['_file'][0]);
+ unset($_POST['_prefix_file'][0]);
+ $packageFk = PluginFlyvemdmPackage::getForeignKeyField();
+ $this->update([
+ 'id' => $this->fields['id'],
+ 'import_status' => 'imported',
+ $packageFk => $package->getID(),
+ ]);
+ return true;
+ }
+
+ /**
+ * Imports an application in the database or updates an existing one
+ * @param array $input
+ * @return integer|false ID of the imported item or false on error
+ */
+ public static function import($input) {
+ $marketFk = PluginFlyvemdmFDroidMarket::getForeignKeyField();
+ if (!isset($input['name']) || !isset($input[$marketFk])) {
+ return false;
+ }
+
+ $application = new self();
+ $application->getFromDBByCrit([
+ 'name' => $input['name'],
+ $marketFk => $input[$marketFk],
+ ]);
+ if ($application->isNewItem()) {
+ return $application->add($input);
+ }
+
+ $input['id'] = $application->getID();
+ $input['is_available'] = '1';
+ if ($application->update($input) === false) {
+ return false;
+ }
+ return $application->getID();
+ }
+
+ public function prepareInputForUpdate($input) {
+ if (isset($input['_skip_checks'])) {
+ return $input;
+ }
+
+ return $input;
+ }
+
+ public function showForm($ID, $options = []) {
+ $options['canUpdate'] = (!$this->isNewID($ID)) && ($this->canUpdate() > 0);
+ $this->initForm($ID, $options);
+ $this->showFormHeader($options);
+ $canedit = static::canUpdate();
+ $fields = $this->fields;
+
+ $importStatuses = static::getEnumImportStatus();
+ $fields['import_status'] = $importStatuses[$fields['import_status']];
+ $fields['is_auto_upgradable'] = Html::getCheckbox([
+ 'title' => __('Download the application updates', 'flyvemdm'),
+ 'name' => 'is_auto_upgradable',
+ 'checked' => $fields['is_auto_upgradable'] !== '0',
+ 'readonly' => ($canedit == '0' ? '1' : '0'),
+ ]);
+
+ $data = [
+ 'withTemplate' => (isset($options['withtemplate']) && $options['withtemplate'] ? '*' : ''),
+ 'isNewID' => $this->isNewID($ID),
+ 'canUpdate' => $options['canUpdate'],
+ 'fdroidapplication' => $fields,
+ ];
+
+ $twig = plugin_flyvemdm_getTemplateEngine();
+ echo $twig->render('fdroidapplication.html.twig', $data);
+
+ if (PluginFlyvemdmPackage::canCreate()) {
+ $options['addbuttons'] = [
+ 'import' => __('Import the package', 'flyvemdm'),
+ ];
+ }
+ $this->showFormButtons($options);
+ }
+
+ public static function showForFDroidMarket(CommonDBTM $item, $withtemplate = '') {
+ global $CFG_GLPI, $DB;
+
+ if (!$item->canView()) {
+ return false;
+ }
+
+ $searchParams = [];
+ if (isset($_SESSION['glpisearch'][PluginFlyvemdmFDroidApplication::class])) {
+ $searchParams = $_SESSION['glpisearch'][PluginFlyvemdmFDroidApplication::class];
+ }
+ $searchParams = Search::manageParams(PluginFlyvemdmApplication::class, $searchParams);
+ $searchParams['showbookmark'] = false;
+ $searchParams['target'] = PluginFlyvemdmFDroidMarket::getFormUrlWithID($item->getID());
+ $searchParams['addhidden'] = [
+ 'id' => $item->getID(),
+ PluginFlyvemdmFDroidMarket::getForeignKeyField() => $item->getID(),
+ ];
+ Search::showGenericSearch(PluginFlyvemdmFDroidApplication::class, $searchParams);
+
+ Search::showList(PluginFlyvemdmFDroidApplication::class, $searchParams);
+ }
+
+ public function post_updateItem($history = 1) {
+ if ($this->fields['import_status'] == 'imported'
+ && isset($this->oldvalues['version_code'])
+ && $this->oldvalues['version_code'] < $this->fields['version_code']
+ ) {
+ // The application was updated
+ $this->fields['version_code']++;
+ if ($this->fields['is_auto_upgradable']) {
+ $this->downloadApplication();
+ }
+ }
+ }
+
+ public function getSearchOptionsNew() {
+ return $this->rawSearchOptions();
+ }
+
+ public function rawSearchOptions() {
+ if (method_exists('CommonDBTM', 'rawSearchOptions')) {
+ $tab = parent::rawSearchOptions();
+ } else {
+ $tab = parent::getSearchOptionsNew();
+ }
+
+ $tab[] = [
+ 'id' => '2',
+ 'table' => self::getTable(),
+ 'field' => 'id',
+ 'name' => __('ID'),
+ 'massiveaction' => false,
+ 'datatype' => 'number'
+ ];
+
+ $tab[] = [
+ 'id' => '3',
+ 'table' => self::getTable(),
+ 'field' => 'alias',
+ 'name' => __('Alias', 'flyvemdm'),
+ 'massiveaction' => false,
+ 'datatype' => 'string'
+ ];
+
+ $tab[] = [
+ 'id' => '4',
+ 'table' => self::getTable(),
+ 'field' => 'version',
+ 'name' => __('Version', 'flyvemdm'),
+ 'massiveaction' => false,
+ 'datatype' => 'string'
+ ];
+
+ $tab[] = [
+ 'id' => '6',
+ 'table' => self::getTable(),
+ 'field' => 'filesize',
+ 'name' => __('Size'),
+ 'massiveaction' => false,
+ 'datatype' => 'number'
+ ];
+
+ $tab[] = [
+ 'id' => '7',
+ 'table' => self::getTable(),
+ 'field' => 'import_status',
+ 'name' => __('Import status', 'flyvemdm'),
+ 'searchtype' => ['equals', 'notequals'],
+ 'massiveaction' => false,
+ 'datatype' => 'specific'
+ ];
+
+ $tab[] = [
+ 'id' => '8',
+ 'table' => self::getTable(),
+ 'field' => PluginFlyvemdmFDroidMarket::getForeignKeyField(),
+ 'name' => __('FDroid market', 'flyvemdm'),
+ 'massiveaction' => false,
+ ];
+
+ $tab[] = [
+ 'id' => '9',
+ 'table' => self::getTable(),
+ 'field' => 'is_auto_upgradable',
+ 'name' => __('Download the application updates', 'flyvemdm'),
+ 'massiveaction' => false,
+ ];
+
+ return $tab;
+ }
+
+ public static function addDefaultJoin($ref_table, $already_link_tables) {
+ $join = '';
+
+ $table = PluginFlyvemdmFDroidMarket::getTable();
+ $fkTable = PluginFlyvemdmFDroidMarket::getForeignKeyField();
+ $join = "LEFT JOIN `$table` ON `$table`.`id`=`$ref_table`.`$fkTable` ";
+
+ return $join;
+ }
+
+ public static function addDefaultWhere() {
+ $where = '';
+
+ $fkFDroidMarket = PluginFlyvemdmFDroidMarket::getForeignKeyField();
+ if (isset($_GET['id'])) {
+ $fDfroidMarketId = (int) $_GET['id'];
+ $where = " `$fkFDroidMarket` = '$fDfroidMarketId'";
+ }
+ return $where;
+ }
+
+ public static function getSpecificValueToSelect($field, $name = '', $values = '', array $options = []) {
+ if (!is_array($values)) {
+ $values = [$field => $values];
+ }
+ switch ($field) {
+ case 'import_status':
+ $elements = self::getEnumImportStatus();
+ $output = Dropdown::showFromArray(
+ $name,
+ $elements,
+ [
+ 'display' => false,
+ 'value' => $values[$field]
+ ]
+ );
+ return $output;
+ break;
+ }
+ return parent::getSpecificValueToSelect($field, $name, $values, $options);
+ }
+}
diff --git a/inc/fdroidmarket.class.php b/inc/fdroidmarket.class.php
new file mode 100644
index 00000000..f5fa0631
--- /dev/null
+++ b/inc/fdroidmarket.class.php
@@ -0,0 +1,232 @@
+addDefaultFormTab($tab);
+ if (!$this->isNewItem()) {
+ $this->addStandardTab(PluginFlyvemdmFDroidApplication::class, $tab, $options);
+ }
+ $this->addStandardTab(Notepad::class, $tab, $options);
+ $this->addStandardTab(Log::class, $tab, $options);
+
+ return $tab;
+ }
+
+ /**
+ * get Cron description parameter for this class
+ * @param $name string name of the task
+ * @return array of string
+ */
+ static function cronInfo($name) {
+ switch ($name) {
+ case 'UpdateRepositories' :
+ return ['description' => __('Updates the list of applications')];
+ }
+ }
+
+ /**
+ * Maitnains a local list of all apps available in the repository
+ * This algorithm is limited and cannot handle a huge quantity of applications
+ * @param CronTask $cronTask
+ * @return integer
+ */
+ public static function cronUpdateRepositories(CronTask $cronTask) {
+ global $DB;
+
+ $cronStatus = 0;
+ $cronTask->log('Update the list of applications available from F-Droid like repositories');
+
+ $request = [
+ 'FROM' => static::getTable(),
+ ];
+ foreach ($DB->request($request) as $row) {
+ $fdroidMarket = new static();
+ $fdroidMarket->getFromResultSet($row);
+ $volume = $fdroidMarket->updateRepository();
+ $cronTask->addVolume($volume);
+ $cronStatus = 1;
+ }
+
+ return $cronStatus;
+ }
+
+ /**
+ * Updates the list of applications from a F Droid like repository
+ * @return integer
+ */
+ public function updateRepository() {
+ global $DB;
+
+ $volume = 0;
+ if (!isset($this->fields['url']) || strlen($this->fields['url']) === 0) {
+ return 0;
+ }
+ $xml = file_get_contents($this->fields['url']);
+ $fdroid = simplexml_load_string($xml);
+ unset($xml);
+
+ $marketFk = $this::getForeignKeyField();
+ $DB->query("UPDATE `" . PluginFlyvemdmFDroidApplication::getTable() . "` SET `is_available` = '0' WHERE `$marketFk`=" . $this->getID());
+ if (isset($fdroid->application)) {
+ foreach ($fdroid->application as $application) {
+ $input = [
+ 'name' => Toolbox::addslashes_deep($application->name),
+ 'package_name' => Toolbox::addslashes_deep($application->id),
+ 'entities_id' => $this->fields['entities_id'],
+ 'is_recursive' => $this->fields['is_recursive'],
+ $marketFk => $this->getID(),
+ 'alias' => Toolbox::addslashes_deep($application->name),
+ 'desc' => Toolbox::addslashes_deep($application->desc),
+ ];
+
+ // Find the latest published version
+ $highestVersionCode = (string) $application->marketvercode;
+ $selectedPackage = null;
+ foreach ($application->package as $key => $package) {
+ if ((string) $package->versioncode == $highestVersionCode) {
+ $selectedPackage = $package;
+ break;
+ }
+ }
+ if ($selectedPackage !== null) {
+ $input['version'] = Toolbox::addslashes_deep((string) $selectedPackage->version);
+ $input['version_code'] = Toolbox::addslashes_deep((string) $selectedPackage->versioncode);
+ $input['filesize'] = Toolbox::addslashes_deep((string) $selectedPackage->size);
+ $input['filename'] = Toolbox::addslashes_deep((string) $selectedPackage->apkname);
+ PluginFlyvemdmFDroidApplication::import($input);
+ }
+ }
+
+ }
+ // Delete applications vanished from the repo
+ $criteria = [$marketFk => $this->getID(), 'is_available' => '0'];
+ $dbUtils = new DbUtils();
+ $deleteCount = $dbUtils->countElementsInTable(PluginFlyvemdmFDroidApplication::getTable(), $criteria);
+ $fdroidApplication = new PluginFlyvemdmFDroidApplication();
+ $fdroidApplication->deleteByCriteria($criteria);
+ $volume = count($fdroid->application) + $deleteCount;
+
+ return $volume;
+ }
+
+ public function showForm($ID, $options = []) {
+ $this->initForm($ID, $options);
+ $this->showFormHeader($options);
+ $canedit = static::canUpdate();
+ $fields = $this->fields;
+
+ $data = [
+ 'withTemplate' => (isset($options['withtemplate']) && $options['withtemplate'] ? '*' : ''),
+ 'isNewID' => $this->isNewID($ID),
+ 'fdroidmarket' => $fields,
+ 'importButton' => Html::submit(_x('button', 'Import'), ['name' => 'import']),
+ 'canImport' => PluginFlyvemdmPackage::canCreate(),
+ ];
+
+ $twig = plugin_flyvemdm_getTemplateEngine();
+ echo $twig->render('fdroidmarket.html.twig', $data);
+
+ if (!$this->isNewID($ID)) {
+ $options['addbuttons'] = [
+ 'refresh' => _x('button', 'Import'),
+ ];
+ }
+ $this->showFormButtons($options);
+ }
+
+ public function getSearchOptionsNew() {
+ return $this->rawSearchOptions();
+ }
+
+ public function rawSearchOptions() {
+ if (method_exists('CommonDBTM', 'rawSearchOptions')) {
+ $tab = parent::rawSearchOptions();
+ } else {
+ $tab = parent::getSearchOptionsNew();
+ }
+
+ $tab[] = [
+ 'id' => '2',
+ 'table' => $this->getTable(),
+ 'field' => 'id',
+ 'name' => __('ID'),
+ 'massiveaction' => false,
+ 'datatype' => 'number'
+ ];
+
+ $tab[] = [
+ 'id' => '3',
+ 'table' => self::getTable(),
+ 'field' => 'url',
+ 'name' => __('URL', 'flyvemdm'),
+ 'datatype' => 'string'
+ ];
+
+ return $tab;
+ }
+}
diff --git a/inc/file.class.php b/inc/file.class.php
index 87476d03..e8aa03c5 100644
--- a/inc/file.class.php
+++ b/inc/file.class.php
@@ -70,6 +70,10 @@ public static function getMenuPicture() {
return 'fa-file';
}
+ public function getAdditionalLinks() {
+ return [];
+ }
+
public function addNeededInfoToInput($input) {
$input['entities_id'] = $_SESSION['glpiactive_entity'];
@@ -251,9 +255,6 @@ public function pre_deleteItem() {
]);
}
- /**
- * Actions done after the getFromFB method
- */
public function post_getFromDB() {
// Check the user can view this itemtype and can view this item
if (!$this->canView() || !$this->canViewItem()) {
@@ -303,7 +304,6 @@ public function showForm($ID, array $options = []) {
$this->initForm($ID, $options);
$this->showFormHeader($options);
- $twig = plugin_flyvemdm_getTemplateEngine();
$fields = $this->fields;
$fields['filesize'] = '';
if (!$this->isNewID($ID)) {
@@ -318,6 +318,7 @@ public function showForm($ID, array $options = []) {
'upload' => Html::file(['name' => 'file', 'display' => false]),
'comment' => $fields['comment'],
];
+ $twig = plugin_flyvemdm_getTemplateEngine();
echo $twig->render('file.html.twig', $data);
$this->showFormButtons($options);
diff --git a/inc/fleet.class.php b/inc/fleet.class.php
index 23ca940c..94f005ba 100644
--- a/inc/fleet.class.php
+++ b/inc/fleet.class.php
@@ -84,6 +84,10 @@ public static function getMenuPicture() {
return 'fa-group';
}
+ public function getAdditionalLinks() {
+ return [];
+ }
+
/**
* @see CommonGLPI::defineTabs()
*/
@@ -123,7 +127,6 @@ public function showForm($ID, array $options = []) {
$this->initForm($ID, $options);
$this->showFormHeader($options);
- $twig = plugin_flyvemdm_getTemplateEngine();
$fields = $this->fields;
$objectName = $DbUtil->autoName($this->fields["name"], "name",
(isset($options['withtemplate']) && $options['withtemplate'] == 2),
@@ -132,10 +135,12 @@ public function showForm($ID, array $options = []) {
['value' => $objectName, 'display' => false]);
$fields['is_default'] = $fields['is_default'] ? __('No') : __('Yes');
$data = [
- 'withTemplate' => (isset($options['withtemplate']) && $options['withtemplate'] ? "*" : ""),
- 'fleet' => $fields,
+ 'withTemplate' => (isset($options['withtemplate']) && $options['withtemplate'] ? "*" : ""),
+ 'isNewID' => $this->isNewID($ID),
+ 'fleet' => $fields,
];
+ $twig = plugin_flyvemdm_getTemplateEngine();
echo $twig->render('fleet.html.twig', $data);
$this->showFormButtons($options);
diff --git a/inc/menu.class.php b/inc/menu.class.php
index 2c8095e8..f3474e5c 100644
--- a/inc/menu.class.php
+++ b/inc/menu.class.php
@@ -112,6 +112,12 @@ public function displayMenu($type = 'dashboard') {
'pic' => PluginFlyvemdmFile::getMenuPicture(),
],
],
+ __('Markets', 'flyvemdm') => [
+ PluginFlyvemdmFDroidMarket::getTypeName($pluralNumber) => [
+ 'link' => Toolbox::getItemTypeSearchURL(PluginFlyvemdmFDroidMarket::class),
+ 'pic' => PluginFlyvemdmFDroidMarket::getMenuPicture(),
+ ],
+ ],
__('Configuration', 'flyvemdm') => [
__('General') => [
'link' => Toolbox::getItemTypeFormURL(PluginFlyvemdmConfig::class) . '?forcetab='.PluginFlyvemdmConfig::class.'$2',
@@ -134,17 +140,20 @@ public function displayMenu($type = 'dashboard') {
*/
public static function getMenuContent() {
$front_flyvemdm = "/plugins/flyvemdm/front";
+ $pics_flyvemdm = "/plugins/flyvemdm/pics";
$menu = [];
$menu['title'] = self::getMenuName();
$menu['page'] = "$front_flyvemdm/menu.php";
$itemtypes = [
- PluginFlyvemdmAgent::class => 'agent',
- PluginFlyvemdmPackage::class => 'package',
- PluginFlyvemdmFile::class => 'file',
- PluginFlyvemdmFleet::class => 'fleet',
- PluginFlyvemdmInvitation::class => 'invitation',
+ PluginFlyvemdmAgent::class => 'agent',
+ PluginFlyvemdmPackage::class => 'package',
+ PluginFlyvemdmFile::class => 'file',
+ PluginFlyvemdmFleet::class => 'fleet',
+ PluginFlyvemdmInvitation::class => 'invitation',
+ PluginFlyvemdmFDroidMarket::class => 'fdroid market',
+ PluginFlyvemdmFDroidApplication::class => 'fdroid application',
];
$pluralNumber = Session::getPluralNumber();
@@ -155,6 +164,17 @@ public static function getMenuContent() {
if ($itemtype::canCreate()) {
$menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false);
}
+
+ // MenuInterface not yet used
+ // Issue: cannot use font awesome because GLPI escapes the picture
+ // if the picture string does not starts with " App inspired by this
+ reddit post
+ Pulls the curated app list from the
+ /r/Android wiki and displays it.
+ As it offers non free apps as well, this app has the non free addon antifeature. App inspired by this
+ reddit post
+ Pulls the curated app list from the
+ /r/Android wiki and displays it.
+ As it offers non free apps as well, this app has the non free addon antifeature.getAdditionalLinks();
+ foreach ($links as $link) {
+ $image = $link['pic'];
+ $menu['options'][$option]['links'][$image] = $link['link'];
+ }
+ }
}
return $menu;
}
diff --git a/inc/menuinterface.class.php b/inc/menuinterface.class.php
new file mode 100644
index 00000000..17d403bd
--- /dev/null
+++ b/inc/menuinterface.class.php
@@ -0,0 +1,41 @@
+publish_sync($topic, $message, $qos, $retain)) {
$log->saveOutgoingMqttMessage($topic, $message);
+
return true;
}
} else {
diff --git a/inc/package.class.php b/inc/package.class.php
index 14ec914d..8a6a4658 100644
--- a/inc/package.class.php
+++ b/inc/package.class.php
@@ -70,6 +70,10 @@ public static function getMenuPicture() {
return 'fa-gear';
}
+ public function getAdditionalLinks() {
+ return [];
+ }
+
/**
* @see CommonGLPI::defineTabs()
*/
@@ -159,18 +163,12 @@ public function showForm($ID, array $options = []) {
$this->showFormButtons($options);
}
- /**
- * @see CommonDBTM::addNeededInfoToInput()
- */
public function addNeededInfoToInput($input) {
$input['entities_id'] = $_SESSION['glpiactive_entity'];
return $input;
}
- /**
- * @see CommonDBTM::prepareInputForAdd()
- */
public function prepareInputForAdd($input) {
// Name must not be populated
if (!Session::isCron()) {
@@ -211,13 +209,9 @@ public function prepareInputForAdd($input) {
return $input;
}
- /**
- * (non-PHPdoc)
- * @see CommonDBTM::prepareInputForUpdate()
- */
public function prepareInputForUpdate($input) {
if (is_int(Session::getLoginUserID()) && strpos($_SERVER['REQUEST_URI'], "front/crontask.form.php") !== false) {
- // a user is loged in and is not in the automatic actions page
+ // a user is logged in and is not in the automatic actions page
unset($input['package_name']);
}
@@ -254,13 +248,15 @@ public function prepareInputForUpdate($input) {
Session::addMessageAfterRedirect(__('Unable to save the file', "flyvemdm"));
$input = false;
}
+ if ($this->fields['parse_status'] === 'parsed'
+ || $this->fields['parse_status'] === 'failed'
+ ) {
+ $input['parse_status'] = 'pending';
+ }
return $input;
}
- /**
- * Actions done after the getFromDB method
- */
public function post_getFromDB() {
// Check the user can view this itemtype and can view this item
if (!$this->canView() || !$this->canViewItem()) {
@@ -297,9 +293,6 @@ private function createOrionReport() {
]);
}
- /**
- * @see CommonDBTM::post_updateItem()
- */
public function post_updateItem($history = 1) {
if (!$this->fields['package_name']) {
// disable sending a mqtt message when the name of the app is null
@@ -316,10 +309,21 @@ public function post_updateItem($history = 1) {
$this->createOrionReport();
}
- /**
- * @see CommonDBTM::pre_deleteItem()
- */
public function pre_deleteItem() {
+ // Reset import status in the linked F-Droid store
+ $fDroidApplication = new PluginFlyvemdmFDroidApplication();
+ $found = $fDroidApplication->getFromDBByCrit([
+ self::getForeignKeyField() => $this->fields['id']
+ ]);
+ if ($found) {
+ $fDroidApplication->update([
+ 'id' => $fDroidApplication->getID(),
+ self::getForeignKeyField() => 0,
+ 'import_status' => 'no_import',
+ ]);
+ }
+
+ // Delete tasks linked to the object
$task = new PluginFlyvemdmTask();
return $task->deleteByCriteria([
'itemtype' => $this->getType(),
diff --git a/inc/profile.class.php b/inc/profile.class.php
index ee94fa65..ed1f5e15 100644
--- a/inc/profile.class.php
+++ b/inc/profile.class.php
@@ -54,9 +54,12 @@ public static function purgeProfiles(Profile $prof) {
$plugprof->deleteByCriteria(['profiles_id' => $prof->getField("id")]);
}
- /**
- * @see Profile::showForm()
- */
+ function getRights($interface = 'central') {
+ $values = [self::RIGHT_FLYVEMDM_USE => __('Use Flyve MDM')];
+
+ return $values;
+ }
+
public function showForm($ID, $options = []) {
if (!Profile::canView()) {
return false;
@@ -92,9 +95,6 @@ public function showForm($ID, $options = []) {
$this->showLegend();
}
- /**
- * @see Profile::getTabNameForItem()
- */
public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
if ($item->getType() == Profile::class) {
return __('Flyve MDM', 'flyvemdm');
@@ -102,9 +102,6 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
return '';
}
- /**
- * @see Profile::displayTabContentForItem
- */
public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
if ($item->getType() == 'Profile') {
$profile = new self();
@@ -169,6 +166,8 @@ public function getAssetsRights() {
PluginFlyvemdmPolicy::class,
PluginFlyvemdmPolicyCategory::class,
PluginFlyvemdmWellknownpath::class,
+ PluginFlyvemdmFDroidMarket::class,
+ PluginFlyvemdmFDroidApplication::class,
];
$rights = [];
diff --git a/install/install.class.php b/install/install.class.php
index 51c82a6e..9ccb3904 100644
--- a/install/install.class.php
+++ b/install/install.class.php
@@ -235,6 +235,8 @@ protected function createFirstAccess() {
PluginFlyvemdmInvitationLog::$rightname => READ,
PluginFlyvemdmTaskstatus::$rightname => READ,
PluginFlyvemdmMqttlog::$rightname => READ,
+ PluginFlyvemdmFDroidApplication::$rightname => READ | UPDATE | READNOTE | UPDATENOTE,
+ PluginFlyvemdmFDroidMarket::$rightname => ALLSTANDARDRIGHT | READNOTE | UPDATENOTE,
];
$profileRight->updateProfileRights($_SESSION['glpiactiveprofile']['id'], $newRights);
@@ -825,6 +827,8 @@ protected function deleteTables() {
PluginFlyvemdmPolicyCategory::getTable(),
PluginFlyvemdmWellknownpath::getTable(),
PluginFlyvemdmTaskstatus::getTable(),
+ PluginFlyvemdmFdroidApplication::getTable(),
+ PluginFlyvemdmFdroidMarket::getTable(),
];
foreach ($tables as $table) {
@@ -848,16 +852,23 @@ protected function deleteProfiles() {
protected function deleteProfileRights() {
$rights = [
PluginFlyvemdmAgent::$rightname,
+ PluginFlyvemdmEntityConfig::$rightname,
+ PluginFlyvemdmFDroidApplication::$rightname,
+ PluginFlyvemdmFDroidMarket::$rightname,
+ PluginFlyvemdmFleet::$rightname,
+ PluginFlyvemdmPackage::$rightname,
PluginFlyvemdmFile::$rightname,
PluginFlyvemdmFleet::$rightname,
PluginFlyvemdmGeolocation::$rightname,
PluginFlyvemdmInvitation::$rightname,
PluginFlyvemdmInvitationlog::$rightname,
- PluginFlyvemdmPackage::$rightname,
+ PluginFlyvemdmInvitation::$rightname,
+ PluginFlyvemdmInvitationlog::$rightname,
PluginFlyvemdmPolicy::$rightname,
+ PluginFlyvemdmPolicyCategory::$rightname,
PluginFlyvemdmProfile::$rightname,
+ PluginFlyvemdmTaskstatus::$rightname,
PluginFlyvemdmWellknownpath::$rightname,
- PluginFlyvemdmMqttlog::$rightname,
];
foreach ($rights as $right) {
ProfileRight::deleteProfileRights([$right]);
diff --git a/install/mysql/plugin_flyvemdm_empty.sql b/install/mysql/plugin_flyvemdm_empty.sql
index 4afebbb3..97133eff 100644
--- a/install/mysql/plugin_flyvemdm_empty.sql
+++ b/install/mysql/plugin_flyvemdm_empty.sql
@@ -259,3 +259,41 @@ CREATE TABLE `glpi_plugin_flyvemdm_taskstatuses` (
INDEX `plugin_flyvemdm_agents_id` (`plugin_flyvemdm_agents_id`),
INDEX `plugin_flyvemdm_tasks_id` (`plugin_flyvemdm_tasks_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+-- Export de la structure de table glpi-flyvemdm. glpi_plugin_flyvemdm_fdroidapplications
+DROP TABLE IF EXISTS `glpi_plugin_flyvemdm_fdroidapplications`;
+CREATE TABLE `glpi_plugin_flyvemdm_fdroidapplications` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL DEFAULT '',
+ `package_name` varchar(255) NOT NULL DEFAULT '',
+ `entities_id` int(11) NOT NULL DEFAULT '0',
+ `is_recursive` tinyint(1) NOT NULL DEFAULT '0',
+ `plugin_flyvemdm_fdroidmarkets_id` int(11) NOT NULL DEFAULT '0',
+ `plugin_flyvemdm_packages_id` int(11) NOT NULL DEFAULT '0',
+ `alias` varchar(255) NOT NULL DEFAULT '',
+ `version` varchar(255) NOT NULL DEFAULT '',
+ `version_code` varchar(255) NOT NULL DEFAULT '',
+ `date_mod` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `desc` text NOT NULL,
+ `filename` varchar(255) NOT NULL DEFAULT '',
+ `filesize` int(11) NOT NULL DEFAULT '0',
+ `import_status` enum('no_import','to_import','imported') NOT NULL DEFAULT 'no_import',
+ `is_available` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Does the application exists in the store ?',
+ `is_auto_upgradable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Can we automatically download the upgrades ?',
+ PRIMARY KEY (`id`),
+ KEY `entities_id` (`entities_id`),
+ KEY `plugin_flyvemdm_fdroidmarkets_id` (`plugin_flyvemdm_fdroidmarkets_id`),
+ KEY `plugin_flyvemdm_packages_id` (`plugin_flyvemdm_packages_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+-- Export de la structure de table glpi-flyvemdm. glpi_plugin_flyvemdm_fdroidmarkets
+DROP TABLE IF EXISTS `glpi_plugin_flyvemdm_fdroidmarkets`;
+CREATE TABLE `glpi_plugin_flyvemdm_fdroidmarkets` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL DEFAULT '',
+ `entities_id` int(11) NOT NULL DEFAULT '0',
+ `is_recursive` tinyint(1) NOT NULL DEFAULT '0',
+ `url` varchar(255) NOT NULL DEFAULT '' COMMENT 'URL to index.xml of the market',
+ PRIMARY KEY (`id`),
+ KEY `entities_id` (`entities_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
diff --git a/install/upgrade_to_dev.php b/install/upgrade_to_dev.php
index f3b334b8..49568547 100644
--- a/install/upgrade_to_dev.php
+++ b/install/upgrade_to_dev.php
@@ -43,6 +43,14 @@ function upgrade(Migration $migration) {
$migration->setVersion(PLUGIN_FLYVEMDM_VERSION);
$profileRight = new ProfileRight();
+ // Merge new rights into current profile
+ $profiles_id = $_SESSION['glpiactiveprofile']['id'];
+ $currentRights = ProfileRight::getProfileRights($profiles_id);
+ $newRights = array_merge($currentRights, [
+ PluginFlyvemdmFDroidMarket::$rightname => ALLSTANDARDRIGHT | READNOTE | UPDATENOTE,
+ PluginFlyvemdmFDroidApplication::$rightname => READ | UPDATE | READNOTE | UPDATENOTE,
+ ]);
+ $profileRight->updateProfileRights($profiles_id, $newRights);
$config = Config::getConfigurationValues('flyvemdm');
if (!isset($config['mqtt_broker_port_backend'])) {
@@ -51,5 +59,73 @@ function upgrade(Migration $migration) {
$config['mqtt_broker_port_backend'] = $config['mqtt_broker_port'];
Config::setConfigurationValues('flyvemdm', $config);
}
+
+ // Create table for F-Droid application
+ $query = "CREATE TABLE IF NOT EXISTS `glpi_plugin_flyvemdm_fdroidapplications` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL DEFAULT '',
+ `package_name` varchar(255) NOT NULL DEFAULT '',
+ `entities_id` int(11) NOT NULL DEFAULT '0',
+ `is_recursive` tinyint(1) NOT NULL DEFAULT '0',
+ `plugin_flyvemdm_fdroidmarkets_id` int(11) NOT NULL DEFAULT '0',
+ `plugin_flyvemdm_packages_id` int(11) NOT NULL DEFAULT '0',
+ `alias` varchar(255) NOT NULL DEFAULT '',
+ `version` varchar(255) NOT NULL DEFAULT '',
+ `version_code` varchar(255) NOT NULL DEFAULT '',
+ `date_mod` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `desc` text NOT NULL,
+ `filename` varchar(255) NOT NULL DEFAULT '',
+ `filesize` int(11) NOT NULL DEFAULT '0',
+ `import_status` enum('no_import','to_import','imported') NOT NULL DEFAULT 'no_import',
+ `is_available` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Does the applciation e xists in the store ?',
+ `is_auto_upgradable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Can we automatically download the upgrades ?',
+ PRIMARY KEY (`id`),
+ KEY `entities_id` (`entities_id`),
+ KEY `plugin_flyvemdm_fdroidmarkets_id` (`plugin_flyvemdm_fdroidmarkets_id`),
+ KEY `plugin_flyvemdm_packages_id` (`plugin_flyvemdm_packages_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+ ";
+ $DB->query($query) or plugin_flyvemdm_upgrade_error($migration);
+
+ // Update enum if needed
+ $table = 'glpi_plugin_flyvemdm_fdroidapplications';
+ $enumImportStatus = PluginFlyvemdmFDroidApplication::getEnumImportStatus();
+ $currentEnumImportStatus = PluginFlyvemdmCommon::getEnumValues($table, 'import_status');
+ if (count($currentEnumImportStatus) > 0) {
+ // The field exists
+ if (count($currentEnumImportStatus) != count($enumImportStatus)) {
+ reset($enumImportStatus);
+ $defaultValue = key($enumImportStatus);
+ $enumImportStatus = "'" . implode("', '", array_keys($enumImportStatus)) . "'";
+ $query = "ALTER TABLE `$table`
+ CHANGE COLUMN `import_status` `import_status`
+ ENUM($enumImportStatus)
+ NOT NULL DEFAULT '$defaultValue'";
+ $DB->query($query) or plugin_flyvemdm_upgrade_error($migration);
+ }
+ } else {
+ // The field does not exists
+ reset($enumImportStatus);
+ $defaultValue = key($enumImportStatus);
+ $enumImportStatus = "'" . implode("', '", array_keys($enumImportStatus)) . "'";
+ $query = "ALTER TABLE `$table`
+ ADD COLUMN `import_status`
+ ENUM($enumImportStatus)
+ NOT NULL DEFAULT '$defaultValue'";
+ $DB->query($query) or plugin_flyvemdm_upgrade_error($migration);
+ }
+
+ // Create table for F-Droid
+ $query = "CREATE TABLE IF NOT EXISTS `glpi_plugin_flyvemdm_fdroidmarkets` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL DEFAULT '',
+ `entities_id` int(11) NOT NULL DEFAULT '0',
+ `is_recursive` tinyint(1) NOT NULL DEFAULT '0',
+ `url` varchar(255) NOT NULL DEFAULT '' COMMENT 'URL to index.xml of the market',
+ PRIMARY KEY (`id`),
+ KEY `entities_id` (`entities_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+ ";
+ $DB->query($query) or plugin_flyvemdm_upgrade_error($migration);
}
}
diff --git a/install/upgrade_to_develop.php b/install/upgrade_to_develop.php
new file mode 100644
index 00000000..2e65114a
--- /dev/null
+++ b/install/upgrade_to_develop.php
@@ -0,0 +1,123 @@
+setVersion(PLUGIN_FLYVEMDM_VERSION);
+
+ $profileRight = new ProfileRight();
+ // Merge new rights into current profile
+ $profiles_id = $_SESSION['glpiactiveprofile']['id'];
+ $currentRights = ProfileRight::getProfileRights($profiles_id);
+ $newRights = array_merge($currentRights, [
+ PluginFlyvemdmFDroidMarket::$rightname => ALLSTANDARDRIGHT | READNOTE | UPDATENOTE,
+ PluginFlyvemdmFDroidApplication::$rightname => READ | UPDATE | READNOTE | UPDATENOTE,
+ ]);
+ $profileRight->updateProfileRights($profiles_id, $newRights);
+
+ // Create table for F-Droid application
+ $query = "CREATE TABLE IF NOT EXISTS `glpi_plugin_flyvemdm_fdroidapplications` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL DEFAULT '',
+ `package_name` varchar(255) NOT NULL DEFAULT '',
+ `entities_id` int(11) NOT NULL DEFAULT '0',
+ `is_recursive` tinyint(1) NOT NULL DEFAULT '0',
+ `plugin_flyvemdm_fdroidmarkets_id` int(11) NOT NULL DEFAULT '0',
+ `plugin_flyvemdm_packages_id` int(11) NOT NULL DEFAULT '0',
+ `alias` varchar(255) NOT NULL DEFAULT '',
+ `version` varchar(255) NOT NULL DEFAULT '',
+ `version_code` varchar(255) NOT NULL DEFAULT '',
+ `date_mod` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `desc` text NOT NULL,
+ `filename` varchar(255) NOT NULL DEFAULT '',
+ `filesize` int(11) NOT NULL DEFAULT '0',
+ `import_status` enum('no_import','to_import','imported') NOT NULL DEFAULT 'no_import',
+ `is_available` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Does the applciation e xists in the store ?',
+ `is_auto_upgradable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Can we automatically download the upgrades ?',
+ PRIMARY KEY (`id`),
+ KEY `entities_id` (`entities_id`),
+ KEY `plugin_flyvemdm_fdroidmarkets_id` (`plugin_flyvemdm_fdroidmarkets_id`),
+ KEY `plugin_flyvemdm_packages_id` (`plugin_flyvemdm_packages_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+ ";
+ $DB->query($query) or plugin_flyvemdm_upgrade_error($migration);
+
+ // Update enum if needed
+ $table = 'glpi_plugin_flyvemdm_fdroidapplications';
+ $enumImportStatus = PluginFlyvemdmFDroidApplication::getEnumImportStatus();
+ $currentEnumImportStatus = PluginFlyvemdmCommon::getEnumValues($table, 'import_status');
+ if (count($currentEnumImportStatus) > 0) {
+ // The field exists
+ if (count($currentEnumImportStatus) != count($enumImportStatus)) {
+ reset($enumImportStatus);
+ $defaultValue = key($enumImportStatus);
+ $enumImportStatus = "'" . implode("', '", array_keys($enumImportStatus)) . "'";
+ $query = "ALTER TABLE `$table`
+ CHANGE COLUMN `import_status` `import_status`
+ ENUM($enumImportStatus)
+ NOT NULL DEFAULT '$defaultValue'";
+ $DB->query($query) or plugin_flyvemdm_upgrade_error($migration);
+ }
+ } else {
+ // The field does not exists
+ reset($enumImportStatus);
+ $defaultValue = key($enumImportStatus);
+ $enumImportStatus = "'" . implode("', '", array_keys($enumImportStatus)) . "'";
+ $query = "ALTER TABLE `$table`
+ ADD COLUMN `import_status`
+ ENUM($enumImportStatus)
+ NOT NULL DEFAULT '$defaultValue'";
+ $DB->query($query) or plugin_flyvemdm_upgrade_error($migration);
+ }
+
+ // Create table for F-Droid
+ $query = "CREATE TABLE IF NOT EXISTS `glpi_plugin_flyvemdm_fdroidmarkets` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL DEFAULT '',
+ `entities_id` int(11) NOT NULL DEFAULT '0',
+ `is_recursive` tinyint(1) NOT NULL DEFAULT '0',
+ `url` varchar(255) NOT NULL DEFAULT '' COMMENT 'URL to index.xml of the market',
+ PRIMARY KEY (`id`),
+ KEY `entities_id` (`entities_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+ ";
+ $DB->query($query) or plugin_flyvemdm_upgrade_error($migration);
+ }
+}
\ No newline at end of file
diff --git a/tests/fixtures/fdroid-app-new-version.xml b/tests/fixtures/fdroid-app-new-version.xml
new file mode 100644
index 00000000..1fee2041
--- /dev/null
+++ b/tests/fixtures/fdroid-app-new-version.xml
@@ -0,0 +1,72 @@
+
Features
+
+Edge Swipe makes it possible to quickly access frequently used apps with just a swipe of the finger from the left or right side of the screen towards the center, and then release it on the desired app. With this feature you can keep your home screen clean and tidy, and only access your important apps when you need to see them.
+
+The App Life Cycle is a section in the Fairphone where all downloaded and installed apps are vertically displayed. App Life Cycle creates more awareness for the user on how they use their Fairphone in combination with apps. It makes apps become “living things.”
+
+The App Life Cycle includes an algorithm that keeps track of how much an app is being used and puts less often used apps in the Idle section after a certain amount of time. This way you get an overview of an app’s usage, and you can easily uninstall apps that are not necessary anymore. This feature only stores information locally on the device; your app usage is not shared in any way.
+
+New and updated apps are bannered for the sake of clarity, and if you don’t want an app to go into idle after a while (because you don’t use it often, but still need to access it quickly when you need it), you can simply “pin” an app so it stays inside the active section.
+
+Icon pack support was added by the WeAreFairphone community. The launcher is the most visited app in your device, so customization is key for making you feel more confortable.
+');
+ }
+
+
+ public function testPre_deleteItem() {
+ $instance = $this->createDummyPackage(0);
+ $fleet = $this->createFleet();
+ $policy = new \PluginFlyvemdmPolicy();
+ $policy->getFromDBBySymbol('deployApp');
+ $task = $this->createTask([
+ 'itemtype_applied' => $fleet::getType(),
+ 'items_id_applied' => $fleet->getID(),
+ 'value' => [
+ 'remove_on_delete' => '1',
+ ],
+ 'plugin_flyvemdm_policies_id' => $policy->getID(),
+ 'itemtype' => $instance::getType(),
+ 'items_id' => $instance->getID(),
+ ]);
+ $this->boolean($task->isNewItem())->isFalse();
+
+ $fdroidApplication = new \PluginFlyvemdmFdroidApplication();
+ $fdroidApplication->add([
+ $instance::getForeignKeyField() => $instance->getID(),
+ ]);
+
+ $output = $instance->pre_deleteItem();
+
+ // check the call suceeded
+ $this->boolean($output)->isTrue();
+
+ // Check the task is removed
+ $deletedTask = new \PluginFlyvemdmTask();
+ $deletedTask->getFromDB($task->getID());
+ $this->boolean($deletedTask->isNewItem())->isTrue();
+
+ // Check the Fdroid application is unlinked
+ $packageFk = $instance::getForeignKeyField();
+ $unlinkedFdroidApplication = new \PluginFlyvemdmFdroidApplication();
+ $unlinkedFdroidApplication->getFromDB($fdroidApplication->getID());
+ $this->integer((int) $unlinkedFdroidApplication->fields[$packageFk])
+ ->isEqualTo(0);
+ }
+
/**
* @tags testPrepareInputForUpdate
*/
@@ -203,5 +254,4 @@ private function assertInvalidResult($result, $message) {
$this->string($_SESSION["MESSAGE_AFTER_REDIRECT"][0][0])->isEqualTo($message);
unset($_SESSION["MESSAGE_AFTER_REDIRECT"]); // to clear the buffer
}
-
-}
\ No newline at end of file
+}
diff --git a/tpl/agentComputerInfo.html.twig b/tpl/agentComputerInfo.html.twig
index 29a8b6fc..013b8596 100644
--- a/tpl/agentComputerInfo.html.twig
+++ b/tpl/agentComputerInfo.html.twig
@@ -1,6 +1,6 @@
| {{ __('Flyve MDM') }} | +{{ __('Flyve MDM', 'flyvemdm') }} |
|---|