CRM-13672 - Add option to suppress current update alerts
authorColeman Watts <coleman@civicrm.org>
Sat, 20 Dec 2014 19:47:04 +0000 (14:47 -0500)
committerColeman Watts <coleman@civicrm.org>
Tue, 30 Dec 2014 01:42:08 +0000 (20:42 -0500)
CRM/Admin/Form/Setting/Miscellaneous.php
CRM/Utils/VersionCheck.php
settings/Core.setting.php
templates/CRM/Admin/Form/Setting/Miscellaneous.tpl
templates/CRM/Admin/Form/Setting/versionCheckOptions.js [new file with mode: 0644]

index f5b03e0d74b2c3c44799e5da6cc72353b6c7aced..d6123cd3b0ace86ff3286a8cedb8cbcb8b148800 100644 (file)
@@ -45,6 +45,7 @@ class CRM_Admin_Form_Setting_Miscellaneous extends CRM_Admin_Form_Setting {
     'versionAlert' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'securityUpdateAlert' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'versionCheck' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
+    'versionCheckIgnoreDate' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'empoweredBy' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'maxFileSize' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'doNotAttachPDFReceipt' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
index 973246a82379c0ac14916f09c0d92c2b1b5021c7..e8cdf969a737bddc32b5d84adf6f334d96105b93 100644 (file)
@@ -67,6 +67,13 @@ class CRM_Utils_VersionCheck {
    */
   public $localMajorVersion;
 
+  /**
+   * User setting to skip updates prior to a certain date
+   *
+   * @var string
+   */
+  public $ignoreDate;
+
   /**
    * Info about available versions
    *
@@ -108,6 +115,7 @@ class CRM_Utils_VersionCheck {
       $this->localVersion = trim($info['version']);
       $this->localMajorVersion = $this->getMajorVersion($this->localVersion);
     }
+    // Populate $versionInfo
     if (CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'versionCheck', NULL, 1)) {
       // Use cached data if available and not stale
       if (!$this->readCacheFile()) {
@@ -117,26 +125,11 @@ class CRM_Utils_VersionCheck {
         // Get the latest version and send site info
         $this->pingBack();
       }
-    }
-    // Make sure version info is in ascending order for easier comparisons
-    ksort($this->versionInfo, SORT_NUMERIC);
-  }
+      $this->ignoreDate = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'versionCheckIgnoreDate');
 
-  /**
-   * Magic property accessor
-   * @param $variable
-   * @return mixed
-   */
-  function __get($variable) {
-    switch ($variable) {
-      case "localVersionStatus":
-        if ($this->localVersion && $this->versionInfo) {
-          $versionInfo = CRM_Utils_Array::value($this->localMajorVersion, $this->versionInfo);
-          return CRM_Utils_Array::value('status', $versionInfo);
-        }
-        return NULL;
+      // Sort version info in ascending order for easier comparisons
+      ksort($this->versionInfo, SORT_NUMERIC);
     }
-    return NULL;
   }
 
   /**
@@ -183,13 +176,18 @@ class CRM_Utils_VersionCheck {
     return "$a.$b";
   }
 
+  /**
+   * @return bool
+   */
   public function isSecurityUpdateAvailable() {
     $thisVersion = $this->getReleaseInfo($this->localVersion);
     $localVersionDate = CRM_Utils_Array::value('date', $thisVersion, 0);
     foreach ($this->versionInfo as $majorVersion) {
       foreach ($majorVersion['releases'] as $release) {
         if (!empty($release['security']) && $release['date'] > $localVersionDate) {
-          return TRUE;
+          if (!$this->ignoreDate || $this->ignoreDate < $release['date']) {
+            return TRUE;
+          }
         }
       }
     }
@@ -199,24 +197,39 @@ class CRM_Utils_VersionCheck {
    * Get the latest version number if it's newer than the local one
    *
    * @return string|null
-   * Returns the newer version's number, or null if the versions are equal
+   * Returns version number of the latest release if it is greater than the local version
    */
   public function isNewerVersionAvailable() {
     $newerVersion = NULL;
     if ($this->versionInfo && $this->localVersion) {
-      // If using an alpha or beta, find the absolute latest available
-      $latest = end($this->versionInfo);
-      // Otherwise find the latest stable version available
-      if ($this->localVersionStatus != 'testing') {
-        foreach ($this->versionInfo as $majorVersion) {
-          if ($majorVersion['status'] == 'stable') {
-            $latest = $majorVersion;
+      foreach ($this->versionInfo as $majorVersionNumber => $majorVersion) {
+        $release = $this->checkBranchForNewVersion($majorVersion);
+        if ($release) {
+          // If we have a release with the same majorVersion as local, return it
+          if ($majorVersionNumber == $this->localMajorVersion) {
+            return $release;
+          }
+          // Search outside the local majorVersion (excluding non-stable)
+          elseif ($majorVersion['status'] != 'testing') {
+            // We found a new release but don't return yet, keep searching newer majorVersions
+            $newerVersion = $release;
           }
         }
       }
-      if ($latest && !empty($latest['releases'])) {
-        foreach ($latest['releases'] as $release) {
-          if (version_compare($this->localVersion, $release['version']) < 0) {
+    }
+    return $newerVersion;
+  }
+
+  /**
+   * @param $majorVersion
+   * @return null|string
+   */
+  private function checkBranchForNewVersion($majorVersion) {
+    $newerVersion = NULL;
+    if (!empty($majorVersion['releases'])) {
+      foreach ($majorVersion['releases'] as $release) {
+        if (version_compare($this->localVersion, $release['version']) < 0) {
+          if (!$this->ignoreDate || $this->ignoreDate < $release['date']) {
             $newerVersion = $release['version'];
           }
         }
@@ -232,6 +245,7 @@ class CRM_Utils_VersionCheck {
   public function versionAlert() {
     $versionAlertSetting = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'versionAlert', NULL, 1);
     $securityAlertSetting = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'securityUpdateAlert', NULL, 3);
+    $settingsUrl =  CRM_Utils_System::url('civicrm/admin/setting/misc', 'reset=1', FALSE, NULL, FALSE, FALSE, TRUE);
     if (CRM_Core_Permission::check('administer CiviCRM') && $securityAlertSetting > 1 && $this->isSecurityUpdateAvailable()) {
       $session = CRM_Core_Session::singleton();
       if ($session->timer('version_alert', 24 * 60 * 60)) {
@@ -239,8 +253,10 @@ class CRM_Utils_VersionCheck {
           '<ul>
             <li><a href="https://civicrm.org/advisory">' . ts('Read advisory') . '</a></li>
             <li><a href="https://civicrm.org/download">' . ts('Download now') . '</a></li>
+            <li><a class="crm-setVersionCheckIgnoreDate" href="' . $settingsUrl . '">' . ts('Suppress this message') . '</a></li>
           </ul>';
-        $session->setStatus($msg, ts('Security Alert'));
+        $session->setStatus($msg, ts('Security Alert'), 'alert');
+        CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'templates/CRM/Admin/Form/Setting/versionCheckOptions.js');
       }
     }
     elseif (CRM_Core_Permission::check('administer CiviCRM') && $versionAlertSetting > 1) {
@@ -248,9 +264,13 @@ class CRM_Utils_VersionCheck {
       if ($newerVersion) {
         $session = CRM_Core_Session::singleton();
         if ($session->timer('version_alert', 24 * 60 * 60)) {
-          $msg = ts('A newer version of CiviCRM is available: %1', array(1 => $newerVersion))
-          . '<br /><a href="https://civicrm.org/download">' . ts('Download now') . '</a>';
+          $msg = ts('A newer version of CiviCRM is available: %1', array(1 => $newerVersion)) .
+            '<ul>
+              <li><a href="https://civicrm.org/download">' . ts('Download now') . '</a></li>
+              <li><a class="crm-setVersionCheckIgnoreDate" href="' . $settingsUrl . '">' . ts('Suppress this message') . '</a></li>
+            </ul>';
           $session->setStatus($msg, ts('Update Available'), 'info');
+          CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'templates/CRM/Admin/Form/Setting/versionCheckOptions.js');
         }
       }
     }
index ffd41021b338b6e0cca80a3e1e713ba9384f4c6f..66b697e6e0193e23d44912bc3facd800d925077e 100644 (file)
@@ -407,6 +407,22 @@ return array (
     'description' => "",
     'help_text' => null,
   ),
+  'versionCheckIgnoreDate' => array(
+    'group_name' => 'CiviCRM Preferences',
+    'group' => 'core',
+    'name' => 'versionCheckIgnoreDate',
+    'type' => 'String',
+    'quick_form_type' => 'Element',
+    'html_type' => 'text',
+    'html_attributes' => array('placeholder' => 'YYYY-MM-DD'),
+    'default' => '',
+    'add' => '4.6',
+    'title' => 'Ignore Updates Prior to',
+    'is_domain' => 1,
+    'is_contact' => 0,
+    'description' => "",
+    'help_text' => null,
+  ),
   'securityAlert' => array(
     'group_name' => 'CiviCRM Preferences',
     'group' => 'core',
index 7b3f84a9db44d4e2e2e8b2961b42b8f6fa54d05e..8c7fb3012fdd11c39843e099739db83cb07152e5 100644 (file)
             <td>{$form.versionCheck.html}<br />
                 <p class="description">{ts}When enabled, statistics about your CiviCRM installation are reported anonymously to the CiviCRM team to assist in prioritizing ongoing development efforts. The following information is gathered: CiviCRM version, versions of PHP, MySQL and framework (Drupal/Joomla/standalone), and default language. Counts (but no actual data) of the following record types are reported: contacts, activities, cases, relationships, contributions, contribution pages, contribution products, contribution widgets, discounts, price sets, profiles, events, participants, tell-a-friend pages, grants, mailings, memberships, membership blocks, pledges, pledge blocks and active payment processor types.{/ts}</p></td>
         </tr>
+        <tr class="crm-miscellaneous-form-block-versionCheckIgnoreDate">
+            <td class="label">{$form.versionCheckIgnoreDate.label}</td>
+            <td>{$form.versionCheckIgnoreDate.html|crmReplace:type:date}<br />
+                <p class="description">{ts}If you wish to stop receiving alerts about a current update (for example, if you have applied a security patch manually), set this to today's date.{/ts}</p></td>
+        </tr>
         <tr class="crm-miscellaneous-form-block-securityUpdateAlert">
           <td class="label">{$form.securityUpdateAlert.label}</td>
           <td>{$form.securityUpdateAlert.html}<br />
diff --git a/templates/CRM/Admin/Form/Setting/versionCheckOptions.js b/templates/CRM/Admin/Form/Setting/versionCheckOptions.js
new file mode 100644 (file)
index 0000000..c6de62a
--- /dev/null
@@ -0,0 +1,24 @@
+// https://civicrm.org/licensing
+CRM.$(function($) {
+  'use strict';
+  $(document)
+    .off('.crmVersionCheckOptions')
+    .on('click.crmVersionCheckOptions', 'a.crm-setVersionCheckIgnoreDate', function(e) {
+      var isSecurity = !($(this).closest('.ui-notify-message').hasClass('info'));
+      var msg = '<p>' + ts('This will suppress notifications about all currently available updates.') + ' ';
+      if (isSecurity) {
+        msg += ts('Notifications will resume when a new security advisory is published.') +
+          '</p><p>' +
+          ts('Warning: Do this only if you have already taken alternate steps to ensure your site is secure.');
+      } else {
+        msg += ts('Notifications will resume when a new release is published.');
+      }
+      msg += '</p>';
+      CRM.confirm({message: msg, title: $(this).text()})
+        .on('crmConfirm:yes', function() {
+          CRM.api3('setting', 'create', {versionCheckIgnoreDate: new Date().toISOString().slice(0,10)}, true);
+          CRM.closeAlertByChild('a.crm-setVersionCheckIgnoreDate');
+        });
+      e.preventDefault();
+    });
+});