Merge remote-tracking branch 'upstream/4.3' into 4.3-master-2013-08-28-20-20-34
[civicrm-core.git] / CRM / Core / CommunityMessages.php
index 85062c0b15cffe065ce8cd0f8b8466b175885359..887f4c13f8619dc6b50be68bb8ed0c3aebd20688 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.3                                                |
+ | CiviCRM version 4.4                                                |
  +--------------------------------------------------------------------+
  | Copyright CiviCRM LLC (c) 2004-2013                                |
  +--------------------------------------------------------------------+
@@ -30,6 +30,9 @@
  */
 class CRM_Core_CommunityMessages {
 
+  const DEFAULT_MESSAGES_URL = 'https://alert.civicrm.org/alert?prot=1&ver={ver}&uf={uf}&sid={sid}&lang={lang}&co={co}';
+  const DEFAULT_PERMISSION = 'administer CiviCRM';
+
   /**
    * Default time to wait before retrying
    */
@@ -45,27 +48,50 @@ class CRM_Core_CommunityMessages {
    */
   protected $cache;
 
+  /**
+   * @var FALSE|string
+   */
+  protected $messagesUrl;
+
+  /**
+   * Create default instance
+   *
+   * @return CRM_Core_CommunityMessages
+   */
+  public static function create() {
+    return new CRM_Core_CommunityMessages(
+      new CRM_Utils_Cache_SqlGroup(array(
+        'group' => 'community-messages',
+        'prefetch' => FALSE,
+      )),
+      CRM_Utils_HttpClient::singleton()
+    );
+  }
+
   /**
    * @param CRM_Utils_Cache_Interface $cache
    * @param CRM_Utils_HttpClient $client
    */
-  public function __construct($cache, $client) {
+  public function __construct($cache, $client, $messagesUrl = NULL) {
     $this->cache = $cache;
     $this->client = $client;
+    if ($messagesUrl === NULL) {
+      $this->messagesUrl = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'communityMessagesUrl', NULL, '*default*');
+    }
+    else {
+      $this->messagesUrl = $messagesUrl;
+    }
+    if ($this->messagesUrl === '*default*') {
+      $this->messagesUrl = self::DEFAULT_MESSAGES_URL;
+    }
   }
 
   /**
-   * Get the messages document
+   * Get the messages document (either from the cache or by downloading)
    *
    * @return NULL|array
    */
   public function getDocument() {
-    // FIXME register in settings
-    $url = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'communityMessagesUrl', NULL, TRUE);
-    if (empty($url)) {
-      return NULL;
-    }
-
     $isChanged = FALSE;
     $document = $this->cache->get('communityMessages');
 
@@ -80,11 +106,13 @@ class CRM_Core_CommunityMessages {
     }
 
     if ($document['expires'] <= CRM_Utils_Time::getTimeRaw()) {
-      $newDocument = $this->fetchDocument($url);
-      if ($newDocument) {
+      $newDocument = $this->fetchDocument();
+      if ($newDocument && $this->validateDocument($newDocument)) {
         $document = $newDocument;
         $document['expires'] = CRM_Utils_Time::getTimeRaw() + $document['ttl'];
-      } else {
+      }
+      else {
+        // keep the old messages for now, try again later
         $document['expires'] = CRM_Utils_Time::getTimeRaw() + $document['retry'];
       }
       $isChanged = TRUE;
@@ -100,11 +128,10 @@ class CRM_Core_CommunityMessages {
   /**
    * Download document from URL and parse as JSON
    *
-   * @param string $url
    * @return NULL|array parsed JSON
    */
-  public function fetchDocument($url) {
-    list($status, $json) = $this->client->get(self::evalUrl($url));
+  public function fetchDocument() {
+    list($status, $json) = $this->client->get($this->getRenderedUrl());
     if ($status != CRM_Utils_HttpClient::STATUS_OK || empty($json)) {
       return NULL;
     }
@@ -116,14 +143,52 @@ class CRM_Core_CommunityMessages {
   }
 
   /**
-   * Pick one message
+   * Get the final, usable URL string (after interpolating any variables)
+   *
+   * @return FALSE|string
+   */
+  public function getRenderedUrl() {
+    return CRM_Utils_System::evalUrl($this->messagesUrl);
+  }
+
+  /**
+   * @return bool
+   */
+  public function isEnabled() {
+    return $this->messagesUrl !== FALSE && $this->messagesUrl !== 'FALSE';
+  }
+
+  /**
+   * Pick a message to display
    *
-   * @param callable $permChecker
-   * @param array $components
    * @return NULL|array
    */
-  public function pick($permChecker, $components) {
-    throw new Exception('not implemented');
+  public function pick() {
+    $document = $this->getDocument();
+    $messages = array();
+    foreach ($document['messages'] as $message) {
+      if (!isset($message['perms'])) {
+        $message['perms'] = array(self::DEFAULT_PERMISSION);
+      }
+      if (!CRM_Core_Permission::checkAnyPerm($message['perms'])) {
+        continue;
+      }
+
+      if (isset($message['components'])) {
+        $enabled = array_keys(CRM_Core_Component::getEnabledComponents());
+        if (count(array_intersect($enabled, $message['components'])) == 0) {
+          continue;
+        }
+      }
+
+      $messages[] = $message;
+    }
+    if (empty($messages)) {
+      return NULL;
+    }
+
+    $idx = rand(0, count($messages) - 1);
+    return $messages[$idx];
   }
 
   /**
@@ -131,14 +196,46 @@ class CRM_Core_CommunityMessages {
    * @return string
    */
   public static function evalMarkup($markup) {
-    throw new Exception('not implemented');
+    $config = CRM_Core_Config::singleton();
+    $vals = array(
+      'resourceUrl' => rtrim($config->resourceBase, '/'),
+      'ver' => CRM_Utils_System::version(),
+      'uf' => $config->userFramework,
+      'php' => phpversion(),
+      'sid' => md5('sid_' . (defined('CIVICRM_SITE_KEY') ? CIVICRM_SITE_KEY : '') . '_' . $config->userFrameworkBaseURL),
+      'baseUrl' => $config->userFrameworkBaseURL,
+      'lang' => $config->lcMessages,
+      'co' => $config->defaultContactCountry,
+    );
+    $vars = array();
+    foreach ($vals as $k => $v) {
+      $vars['%%' . $k . '%%'] = $v;
+      $vars['{{' . $k . '}}'] = urlencode($v);
+    }
+    return strtr($markup, $vars);
   }
 
   /**
-   * @param string $markup
-   * @return string
+   * Ensure that a document is well-formed
+   *
+   * @param array $document
+   * @return bool
    */
-  public static function evalUrl($url) {
-    return $url; // FIXME
+  public function validateDocument($document) {
+    if (!isset($document['ttl']) || !is_integer($document['ttl'])) {
+      return FALSE;
+    }
+    if (!isset($document['retry']) || !is_integer($document['retry'])) {
+      return FALSE;
+    }
+    if (!isset($document['messages']) || !is_array($document['messages'])) {
+      return FALSE;
+    }
+    foreach ($document['messages'] as $message) {
+      // TODO validate $message['markup']
+    }
+
+    return TRUE;
   }
+
 }