CRM_Utils_Cache::create - Use factory function
authorTim Otten <totten@civicrm.org>
Sat, 12 Sep 2015 03:36:44 +0000 (20:36 -0700)
committerTim Otten <totten@civicrm.org>
Thu, 17 Sep 2015 22:49:30 +0000 (15:49 -0700)
Low-level tools like GenCode may run without access to a database. When we
try to use caching in central code, the cache-accesses are prone to
crashing. The problem -- in this environment, we shouldn't even try to use
databse for caching.

`CRM_Utils_Cache::create()` will attempt to create the best cache it can,
depending on what services are available.

CRM/Core/BAO/Setting.php
CRM/Core/CommunityMessages.php
CRM/Core/Resources.php
CRM/Cxn/CiviCxnHttp.php
CRM/Extension/System.php
CRM/Utils/Cache.php
Civi/Core/Container.php

index a9688fc9ac8b7ade03d59b4a69340e6cc720f3b4..e249aeca52aaae71e18ad38b468d0ba831eb3230 100644 (file)
@@ -44,6 +44,7 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting {
    * Various predefined settings that have been migrated to the setting table.
    */
   const
+    ALL = 'all',
     ADDRESS_STANDARDIZATION_PREFERENCES_NAME = 'Address Standardization Preferences',
     CAMPAIGN_PREFERENCES_NAME = 'Campaign Preferences',
     DEVELOPER_PREFERENCES_NAME = 'Developer Preferences',
@@ -633,22 +634,25 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting {
     $domainID = NULL,
     $profile = NULL
   ) {
-    $cacheString = 'settingsMetadata_' . $domainID . '_' . $profile;
+    $cache = Civi::cache('settings');
+
+    $cacheString = 'settingsMetadata_' . $domainID . '_' . $profile . '_' . $componentID;
     foreach ($filters as $filterField => $filterString) {
       $cacheString .= "_{$filterField}_{$filterString}";
     }
     $cached = 1;
     // the caching into 'All' seems to be a duplicate of caching to
     // settingsMetadata__ - I think the reason was to cache all settings as defined & then those altered by a hook
-    $settingsMetadata = CRM_Core_BAO_Cache::getItem('CiviCRM setting Specs', $cacheString, $componentID);
+    $settingsMetadata = $cache->get($cacheString);
+
     if ($settingsMetadata === NULL) {
-      $settingsMetadata = CRM_Core_BAO_Cache::getItem('CiviCRM setting Spec', 'All', $componentID);
+      $settingsMetadata = $cache->get(self::ALL);
       if (empty($settingsMetadata)) {
         global $civicrm_root;
         $metaDataFolders = array($civicrm_root . '/settings');
         CRM_Utils_Hook::alterSettingsFolders($metaDataFolders);
         $settingsMetadata = self::loadSettingsMetaDataFolders($metaDataFolders);
-        CRM_Core_BAO_Cache::setItem($settingsMetadata, 'CiviCRM setting Spec', 'All', $componentID);
+        $cache->set(self::ALL, $settingsMetadata);
       }
       $cached = 0;
     }
@@ -660,12 +664,7 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting {
       // this is a bit 'heavy' if you are using hooks but this function
       // is expected to only be called during setting administration
       // it should not be called by 'getvalue' or 'getitem
-      CRM_Core_BAO_Cache::setItem(
-        $settingsMetadata,
-        'CiviCRM setting Specs',
-        $cacheString,
-        $componentID
-      );
+      $cache->set($cacheString, $settingsMetadata);
     }
     return $settingsMetadata;
 
@@ -700,7 +699,7 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting {
       $settings = include $file;
       $settingMetaData = array_merge($settingMetaData, $settings);
     }
-    CRM_Core_BAO_Cache::setItem($settingMetaData, 'CiviCRM setting Spec', 'All');
+    Civi::cache('settings')->set(self::ALL, $settingMetaData);
     return $settingMetaData;
   }
 
index 908bf362f0a572930f6eaaa572a74901f9f17002..c99c945d77be3cbe76a26df5eb7287da8be1ba26 100644 (file)
@@ -60,10 +60,7 @@ class CRM_Core_CommunityMessages {
    */
   public static function create() {
     return new CRM_Core_CommunityMessages(
-      new CRM_Utils_Cache_SqlGroup(array(
-        'group' => 'community-messages',
-        'prefetch' => FALSE,
-      )),
+      Civi::cache('community_messages'),
       CRM_Utils_HttpClient::singleton()
     );
   }
index 7d0e3649e474f18388a4a54cd8d812d4a4139a78..f2bb53a18f8dd22f447867241f4b255b0754b4e6 100644 (file)
@@ -111,10 +111,7 @@ class CRM_Core_Resources {
     }
     if (self::$_singleton === NULL) {
       $sys = CRM_Extension_System::singleton();
-      $cache = new CRM_Utils_Cache_SqlGroup(array(
-                 'group' => 'js-strings',
-                 'prefetch' => FALSE,
-               ));
+      $cache = Civi::cache('js_strings');
       self::$_singleton = new CRM_Core_Resources(
         $sys->getMapper(),
         $cache,
index c64e79be6060ea9c6b6148ada28a6039506f5711..d1b5e7f48b15a04e485dc7e90c7722081a8f4d84 100644 (file)
@@ -22,17 +22,11 @@ class CRM_Cxn_CiviCxnHttp extends \Civi\Cxn\Rpc\Http\PhpHttp {
    */
   public static function singleton($fresh = FALSE) {
     if (self::$singleton === NULL || $fresh) {
-      $config = CRM_Core_Config::singleton();
-
-      if ($config->debug) {
-        $cache = new CRM_Utils_Cache_Arraycache(array());
-      }
-      else {
-        $cache = new CRM_Utils_Cache_SqlGroup(array(
-          'group' => 'CiviCxnHttp',
-          'prefetch' => FALSE,
-        ));
-      }
+      $cache = CRM_Utils_Cache::create(array(
+        'name' => 'CiviCxnHttp',
+        'type' => Civi::settings()->get('debug_enabled') ? 'ArrayCache' : array('SqlGroup', 'ArrayCache'),
+        'prefetch' => FALSE,
+      ));
 
       self::$singleton = new CRM_Cxn_CiviCxnHttp($cache);
     }
index e453bc167f45362ff07049ea87c07a4b6dbd94fa..a04d63cb7c1f2f82af4e2a7f698ee5b141af00ec 100644 (file)
@@ -240,16 +240,13 @@ class CRM_Extension_System {
    */
   public function getCache() {
     if ($this->cache === NULL) {
-      if (defined('CIVICRM_DSN')) {
-        $cacheGroup = md5(serialize(array('ext', $this->parameters)));
-        $this->cache = new CRM_Utils_Cache_SqlGroup(array(
-          'group' => $cacheGroup,
-          'prefetch' => TRUE,
-        ));
-      }
-      else {
-        $this->cache = new CRM_Utils_Cache_ArrayCache(array());
-      }
+      $cacheGroup = md5(serialize(array('ext', $this->parameters)));
+      // Extension system starts before container. Manage our own cache.
+      $this->cache = CRM_Utils_Cache::create(array(
+        'name' => $cacheGroup,
+        'type' => array('SqlGroup', 'ArrayCache'),
+        'prefetch' => TRUE,
+      ));
     }
     return $this->cache;
   }
index ef4afa27d06cd4719bb61b3227169478c206cfc9..5caa450dbec167a5aad48759f1c59d2c1eb06396 100644 (file)
@@ -162,4 +162,43 @@ class CRM_Utils_Cache {
     return $defaults;
   }
 
+  /**
+   * Create a new, named, limited-use cache.
+   *
+   * This is a factory function. Generally, you should use Civi::cache($name)
+   * to locate managed cached instance.
+   *
+   * @param array $params
+   *   Array with keys:
+   *   - name: string, unique symbolic name.
+   *   - type: array|string, list of acceptable cache types, in order of preference.
+   *   - prefetch: bool, whether to prefetch all data in cache (if possible).
+   * @return CRM_Utils_Cache_Interface
+   * @throws CRM_Core_Exception
+   * @see Civi::cache()
+   */
+  public static function create($params = array()) {
+    $types = (array) $params['type'];
+
+    foreach ($types as $type) {
+      switch ($type) {
+        case 'SqlGroup':
+          if (defined('CIVICRM_DSN') && CIVICRM_DSN) {
+            return new CRM_Utils_Cache_SqlGroup(array(
+              'group' => $params['name'],
+              'prefetch' => CRM_Utils_Array::value('prefetch', $params, FALSE),
+            ));
+          }
+          break;
+
+        case 'Arraycache':
+        case 'ArrayCache':
+          return new CRM_Utils_Cache_ArrayCache(array());
+
+      }
+    }
+
+    throw new CRM_Core_Exception("Failed to instantiate cache. No supported cache type found. " . print_r($params, 1));
+  }
+
 }
index d281b06eaae6d769d083149e2f3b8824212fc3a9..e1d0132e02c4f486496910c3d618590598151fd1 100644 (file)
@@ -174,12 +174,17 @@ class Container {
 
     $container->setDefinition('psr_log', new Definition('CRM_Core_Error_Log', array()));
 
-    $container->setDefinition('cache.settings', new Definition(
-      'CRM_Utils_Cache_SqlGroup',
-      array(
-        array('group' => 'Settings', 'prefetch' => 0),
-      )
-    ));
+    foreach (array('settings', 'js_strings', 'community_messages') as $cacheName) {
+      $container->setDefinition("cache.{$cacheName}", new Definition(
+        'CRM_Utils_Cache_Interface',
+        array(
+          array(
+            'name' => $cacheName,
+            'type' => array('SqlGroup', 'ArrayCache'),
+          ),
+        )
+      ))->setFactoryClass('CRM_Utils_Cache')->setFactoryMethod('create');
+    }
 
     $container->setDefinition('settings_manager', new Definition(
       'Civi\Core\SettingsManager',