X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FCore%2FRegion.php;h=4d9f733068c67003c28ad68cd6345be2b37c3d3e;hb=26ad621a0eb1aa1757755684d45cb162f6284985;hp=06cece6bc9e7fd08e0da124e6e16fb39b945f710;hpb=4b2791fae8e445392bc410b81d909e416226f30a;p=civicrm-core.git diff --git a/CRM/Core/Region.php b/CRM/Core/Region.php index 06cece6bc9..4d9f733068 100644 --- a/CRM/Core/Region.php +++ b/CRM/Core/Region.php @@ -3,8 +3,7 @@ /** * Maintain a set of markup/templates to inject inside various regions */ -class CRM_Core_Region { - static private $_instances = NULL; +class CRM_Core_Region implements CRM_Core_Resources_CollectionInterface, CRM_Core_Resources_CollectionAdderInterface { /** * Obtain the content for a given region. @@ -15,12 +14,14 @@ class CRM_Core_Region { * @return CRM_Core_Region */ public static function &instance($name, $autocreate = TRUE) { - if ($autocreate && !isset(self::$_instances[$name])) { - self::$_instances[$name] = new CRM_Core_Region($name); + if ($autocreate && !isset(Civi::$statics[__CLASS__][$name])) { + Civi::$statics[__CLASS__][$name] = new CRM_Core_Region($name); } - return self::$_instances[$name]; + return Civi::$statics[__CLASS__][$name]; } + use CRM_Core_Resources_CollectionTrait; + /** * Symbolic name of this region * @@ -28,28 +29,13 @@ class CRM_Core_Region { */ public $_name; - /** - * List of snippets to inject within region. - * - * e.g. $this->_snippets[3]['type'] = 'template'; - * - * @var array - */ - public $_snippets; - - /** - * Whether the snippets array has been sorted - * - * @var bool - */ - public $_isSorted; - /** * @param string $name */ public function __construct($name) { $this->_name = $name; - $this->_snippets = []; + $this->types = ['markup', 'template', 'callback', 'scriptFile', 'scriptUrl', 'script', 'jquery', 'settings', 'style', 'styleFile', 'styleUrl']; + $this->defaults['region'] = $name; // Placeholder which represents any of the default content generated by the main Smarty template $this->add([ @@ -58,92 +44,6 @@ class CRM_Core_Region { 'markup' => '', 'weight' => 0, ]); - $this->_isSorted = TRUE; - } - - /** - * Add a snippet of content to a region. - * - * ``` - * CRM_Core_Region::instance('page-header')->add(array( - * 'markup' => '
Hello!
', - * )); - * CRM_Core_Region::instance('page-header')->add(array( - * 'script' => 'alert("Hello");', - * )); - * CRM_Core_Region::instance('page-header')->add(array( - * 'template' => 'CRM/Myextension/Extra.tpl', - * )); - * CRM_Core_Region::instance('page-header')->add(array( - * 'callback' => 'myextension_callback_function', - * )); - * ``` - * - * Note: This function does not perform any extra encoding of markup, script code, or etc. If - * you're passing in user-data, you must clean it yourself. - * - * @param array $snippet - * Array; keys:. - * - type: string (auto-detected for markup, template, callback, script, scriptUrl, jquery, style, styleUrl) - * - name: string, optional - * - weight: int, optional; default=1 - * - disabled: int, optional; default=0 - * - markup: string, HTML; required (for type==markup) - * - template: string, path; required (for type==template) - * - callback: mixed; required (for type==callback) - * - arguments: array, optional (for type==callback) - * - script: string, Javascript code - * - scriptUrl: string, URL of a Javascript file - * - jquery: string, Javascript code which runs inside a jQuery(function($){...}); block - * - style: string, CSS code - * - styleUrl: string, URL of a CSS file - * - * @return array - */ - public function add($snippet) { - static $types = ['markup', 'template', 'callback', 'scriptUrl', 'script', 'jquery', 'style', 'styleUrl']; - $defaults = [ - 'region' => $this->_name, - 'weight' => 1, - 'disabled' => FALSE, - ]; - $snippet += $defaults; - if (!isset($snippet['type'])) { - foreach ($types as $type) { - // auto-detect - if (isset($snippet[$type])) { - $snippet['type'] = $type; - break; - } - } - } - if (!isset($snippet['name'])) { - $snippet['name'] = count($this->_snippets); - } - - $this->_snippets[$snippet['name']] = $snippet; - $this->_isSorted = FALSE; - return $snippet; - } - - /** - * @param string $name - * @param $snippet - */ - public function update($name, $snippet) { - $this->_snippets[$name] = array_merge($this->_snippets[$name], $snippet); - $this->_isSorted = FALSE; - } - - /** - * Get snippet. - * - * @param string $name - * - * @return mixed - */ - public function get($name) { - return !empty($this->_snippets[$name]) ? $this->_snippets[$name] : NULL; } /** @@ -157,23 +57,19 @@ class CRM_Core_Region { */ public function render($default, $allowCmsOverride = TRUE) { // $default is just another part of the region - if (is_array($this->_snippets['default'])) { - $this->_snippets['default']['markup'] = $default; + if (is_array($this->snippets['default'])) { + $this->snippets['default']['markup'] = $default; } - // We hand as much of the work off to the CMS as possible - $cms = CRM_Core_Config::singleton()->userSystem; - if (!$this->_isSorted) { - uasort($this->_snippets, ['CRM_Core_Region', '_cmpSnippet']); - $this->_isSorted = TRUE; - } + Civi::dispatcher()->dispatch('civi.region.render', \Civi\Core\Event\GenericHookEvent::create(['region' => $this])); + $this->sort(); + + $cms = CRM_Core_Config::singleton()->userSystem; $smarty = CRM_Core_Smarty::singleton(); $html = ''; - foreach ($this->_snippets as $snippet) { - if ($snippet['disabled']) { - continue; - } + + $renderSnippet = function($snippet) use (&$html, $smarty, $cms, $allowCmsOverride, &$renderSnippet) { switch ($snippet['type']) { case 'markup': $html .= $snippet['markup']; @@ -198,14 +94,30 @@ class CRM_Core_Region { break; case 'jquery': - $snippet['script'] = sprintf("CRM.\$(function(\$) {\n%s\n});", $snippet['jquery']); - // no break - continue processing as script + $renderSnippet([ + 'type' => 'script', + 'script' => sprintf("CRM.\$(function(\$) {\n%s\n});", $snippet['jquery']), + ]); + break; + + case 'scriptFile': + foreach ($snippet['scriptFileUrls'] as $url) { + $html .= $renderSnippet(['type' => 'scriptUrl', 'scriptUrl' => $url] + $snippet); + } + break; + case 'script': if (!$allowCmsOverride || !$cms->addScript($snippet['script'], $this->_name)) { $html .= sprintf("\n", $snippet['script']); } break; + case 'styleFile': + foreach ($snippet['styleFileUrls'] as $url) { + $html .= $renderSnippet(['type' => 'styleUrl', 'styleUrl' => $url] + $snippet); + } + break; + case 'styleUrl': if (!$allowCmsOverride || !$cms->addStyleUrl($snippet['styleUrl'], $this->_name)) { $html .= sprintf("\n", $snippet['styleUrl']); @@ -218,35 +130,26 @@ class CRM_Core_Region { } break; + case 'settings': + $settingsData = json_encode($this->getSettings(), JSON_UNESCAPED_SLASHES); + $js = "(function(vars) { + if (window.CRM) CRM.$.extend(true, CRM, vars); else window.CRM = vars; + })($settingsData)"; + $html .= sprintf("\n", $js); + break; + default: throw new CRM_Core_Exception(ts('Snippet type %1 is unrecognized', [1 => $snippet['type']])); } - } - return $html; - } + }; - /** - * @param $a - * @param $b - * - * @return int - */ - public static function _cmpSnippet($a, $b) { - if ($a['weight'] < $b['weight']) { - return -1; - } - if ($a['weight'] > $b['weight']) { - return 1; - } - // fallback to name sort; don't really want to do this, but it makes results more stable - if ($a['name'] < $b['name']) { - return -1; - } - if ($a['name'] > $b['name']) { - return 1; + foreach ($this->snippets as $snippet) { + if (empty($snippet['disabled'])) { + $renderSnippet($snippet); + } } - return 0; + return $html; } }