AngularLoader - Support multiple angularjs apps running on the page
[civicrm-core.git] / CRM / Core / Region.php
1 <?php
2
3 /**
4 * Maintain a set of markup/templates to inject inside various regions
5 */
6 class CRM_Core_Region implements CRM_Core_Resources_CollectionInterface, CRM_Core_Resources_CollectionAdderInterface {
7
8 /**
9 * Obtain the content for a given region.
10 *
11 * @param string $name
12 * @param bool $autocreate
13 * Whether to automatically create an empty region.
14 * @return CRM_Core_Region
15 */
16 public static function &instance($name, $autocreate = TRUE) {
17 if ($autocreate && !isset(Civi::$statics[__CLASS__][$name])) {
18 Civi::$statics[__CLASS__][$name] = new CRM_Core_Region($name);
19 }
20 return Civi::$statics[__CLASS__][$name];
21 }
22
23 use CRM_Core_Resources_CollectionTrait;
24
25 /**
26 * Symbolic name of this region
27 *
28 * @var string
29 */
30 public $_name;
31
32 /**
33 * @param string $name
34 */
35 public function __construct($name) {
36 $this->_name = $name;
37 $this->types = ['markup', 'template', 'callback', 'scriptFile', 'scriptUrl', 'script', 'jquery', 'settings', 'style', 'styleFile', 'styleUrl'];
38 $this->defaults['region'] = $name;
39
40 // Placeholder which represents any of the default content generated by the main Smarty template
41 $this->add([
42 'name' => 'default',
43 'type' => 'markup',
44 'markup' => '',
45 'weight' => 0,
46 ]);
47 }
48
49 /**
50 * Render all the snippets in a region.
51 *
52 * @param string $default
53 * HTML, the initial content of the region.
54 * @param bool $allowCmsOverride
55 * Allow CMS to override rendering of region.
56 * @return string, HTML
57 */
58 public function render($default, $allowCmsOverride = TRUE) {
59 // $default is just another part of the region
60 if (is_array($this->snippets['default'])) {
61 $this->snippets['default']['markup'] = $default;
62 }
63
64 $this->sort();
65
66 $cms = CRM_Core_Config::singleton()->userSystem;
67 $smarty = CRM_Core_Smarty::singleton();
68 $html = '';
69
70 $renderSnippet = function($snippet) use (&$html, $smarty, $cms, $allowCmsOverride, &$renderSnippet) {
71 switch ($snippet['type']) {
72 case 'markup':
73 $html .= $snippet['markup'];
74 break;
75
76 case 'template':
77 $tmp = $smarty->get_template_vars('snippet');
78 $smarty->assign('snippet', $snippet);
79 $html .= $smarty->fetch($snippet['template']);
80 $smarty->assign('snippet', $tmp);
81 break;
82
83 case 'callback':
84 $args = $snippet['arguments'] ?? array(&$snippet, &$html);
85 $html .= call_user_func_array($snippet['callback'], $args);
86 break;
87
88 case 'scriptUrl':
89 if (!$allowCmsOverride || !$cms->addScriptUrl($snippet['scriptUrl'], $this->_name)) {
90 $html .= sprintf("<script type=\"text/javascript\" src=\"%s\">\n</script>\n", $snippet['scriptUrl']);
91 }
92 break;
93
94 case 'jquery':
95 $renderSnippet([
96 'type' => 'script',
97 'script' => sprintf("CRM.\$(function(\$) {\n%s\n});", $snippet['jquery']),
98 ]);
99 break;
100
101 case 'scriptFile':
102 foreach ($snippet['scriptFileUrls'] as $url) {
103 $html .= $renderSnippet(['type' => 'scriptUrl', 'scriptUrl' => $url] + $snippet);
104 }
105 break;
106
107 case 'script':
108 if (!$allowCmsOverride || !$cms->addScript($snippet['script'], $this->_name)) {
109 $html .= sprintf("<script type=\"text/javascript\">\n%s\n</script>\n", $snippet['script']);
110 }
111 break;
112
113 case 'styleFile':
114 foreach ($snippet['styleFileUrls'] as $url) {
115 $html .= $renderSnippet(['type' => 'styleUrl', 'styleUrl' => $url] + $snippet);
116 }
117 break;
118
119 case 'styleUrl':
120 if (!$allowCmsOverride || !$cms->addStyleUrl($snippet['styleUrl'], $this->_name)) {
121 $html .= sprintf("<link href=\"%s\" rel=\"stylesheet\" type=\"text/css\"/>\n", $snippet['styleUrl']);
122 }
123 break;
124
125 case 'style':
126 if (!$allowCmsOverride || !$cms->addStyle($snippet['style'], $this->_name)) {
127 $html .= sprintf("<style type=\"text/css\">\n%s\n</style>\n", $snippet['style']);
128 }
129 break;
130
131 case 'settings':
132 $settingsData = json_encode($this->getSettings(), JSON_UNESCAPED_SLASHES);
133 $js = "(function(vars) {
134 if (window.CRM) CRM.$.extend(true, CRM, vars); else window.CRM = vars;
135 })($settingsData)";
136 $html .= sprintf("<script type=\"text/javascript\">\n%s\n</script>\n", $js);
137 break;
138
139 default:
140 throw new CRM_Core_Exception(ts('Snippet type %1 is unrecognized',
141 [1 => $snippet['type']]));
142 }
143 };
144
145 Civi::dispatcher()->dispatch('civi.region.render', \Civi\Core\Event\GenericHookEvent::create(['region' => $this]));
146 foreach ($this->snippets as $snippet) {
147 if (empty($snippet['disabled'])) {
148 $renderSnippet($snippet);
149 }
150 }
151 return $html;
152 }
153
154 }