'community-messages', 'prefetch' => FALSE, )), CRM_Utils_HttpClient::singleton() ); } /** * @param CRM_Utils_Cache_Interface $cache * @param CRM_Utils_HttpClient $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 (either from the cache or by downloading) * * @return NULL|array */ public function getDocument() { $isChanged = FALSE; $document = $this->cache->get('communityMessages'); if (empty($document) || !is_array($document)) { $document = array( 'messages' => array(), 'expires' => 0, // ASAP 'ttl' => self::DEFAULT_RETRY, 'retry' => self::DEFAULT_RETRY, ); $isChanged = TRUE; } if ($document['expires'] <= CRM_Utils_Time::getTimeRaw()) { $newDocument = $this->fetchDocument(); if ($newDocument && $this->validateDocument($newDocument)) { $document = $newDocument; $document['expires'] = CRM_Utils_Time::getTimeRaw() + $document['ttl']; } else { // keep the old messages for now, try again later $document['expires'] = CRM_Utils_Time::getTimeRaw() + $document['retry']; } $isChanged = TRUE; } if ($isChanged) { $this->cache->set('communityMessages', $document); } return $document; } /** * Download document from URL and parse as JSON * * @return NULL|array parsed JSON */ public function fetchDocument() { list($status, $json) = $this->client->get($this->getRenderedUrl()); if ($status != CRM_Utils_HttpClient::STATUS_OK || empty($json)) { return NULL; } $doc = json_decode($json, TRUE); if (empty($doc) || json_last_error() != JSON_ERROR_NONE) { return NULL; } return $doc; } /** * 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 * * @return NULL|array */ 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]; } /** * @param string $markup * @return string */ public static function evalMarkup($markup) { $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); } /** * Ensure that a document is well-formed * * @param array $document * @return bool */ 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; } }