diff --git a/application/Espo/Core/defaults/config.php b/application/Espo/Core/defaults/config.php index 480e6510e5..37afe59630 100644 --- a/application/Espo/Core/defaults/config.php +++ b/application/Espo/Core/defaults/config.php @@ -111,6 +111,7 @@ return array ( 'adminNotifications' => true, 'adminNotificationsNewVersion' => true, 'adminNotificationsCronIsNotConfigured' => true, + 'adminNotificationsNewExtensionVersion' => true, 'assignmentEmailNotifications' => false, 'assignmentEmailNotificationsEntityList' => ['Lead', 'Opportunity', 'Task', 'Case'], 'assignmentNotificationsEntityList' => ['Meeting', 'Call', 'Task', 'Email'], diff --git a/application/Espo/Core/defaults/systemConfig.php b/application/Espo/Core/defaults/systemConfig.php index 514f1c4501..99275895f8 100644 --- a/application/Espo/Core/defaults/systemConfig.php +++ b/application/Espo/Core/defaults/systemConfig.php @@ -154,7 +154,11 @@ return array ( 'defaultPermissions' => 'ldapUserTeamsIds', 'ldapUserTeamsNames', 'cleanupJobPeriod', - 'cleanupActionHistoryPeriod' + 'cleanupActionHistoryPeriod', + 'adminNotifications', + 'adminNotificationsNewVersion', + 'adminNotificationsCronIsNotConfigured', + 'adminNotificationsNewExtensionVersion' ), 'userItems' => array ( diff --git a/application/Espo/Jobs/CheckNewExtensionsVersions.php b/application/Espo/Jobs/CheckNewExtensionsVersions.php new file mode 100644 index 0000000000..d089891acb --- /dev/null +++ b/application/Espo/Jobs/CheckNewExtensionsVersions.php @@ -0,0 +1,54 @@ +getConfig()->get('adminNotifications') || !$this->getConfig()->get('adminNotificationsNewExtensionVersion')) { + return true; + } + + $job = $this->getEntityManager()->getEntity('Job'); + $job->set(array( + 'name' => 'Check for New Version of installed extensions (job)', + 'serviceName' => 'AdminNotifications', + 'methodName' => 'jobCheckNewExtensionsVersions', + 'executeTime' => $this->getRunTime() + )); + + $this->getEntityManager()->saveEntity($job); + + return true; + } +} \ No newline at end of file diff --git a/application/Espo/Resources/i18n/en_US/Settings.json b/application/Espo/Resources/i18n/en_US/Settings.json index 468b24d53a..8cc19e8bdf 100644 --- a/application/Espo/Resources/i18n/en_US/Settings.json +++ b/application/Espo/Resources/i18n/en_US/Settings.json @@ -93,6 +93,7 @@ "aclAllowDeleteCreated": "Allow to remove created records", "adminNotifications": "System notifications in administration panel", "adminNotificationsNewVersion": "Show notification when new EspoCRM version is available", + "adminNotificationsNewExtensionVersion": "Show notification when new version of extensions are available", "textFilterUseContainsForVarchar": "Use 'contains' operator when filtering varchar fields", "authTokenPreventConcurrent": "Only one auth token per user", "scopeColorsDisabled": "Disable scope colors", diff --git a/application/Espo/Resources/layouts/Settings/notifications.json b/application/Espo/Resources/layouts/Settings/notifications.json index 58d2936061..a0abba9d6c 100644 --- a/application/Espo/Resources/layouts/Settings/notifications.json +++ b/application/Espo/Resources/layouts/Settings/notifications.json @@ -19,7 +19,7 @@ "label": "Admin Notifications", "rows": [ [{"name": "adminNotifications"}, false], - [{"name": "adminNotificationsNewVersion"}, false] + [{"name": "adminNotificationsNewVersion"}, {"name": "adminNotificationsNewExtensionVersion"}] ] } ] \ No newline at end of file diff --git a/application/Espo/Resources/metadata/entityDefs/ScheduledJob.json b/application/Espo/Resources/metadata/entityDefs/ScheduledJob.json index 6cb3d2137a..7c9914cd5b 100644 --- a/application/Espo/Resources/metadata/entityDefs/ScheduledJob.json +++ b/application/Espo/Resources/metadata/entityDefs/ScheduledJob.json @@ -82,6 +82,11 @@ "name": "Check for New Version", "isSystem": true, "scheduling": "15 5 * * *" + }, + "CheckNewExtensionsVersions": { + "name": "Check for New Version of Installed Extensions", + "isSystem": true, + "scheduling": "25 5 * * *" } } } diff --git a/application/Espo/Resources/metadata/entityDefs/Settings.json b/application/Espo/Resources/metadata/entityDefs/Settings.json index 8f58e048c2..6c0fcb7ddc 100644 --- a/application/Espo/Resources/metadata/entityDefs/Settings.json +++ b/application/Espo/Resources/metadata/entityDefs/Settings.json @@ -453,6 +453,9 @@ "adminNotificationsNewVersion": { "type": "bool" }, + "adminNotificationsNewExtensionVersion": { + "type": "bool" + }, "textFilterUseContainsForVarchar": { "type": "bool", "tooltip": true diff --git a/application/Espo/Services/AdminNotifications.php b/application/Espo/Services/AdminNotifications.php index 8b1bdf2c32..b8035dbae2 100644 --- a/application/Espo/Services/AdminNotifications.php +++ b/application/Espo/Services/AdminNotifications.php @@ -31,6 +31,13 @@ namespace Espo\Services; class AdminNotifications extends \Espo\Core\Services\Base { + /** + * Job for checking a new version of EspoCRM + * + * @param object $data + * + * @return boolean + */ public function jobCheckNewVersion($data) { $config = $this->getConfig(); @@ -40,24 +47,129 @@ class AdminNotifications extends \Espo\Core\Services\Base } $latestRelease = $this->getLatestRelease(); - if (!empty($latestRelease['version']) && $config->get('latestVersion') != $latestRelease['version']) { + if (empty($latestRelease['version'])) { $config->set('latestVersion', $latestRelease['version']); $config->save(); + return true; + } + + if ($config->get('latestVersion') != $latestRelease['version']) { + $config->set('latestVersion', $latestRelease['version']); + + if (!empty($latestRelease['notes'])) { + //todo: create notification + } + + $config->save(); + return true; + } + + if (!empty($latestRelease['notes'])) { + //todo: find and modify notification + } + + return true; + } + + /** + * Job for cheking a new version of installed extensions + * + * @param object $data + * + * @return boolean + */ + public function jobCheckNewExtensionsVersions($data) + { + $config = $this->getConfig(); + + if (!$config->get('adminNotifications') || !$config->get('adminNotificationsNewExtensionVersion')) { + return true; + } + + $pdo = $this->getEntityManager()->getPDO(); + + $query = " + SELECT id, name, version, check_version_url as url + FROM extension + WHERE deleted = 0 + AND is_installed = 1 + ORDER BY created_at + "; + + $sth = $pdo->prepare($query); + $sth->execute(); + + $rowList = $sth->fetchAll(\PDO::FETCH_ASSOC); + + $latestReleases = []; + foreach ($rowList as $row) { + + $url = !empty($row['url']) ? $row['url'] : null; + $extensionName = $row['name']; + + $latestRelease = $this->getLatestRelease($url, [ + 'response' => 'latestRelease', + 'name' => $extensionName, + ]); + + if (!empty($latestRelease) && !isset($latestRelease['error'])) { + $latestReleases[$extensionName] = $latestRelease; + } + } + + $latestExtensionVersions = $config->get('latestExtensionVersions', []); + + $save = false; + foreach ($latestReleases as $extensionName => $extensionData) { + + if (empty($latestExtensionVersions[$extensionName])) { + $latestExtensionVersions[$extensionName] = $extensionData['version']; + $save = true; + continue; + } + + if ($latestExtensionVersions[$extensionName] != $extensionData['version']) { + $latestExtensionVersions[$extensionName] = $extensionData['version']; + + if (!empty($extensionData['notes'])) { + //todo: create notification + } + + $save = true; + continue; + } + + if (!empty($extensionData['notes'])) { + //todo: find and modify notification + } + } + + if ($save) { + $config->set('latestExtensionVersions', $latestExtensionVersions); + $config->save(); } return true; } - protected function getLatestRelease($url = null, array $requestData = ['action' => 'latestRelease']) + /** + * Get latest version + * + * @param string $url + * @param array $requestData + * + * @return array|null + */ + protected function getLatestRelease($url = null, array $requestData = ['response' => 'latestRelease']) { if (function_exists('curl_version')) { $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url ? $url : base64_decode('aHR0cHM6Ly9zLmVzcG9jcm0uY29tLw==')); + $requestUrl = $url ? $url : base64_decode('aHR0cHM6Ly9zLmVzcG9jcm0uY29tLw=='); + + curl_setopt($ch, CURLOPT_URL, $requestUrl. '?' . http_build_query($requestData)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($requestData)); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); diff --git a/client/src/views/admin/notifications.js b/client/src/views/admin/notifications.js index d129ac560b..107f770640 100644 --- a/client/src/views/admin/notifications.js +++ b/client/src/views/admin/notifications.js @@ -54,14 +54,14 @@ Espo.define('views/admin/notifications', 'views/settings/record/edit', function true: [ { action: 'show', - fields: ['adminNotificationsNewVersion'] + fields: ['adminNotificationsNewVersion', 'adminNotificationsNewExtensionVersion'] } ] }, default: [ { action: 'hide', - fields: ['adminNotificationsNewVersion'] + fields: ['adminNotificationsNewVersion', 'adminNotificationsNewExtensionVersion'] } ] }