Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
bc77d7c0 TO |
3 | +--------------------------------------------------------------------+ |
4 | | Copyright CiviCRM LLC. All rights reserved. | | |
5 | | | | |
6 | | This work is published under the GNU AGPLv3 license with some | | |
7 | | permitted exceptions and without any warranty. For full license | | |
8 | | and copyright information, see https://civicrm.org/licensing | | |
9 | +--------------------------------------------------------------------+ | |
e70a7fc0 | 10 | */ |
1889d803 | 11 | use Civi\Core\Event\GenericHookEvent; |
6a488035 TO |
12 | |
13 | /** | |
14 | * This class facilitates the loading of resources | |
15 | * such as JavaScript files and CSS files. | |
16 | * | |
17 | * Any URLs generated for resources may include a 'cache-code'. By resetting the | |
18 | * cache-code, one may force clients to re-download resource files (regardless of | |
19 | * any HTTP caching rules). | |
20 | * | |
21 | * TODO: This is currently a thin wrapper over CRM_Core_Region. We | |
22 | * should incorporte services for aggregation, minimization, etc. | |
23 | * | |
24 | * @package CRM | |
ca5cec67 | 25 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 | 26 | */ |
e9d08c6b | 27 | class CRM_Core_Resources implements CRM_Core_Resources_CollectionAdderInterface { |
6a488035 TO |
28 | const DEFAULT_WEIGHT = 0; |
29 | const DEFAULT_REGION = 'page-footer'; | |
30 | ||
e9d08c6b TO |
31 | use CRM_Core_Resources_CollectionAdderTrait; |
32 | ||
6a488035 TO |
33 | /** |
34 | * We don't have a container or dependency-injection, so use singleton instead | |
35 | * | |
36 | * @var object | |
6a488035 TO |
37 | */ |
38 | private static $_singleton = NULL; | |
39 | ||
40 | /** | |
41 | * @var CRM_Extension_Mapper | |
42 | */ | |
43 | private $extMapper = NULL; | |
44 | ||
45 | /** | |
fd7dc3f3 | 46 | * @var CRM_Core_Resources_Strings |
6a488035 | 47 | */ |
fd7dc3f3 | 48 | private $strings = NULL; |
6a488035 | 49 | |
fcf926ad TO |
50 | /** |
51 | * Any bundles that have been added. | |
52 | * | |
53 | * Format is ($bundleName => bool). | |
54 | * | |
55 | * @var array | |
56 | */ | |
57 | protected $addedBundles = []; | |
58 | ||
6a488035 | 59 | /** |
e97c66ff | 60 | * Added core resources. |
61 | * | |
62 | * Format is ($regionName => bool). | |
63 | * | |
64 | * @var array | |
6a488035 | 65 | */ |
be2fb01f | 66 | protected $addedCoreResources = []; |
6a488035 | 67 | |
2b2878a9 MW |
68 | /** |
69 | * Added settings. | |
70 | * | |
71 | * Format is ($regionName => bool). | |
72 | * | |
73 | * @var array | |
74 | */ | |
75 | protected $addedSettings = []; | |
76 | ||
6a488035 | 77 | /** |
e97c66ff | 78 | * A value to append to JS/CSS URLs to coerce cache resets. |
79 | * | |
80 | * @var string | |
6a488035 TO |
81 | */ |
82 | protected $cacheCode = NULL; | |
83 | ||
84 | /** | |
e97c66ff | 85 | * The name of a setting which persistently stores the cacheCode. |
86 | * | |
87 | * @var string | |
6a488035 TO |
88 | */ |
89 | protected $cacheCodeKey = NULL; | |
90 | ||
53f2643c | 91 | /** |
e97c66ff | 92 | * Are ajax popup screens enabled. |
93 | * | |
53f2643c CW |
94 | * @var bool |
95 | */ | |
96 | public $ajaxPopupsEnabled; | |
97 | ||
b698e2d5 TO |
98 | /** |
99 | * @var \Civi\Core\Paths | |
100 | */ | |
101 | protected $paths; | |
102 | ||
6a488035 | 103 | /** |
fe482240 | 104 | * Get or set the single instance of CRM_Core_Resources. |
6a488035 | 105 | * |
5a4f6742 CW |
106 | * @param CRM_Core_Resources $instance |
107 | * New copy of the manager. | |
e97c66ff | 108 | * |
6a488035 TO |
109 | * @return CRM_Core_Resources |
110 | */ | |
518fa0ee | 111 | public static function singleton(CRM_Core_Resources $instance = NULL) { |
6a488035 TO |
112 | if ($instance !== NULL) { |
113 | self::$_singleton = $instance; | |
114 | } | |
115 | if (self::$_singleton === NULL) { | |
223ba025 | 116 | self::$_singleton = Civi::service('resources'); |
6a488035 TO |
117 | } |
118 | return self::$_singleton; | |
119 | } | |
120 | ||
121 | /** | |
d09edf64 | 122 | * Construct a resource manager. |
6a488035 | 123 | * |
6a0b768e TO |
124 | * @param CRM_Extension_Mapper $extMapper |
125 | * Map extension names to their base path or URLs. | |
bbcf0f46 | 126 | * @param CRM_Core_Resources_Strings $strings |
6a0b768e | 127 | * JS-localization cache. |
3be754d6 | 128 | * @param string|null $cacheCodeKey Random code to append to resource URLs; changing the code forces clients to reload resources |
6a488035 | 129 | */ |
bbcf0f46 | 130 | public function __construct($extMapper, $strings, $cacheCodeKey = NULL) { |
6a488035 | 131 | $this->extMapper = $extMapper; |
bbcf0f46 | 132 | $this->strings = $strings; |
6a488035 TO |
133 | $this->cacheCodeKey = $cacheCodeKey; |
134 | if ($cacheCodeKey !== NULL) { | |
aaffa79f | 135 | $this->cacheCode = Civi::settings()->get($cacheCodeKey); |
6a488035 | 136 | } |
150f50c1 | 137 | if (!$this->cacheCode) { |
6a488035 TO |
138 | $this->resetCacheCode(); |
139 | } | |
84fb7424 | 140 | $this->ajaxPopupsEnabled = (bool) Civi::settings()->get('ajaxPopupsEnabled'); |
b698e2d5 | 141 | $this->paths = Civi::paths(); |
6a488035 TO |
142 | } |
143 | ||
e9d08c6b TO |
144 | /** |
145 | * Add an item to the collection. | |
146 | * | |
147 | * @param array $snippet | |
148 | * @return array | |
149 | * The full/computed snippet (with defaults applied). | |
150 | * @see CRM_Core_Resources_CollectionInterface::add() | |
151 | */ | |
152 | public function add($snippet) { | |
153 | if (!isset($snippet['region'])) { | |
154 | $snippet['region'] = self::DEFAULT_REGION; | |
155 | } | |
156 | if (!isset($snippet['weight'])) { | |
157 | $snippet['weight'] = self::DEFAULT_WEIGHT; | |
158 | } | |
159 | return CRM_Core_Region::instance($snippet['region'])->add($snippet); | |
160 | } | |
161 | ||
162 | /** | |
163 | * Locate the 'settings' snippet. | |
164 | * | |
165 | * @param array $options | |
166 | * @return array | |
167 | * @see CRM_Core_Resources_CollectionTrait::findCreateSettingSnippet() | |
168 | */ | |
169 | public function &findCreateSettingSnippet($options = []): array { | |
170 | $options = CRM_Core_Resources_CollectionAdderTrait::mergeSettingOptions($options, [ | |
171 | 'region' => NULL, | |
172 | ]); | |
173 | return $this->getSettingRegion($options['region'])->findCreateSettingSnippet($options); | |
174 | } | |
175 | ||
fcf926ad TO |
176 | /** |
177 | * Assimilate all the resources listed in a bundle. | |
178 | * | |
179 | * @param iterable|string|\CRM_Core_Resources_Bundle $bundle | |
19d42be6 | 180 | * Either bundle object, or the symbolic name of a bundle, or a list of bundles. |
fcf926ad TO |
181 | * Note: For symbolic names, the bundle must be a container service ('bundle.FOO'). |
182 | * @return static | |
183 | */ | |
184 | public function addBundle($bundle) { | |
19d42be6 TO |
185 | // There are two ways you might write this method: (1) immediately merge |
186 | // resources from the bundle, or (2) store a reference to the bundle and | |
187 | // merge resources later. Both have pros/cons. The implementation does #1. | |
188 | // | |
189 | // The upshot of #1 is *multi-region* support. For example, a bundle might | |
190 | // add some JS to `html-header` and then add some HTML to `page-header`. | |
191 | // Implementing this requires splitting the bundle (ie copying specific | |
192 | // resources to their respective regions). The timing of `addBundle()` is | |
193 | // favorable to splitting. | |
194 | // | |
195 | // The upshot of #2 would be *reduced timing sensitivity for downstream*: | |
196 | // if party A wants to include some bundle, and party B wants to refine | |
197 | // the same bundle, then it wouldn't matter if A or B executed first. | |
198 | // This should make DX generally more forgiving. But we can't split until | |
199 | // everyone has their shot at tweaking the bundle. | |
200 | // | |
201 | // In theory, you could have both characteristics if you figure the right | |
202 | // time at which to perform a split. Or maybe you could have both by tracking | |
203 | // more detailed references+events among the bundles/regions. I haven't | |
204 | // seen a simple way to do get both. | |
205 | ||
fcf926ad TO |
206 | if (is_iterable($bundle)) { |
207 | foreach ($bundle as $b) { | |
208 | $this->addBundle($b); | |
fcf926ad | 209 | } |
87edc8d2 | 210 | return $this; |
fcf926ad TO |
211 | } |
212 | ||
213 | if (is_string($bundle)) { | |
214 | $bundle = Civi::service('bundle.' . $bundle); | |
215 | } | |
216 | ||
217 | if (isset($this->addedBundles[$bundle->name])) { | |
218 | return $this; | |
219 | } | |
220 | $this->addedBundles[$bundle->name] = TRUE; | |
221 | ||
0aded46e TO |
222 | // Ensure that every asset has a region. |
223 | $bundle->filter(function($snippet) { | |
224 | if (empty($snippet['region'])) { | |
225 | $snippet['region'] = isset($snippet['settings']) | |
226 | ? $this->getSettingRegion()->_name | |
227 | : self::DEFAULT_REGION; | |
fcf926ad | 228 | } |
0aded46e TO |
229 | return $snippet; |
230 | }); | |
fcf926ad | 231 | |
0aded46e | 232 | $byRegion = CRM_Utils_Array::index(['region', 'name'], $bundle->getAll()); |
fcf926ad TO |
233 | foreach ($byRegion as $regionName => $snippets) { |
234 | CRM_Core_Region::instance($regionName)->merge($snippets); | |
235 | } | |
236 | return $this; | |
237 | } | |
238 | ||
69847402 | 239 | /** |
d09edf64 | 240 | * Helper fn for addSettingsFactory. |
6a488035 | 241 | */ |
63918d37 TO |
242 | public function getSettings($region = NULL) { |
243 | return $this->getSettingRegion($region)->getSettings(); | |
6a488035 TO |
244 | } |
245 | ||
6a488035 | 246 | /** |
d09edf64 | 247 | * Determine file path of a resource provided by an extension. |
6a488035 | 248 | * |
5a4f6742 CW |
249 | * @param string $ext |
250 | * extension name; use 'civicrm' for core. | |
e97c66ff | 251 | * @param string|null $file |
5a4f6742 | 252 | * file path -- relative to the extension base dir. |
6a488035 | 253 | * |
72b3a70c CW |
254 | * @return bool|string |
255 | * full file path or FALSE if not found | |
6a488035 | 256 | */ |
16cd1eca | 257 | public function getPath($ext, $file = NULL) { |
6a488035 | 258 | // TODO consider caching results |
b698e2d5 TO |
259 | $base = $this->paths->hasVariable($ext) |
260 | ? rtrim($this->paths->getVariable($ext, 'path'), '/') | |
261 | : $this->extMapper->keyToBasePath($ext); | |
16cd1eca | 262 | if ($file === NULL) { |
b698e2d5 | 263 | return $base; |
16cd1eca | 264 | } |
b698e2d5 | 265 | $path = $base . '/' . $file; |
6a488035 TO |
266 | if (is_file($path)) { |
267 | return $path; | |
268 | } | |
269 | return FALSE; | |
270 | } | |
271 | ||
272 | /** | |
d09edf64 | 273 | * Determine public URL of a resource provided by an extension. |
6a488035 | 274 | * |
5a4f6742 CW |
275 | * @param string $ext |
276 | * extension name; use 'civicrm' for core. | |
277 | * @param string $file | |
278 | * file path -- relative to the extension base dir. | |
2a6da8d7 EM |
279 | * @param bool $addCacheCode |
280 | * | |
6a488035 TO |
281 | * @return string, URL |
282 | */ | |
283 | public function getUrl($ext, $file = NULL, $addCacheCode = FALSE) { | |
284 | if ($file === NULL) { | |
285 | $file = ''; | |
286 | } | |
287 | if ($addCacheCode) { | |
6f12c6eb | 288 | $file = $this->addCacheCode($file); |
6a488035 TO |
289 | } |
290 | // TODO consider caching results | |
b698e2d5 TO |
291 | $base = $this->paths->hasVariable($ext) |
292 | ? $this->paths->getVariable($ext, 'url') | |
293 | : ($this->extMapper->keyToUrl($ext) . '/'); | |
294 | return $base . $file; | |
6a488035 TO |
295 | } |
296 | ||
16cd1eca TO |
297 | /** |
298 | * Evaluate a glob pattern in the context of a particular extension. | |
299 | * | |
300 | * @param string $ext | |
301 | * Extension name; use 'civicrm' for core. | |
302 | * @param string|array $patterns | |
303 | * Glob pattern; e.g. "*.html". | |
304 | * @param null|int $flags | |
305 | * See glob(). | |
306 | * @return array | |
307 | * List of matching files, relative to the extension base dir. | |
308 | * @see glob() | |
309 | */ | |
310 | public function glob($ext, $patterns, $flags = NULL) { | |
311 | $path = $this->getPath($ext); | |
312 | $patterns = (array) $patterns; | |
be2fb01f | 313 | $files = []; |
16cd1eca | 314 | foreach ($patterns as $pattern) { |
e5c376e7 TO |
315 | if (preg_match(';^(assetBuilder|ext)://;', $pattern)) { |
316 | $files[] = $pattern; | |
317 | } | |
9f87b14b | 318 | if (CRM_Utils_File::isAbsolute($pattern)) { |
16cd1eca TO |
319 | // Absolute path. |
320 | $files = array_merge($files, (array) glob($pattern, $flags)); | |
321 | } | |
322 | else { | |
323 | // Relative path. | |
324 | $files = array_merge($files, (array) glob("$path/$pattern", $flags)); | |
325 | } | |
326 | } | |
518fa0ee SL |
327 | // Deterministic order. |
328 | sort($files); | |
16cd1eca TO |
329 | $files = array_unique($files); |
330 | return array_map(function ($file) use ($path) { | |
331 | return CRM_Utils_File::relativize($file, "$path/"); | |
332 | }, $files); | |
333 | } | |
334 | ||
a0ee3941 EM |
335 | /** |
336 | * @return string | |
337 | */ | |
6a488035 TO |
338 | public function getCacheCode() { |
339 | return $this->cacheCode; | |
340 | } | |
341 | ||
a0ee3941 EM |
342 | /** |
343 | * @param $value | |
5badddc3 | 344 | * @return CRM_Core_Resources |
a0ee3941 | 345 | */ |
6a488035 TO |
346 | public function setCacheCode($value) { |
347 | $this->cacheCode = $value; | |
348 | if ($this->cacheCodeKey) { | |
08ef4ddd | 349 | Civi::settings()->set($this->cacheCodeKey, $value); |
6a488035 | 350 | } |
9762f6ff | 351 | return $this; |
6a488035 TO |
352 | } |
353 | ||
5badddc3 CW |
354 | /** |
355 | * @return CRM_Core_Resources | |
356 | */ | |
6a488035 TO |
357 | public function resetCacheCode() { |
358 | $this->setCacheCode(CRM_Utils_String::createRandom(5, CRM_Utils_String::ALPHANUMERIC)); | |
f091327b CW |
359 | // Also flush cms resource cache if needed |
360 | CRM_Core_Config::singleton()->userSystem->clearResourceCache(); | |
9762f6ff | 361 | return $this; |
6a488035 TO |
362 | } |
363 | ||
364 | /** | |
365 | * This adds CiviCRM's standard css and js to the specified region of the document. | |
366 | * It will only run once. | |
367 | * | |
2a6da8d7 | 368 | * @param string $region |
6a488035 | 369 | * @return CRM_Core_Resources |
6a488035 TO |
370 | */ |
371 | public function addCoreResources($region = 'html-header') { | |
8d2c99cf TO |
372 | if ($region !== 'html-header') { |
373 | // The signature of this method allowed different regions. However, this | |
374 | // doesn't appear to be used - based on grepping `universe` generally | |
375 | // and `civicrm-{core,backdrop,drupal,packages,wordpress,joomla}` specifically, | |
376 | // it appears that all callers use 'html-header' (either implicitly or explicitly). | |
377 | throw new \CRM_Core_Exception("Error: addCoreResources only supports html-header"); | |
378 | } | |
8d469336 TO |
379 | if (!self::isAjaxMode()) { |
380 | $this->addBundle('coreResources'); | |
6a488035 TO |
381 | $this->addCoreStyles($region); |
382 | } | |
383 | return $this; | |
384 | } | |
385 | ||
386 | /** | |
387 | * This will add CiviCRM's standard CSS | |
388 | * | |
6a488035 TO |
389 | * @param string $region |
390 | * @return CRM_Core_Resources | |
391 | */ | |
392 | public function addCoreStyles($region = 'html-header') { | |
8d2c99cf TO |
393 | if ($region !== 'html-header') { |
394 | // The signature of this method allowed different regions. However, this | |
395 | // doesn't appear to be used - based on grepping `universe` generally | |
396 | // and `civicrm-{core,backdrop,drupal,packages,wordpress,joomla}` specifically, | |
397 | // it appears that all callers use 'html-header' (either implicitly or explicitly). | |
398 | throw new \CRM_Core_Exception("Error: addCoreResources only supports html-header"); | |
399 | } | |
5526ab4d | 400 | $this->addBundle('coreStyles'); |
6a488035 TO |
401 | return $this; |
402 | } | |
403 | ||
627668e8 | 404 | /** |
d09edf64 | 405 | * Flushes cached translated strings. |
5badddc3 | 406 | * @return CRM_Core_Resources |
627668e8 CW |
407 | */ |
408 | public function flushStrings() { | |
fd7dc3f3 | 409 | $this->strings->flush(); |
9762f6ff CW |
410 | return $this; |
411 | } | |
412 | ||
6a488035 | 413 | /** |
fd7dc3f3 TO |
414 | * @return CRM_Core_Resources_Strings |
415 | */ | |
416 | public function getStrings() { | |
417 | return $this->strings; | |
6a488035 TO |
418 | } |
419 | ||
19f7e35e | 420 | /** |
8d7a9d07 | 421 | * Create dynamic script for localizing js widgets. |
19f7e35e | 422 | */ |
00be9182 | 423 | public static function outputLocalizationJS() { |
4cc9b813 | 424 | CRM_Core_Page_AJAX::setJsHeaders(); |
a88cf11a | 425 | $config = CRM_Core_Config::singleton(); |
be2fb01f | 426 | $vars = [ |
3d527838 CW |
427 | 'moneyFormat' => json_encode(CRM_Utils_Money::format(1234.56)), |
428 | 'contactSearch' => json_encode($config->includeEmailInName ? ts('Start typing a name or email...') : ts('Start typing a name...')), | |
429 | 'otherSearch' => json_encode(ts('Enter search term...')), | |
e695ee7c | 430 | 'entityRef' => self::getEntityRefMetadata(), |
7b83e312 | 431 | 'ajaxPopupsEnabled' => self::singleton()->ajaxPopupsEnabled, |
a9fb6123 | 432 | 'allowAlertAutodismissal' => (bool) Civi::settings()->get('allow_alert_autodismissal'), |
c7e39a79 | 433 | 'resourceCacheCode' => self::singleton()->getCacheCode(), |
b30809e4 CW |
434 | 'locale' => CRM_Core_I18n::getLocale(), |
435 | 'cid' => (int) CRM_Core_Session::getLoggedInContactID(), | |
be2fb01f | 436 | ]; |
3d4fb0ed | 437 | print CRM_Core_Smarty::singleton()->fetchWith('CRM/common/l10n.js.tpl', $vars); |
4cc9b813 | 438 | CRM_Utils_System::civiExit(); |
c66581f5 CW |
439 | } |
440 | ||
156fd9b9 | 441 | /** |
a6c01b45 CW |
442 | * @return bool |
443 | * is this page request an ajax snippet? | |
156fd9b9 | 444 | */ |
00be9182 | 445 | public static function isAjaxMode() { |
be2fb01f | 446 | if (in_array(CRM_Utils_Array::value('snippet', $_REQUEST), [ |
518fa0ee SL |
447 | CRM_Core_Smarty::PRINT_SNIPPET, |
448 | CRM_Core_Smarty::PRINT_NOFORM, | |
449 | CRM_Core_Smarty::PRINT_JSON, | |
450 | ]) | |
42a40a1c | 451 | ) { |
452 | return TRUE; | |
453 | } | |
f31f885e | 454 | list($arg0, $arg1) = array_pad(explode('/', CRM_Utils_System::currentPath()), 2, ''); |
60c3b6e9 | 455 | return ($arg0 === 'civicrm' && in_array($arg1, ['ajax', 'angularprofiles', 'asset'])); |
156fd9b9 | 456 | } |
b7ceb253 | 457 | |
1889d803 | 458 | /** |
518fa0ee | 459 | * @param \Civi\Core\Event\GenericHookEvent $e |
1889d803 CW |
460 | * @see \CRM_Utils_Hook::buildAsset() |
461 | */ | |
462 | public static function renderMenubarStylesheet(GenericHookEvent $e) { | |
463 | if ($e->asset !== 'crm-menubar.css') { | |
464 | return; | |
465 | } | |
466 | $e->mimeType = 'text/css'; | |
dcaf410f | 467 | $content = ''; |
1889d803 CW |
468 | $config = CRM_Core_Config::singleton(); |
469 | $cms = strtolower($config->userFramework); | |
470 | $cms = $cms === 'drupal' ? 'drupal7' : $cms; | |
471 | $items = [ | |
472 | 'bower_components/smartmenus/dist/css/sm-core-css.css', | |
473 | 'css/crm-menubar.css', | |
474 | "css/menubar-$cms.css", | |
475 | ]; | |
476 | foreach ($items as $item) { | |
dcaf410f | 477 | $content .= file_get_contents(self::singleton()->getPath('civicrm', $item)); |
8a52ae34 | 478 | } |
dcaf410f CW |
479 | $params = $e->params; |
480 | // "color" is deprecated in favor of the more specific "menubarColor" | |
481 | $menubarColor = $params['color'] ?? $params['menubarColor']; | |
1889d803 | 482 | $vars = [ |
dcaf410f CW |
483 | '$resourceBase' => rtrim($config->resourceBase, '/'), |
484 | '$menubarHeight' => $params['height'] . 'px', | |
485 | '$breakMin' => $params['breakpoint'] . 'px', | |
486 | '$breakMax' => ($params['breakpoint'] - 1) . 'px', | |
487 | '$menubarColor' => $menubarColor, | |
63c2508b | 488 | '$menuItemColor' => $params['menuItemColor'] ?? $menubarColor, |
dcaf410f CW |
489 | '$highlightColor' => $params['highlightColor'] ?? CRM_Utils_Color::getHighlight($menubarColor), |
490 | '$textColor' => $params['textColor'] ?? CRM_Utils_Color::getContrast($menubarColor, '#333', '#ddd'), | |
1889d803 | 491 | ]; |
dcaf410f CW |
492 | $vars['$highlightTextColor'] = $params['highlightTextColor'] ?? CRM_Utils_Color::getContrast($vars['$highlightColor'], '#333', '#ddd'); |
493 | $e->content = str_replace(array_keys($vars), array_values($vars), $content); | |
1889d803 CW |
494 | } |
495 | ||
b7ceb253 | 496 | /** |
f9e31d7f | 497 | * Provide a list of available entityRef filters. |
fd7c068f | 498 | * |
b7ceb253 CW |
499 | * @return array |
500 | */ | |
e695ee7c CW |
501 | public static function getEntityRefMetadata() { |
502 | $data = [ | |
503 | 'filters' => [], | |
504 | 'links' => [], | |
505 | ]; | |
06606cd1 | 506 | $config = CRM_Core_Config::singleton(); |
b7ceb253 | 507 | |
1d6f94ab CW |
508 | $disabledComponents = []; |
509 | $dao = CRM_Core_DAO::executeQuery("SELECT name, namespace FROM civicrm_component"); | |
510 | while ($dao->fetch()) { | |
511 | if (!in_array($dao->name, $config->enableComponents)) { | |
512 | $disabledComponents[$dao->name] = $dao->namespace; | |
06606cd1 CW |
513 | } |
514 | } | |
515 | ||
1d6f94ab CW |
516 | foreach (CRM_Core_DAO_AllCoreTables::daoToClass() as $entity => $daoName) { |
517 | // Skip DAOs of disabled components | |
518 | foreach ($disabledComponents as $nameSpace) { | |
519 | if (strpos($daoName, $nameSpace) === 0) { | |
520 | continue 2; | |
521 | } | |
522 | } | |
523 | $baoName = str_replace('_DAO_', '_BAO_', $daoName); | |
524 | if (class_exists($baoName)) { | |
e695ee7c CW |
525 | $filters = $baoName::getEntityRefFilters(); |
526 | if ($filters) { | |
2229cf4f | 527 | $data['filters'][$entity] = $filters; |
e695ee7c CW |
528 | } |
529 | if (is_callable([$baoName, 'getEntityRefCreateLinks'])) { | |
530 | $createLinks = $baoName::getEntityRefCreateLinks(); | |
531 | if ($createLinks) { | |
2229cf4f | 532 | $data['links'][$entity] = $createLinks; |
e695ee7c | 533 | } |
1d6f94ab CW |
534 | } |
535 | } | |
b7b528bc CW |
536 | } |
537 | ||
77d0bf4e | 538 | CRM_Utils_Hook::entityRefFilters($data['filters'], $data['links']); |
fd7c068f | 539 | |
e695ee7c | 540 | return $data; |
b7ceb253 | 541 | } |
96025800 | 542 | |
09a4dcd5 | 543 | /** |
d89d2545 | 544 | * Determine the minified file name. |
09a4dcd5 | 545 | * |
d89d2545 TO |
546 | * @param string $ext |
547 | * @param string $file | |
548 | * @return string | |
549 | * An updated $fileName. If a minified version exists and is supported by | |
550 | * system policy, the minified version will be returned. Otherwise, the original. | |
551 | */ | |
552 | public function filterMinify($ext, $file) { | |
553 | if (CRM_Core_Config::singleton()->debug && strpos($file, '.min.') !== FALSE) { | |
554 | $nonMiniFile = str_replace('.min.', '.', $file); | |
555 | if ($this->getPath($ext, $nonMiniFile)) { | |
556 | $file = $nonMiniFile; | |
09a4dcd5 CW |
557 | } |
558 | } | |
d89d2545 | 559 | return $file; |
09a4dcd5 CW |
560 | } |
561 | ||
6f12c6eb | 562 | /** |
563 | * @param string $url | |
564 | * @return string | |
565 | */ | |
566 | public function addCacheCode($url) { | |
33603e1d | 567 | $hasQuery = strpos($url, '?') !== FALSE; |
03449a5b | 568 | $operator = $hasQuery ? '&' : '?'; |
6f12c6eb | 569 | |
03449a5b | 570 | return $url . $operator . 'r=' . $this->cacheCode; |
6f12c6eb | 571 | } |
33603e1d | 572 | |
adcd4bf7 CW |
573 | /** |
574 | * Checks if the given URL is fully-formed | |
575 | * | |
576 | * @param string $url | |
577 | * | |
578 | * @return bool | |
579 | */ | |
580 | public static function isFullyFormedUrl($url) { | |
581 | return (substr($url, 0, 4) === 'http') || (substr($url, 0, 1) === '/'); | |
582 | } | |
583 | ||
f55f8f17 TO |
584 | /** |
585 | * @param string|NULL $region | |
586 | * Optional request for a specific region. If NULL/omitted, use global default. | |
587 | * @return \CRM_Core_Region | |
588 | */ | |
589 | private function getSettingRegion($region = NULL) { | |
590 | $region = $region ?: (self::isAjaxMode() ? 'ajax-snippet' : 'html-header'); | |
591 | return CRM_Core_Region::instance($region); | |
592 | } | |
593 | ||
6a488035 | 594 | } |