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); | |
209 | return $this; | |
210 | } | |
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 | ||
222 | // If an item is already assigned to a region, we'll respect that. | |
223 | // Otherwise, we'll use defaults. | |
224 | $pickRegion = function ($snippet) { | |
225 | if (isset($snippet['settings'])) { | |
226 | return $this->getSettingRegion($snippet['region'] ?? NULL)->_name; | |
227 | } | |
228 | else { | |
229 | return $snippet['region'] ?? self::DEFAULT_REGION; | |
230 | } | |
231 | }; | |
232 | ||
233 | $byRegion = []; | |
234 | foreach ($bundle->getAll() as $snippet) { | |
235 | $snippet['region'] = $pickRegion($snippet); | |
236 | $byRegion[$snippet['region']][$snippet['name']] = $snippet; | |
237 | } | |
238 | ||
239 | foreach ($byRegion as $regionName => $snippets) { | |
240 | CRM_Core_Region::instance($regionName)->merge($snippets); | |
241 | } | |
242 | return $this; | |
243 | } | |
244 | ||
69847402 | 245 | /** |
d09edf64 | 246 | * Helper fn for addSettingsFactory. |
6a488035 | 247 | */ |
63918d37 TO |
248 | public function getSettings($region = NULL) { |
249 | return $this->getSettingRegion($region)->getSettings(); | |
6a488035 TO |
250 | } |
251 | ||
6a488035 | 252 | /** |
d09edf64 | 253 | * Determine file path of a resource provided by an extension. |
6a488035 | 254 | * |
5a4f6742 CW |
255 | * @param string $ext |
256 | * extension name; use 'civicrm' for core. | |
e97c66ff | 257 | * @param string|null $file |
5a4f6742 | 258 | * file path -- relative to the extension base dir. |
6a488035 | 259 | * |
72b3a70c CW |
260 | * @return bool|string |
261 | * full file path or FALSE if not found | |
6a488035 | 262 | */ |
16cd1eca | 263 | public function getPath($ext, $file = NULL) { |
6a488035 | 264 | // TODO consider caching results |
b698e2d5 TO |
265 | $base = $this->paths->hasVariable($ext) |
266 | ? rtrim($this->paths->getVariable($ext, 'path'), '/') | |
267 | : $this->extMapper->keyToBasePath($ext); | |
16cd1eca | 268 | if ($file === NULL) { |
b698e2d5 | 269 | return $base; |
16cd1eca | 270 | } |
b698e2d5 | 271 | $path = $base . '/' . $file; |
6a488035 TO |
272 | if (is_file($path)) { |
273 | return $path; | |
274 | } | |
275 | return FALSE; | |
276 | } | |
277 | ||
278 | /** | |
d09edf64 | 279 | * Determine public URL of a resource provided by an extension. |
6a488035 | 280 | * |
5a4f6742 CW |
281 | * @param string $ext |
282 | * extension name; use 'civicrm' for core. | |
283 | * @param string $file | |
284 | * file path -- relative to the extension base dir. | |
2a6da8d7 EM |
285 | * @param bool $addCacheCode |
286 | * | |
6a488035 TO |
287 | * @return string, URL |
288 | */ | |
289 | public function getUrl($ext, $file = NULL, $addCacheCode = FALSE) { | |
290 | if ($file === NULL) { | |
291 | $file = ''; | |
292 | } | |
293 | if ($addCacheCode) { | |
6f12c6eb | 294 | $file = $this->addCacheCode($file); |
6a488035 TO |
295 | } |
296 | // TODO consider caching results | |
b698e2d5 TO |
297 | $base = $this->paths->hasVariable($ext) |
298 | ? $this->paths->getVariable($ext, 'url') | |
299 | : ($this->extMapper->keyToUrl($ext) . '/'); | |
300 | return $base . $file; | |
6a488035 TO |
301 | } |
302 | ||
16cd1eca TO |
303 | /** |
304 | * Evaluate a glob pattern in the context of a particular extension. | |
305 | * | |
306 | * @param string $ext | |
307 | * Extension name; use 'civicrm' for core. | |
308 | * @param string|array $patterns | |
309 | * Glob pattern; e.g. "*.html". | |
310 | * @param null|int $flags | |
311 | * See glob(). | |
312 | * @return array | |
313 | * List of matching files, relative to the extension base dir. | |
314 | * @see glob() | |
315 | */ | |
316 | public function glob($ext, $patterns, $flags = NULL) { | |
317 | $path = $this->getPath($ext); | |
318 | $patterns = (array) $patterns; | |
be2fb01f | 319 | $files = []; |
16cd1eca | 320 | foreach ($patterns as $pattern) { |
e5c376e7 TO |
321 | if (preg_match(';^(assetBuilder|ext)://;', $pattern)) { |
322 | $files[] = $pattern; | |
323 | } | |
9f87b14b | 324 | if (CRM_Utils_File::isAbsolute($pattern)) { |
16cd1eca TO |
325 | // Absolute path. |
326 | $files = array_merge($files, (array) glob($pattern, $flags)); | |
327 | } | |
328 | else { | |
329 | // Relative path. | |
330 | $files = array_merge($files, (array) glob("$path/$pattern", $flags)); | |
331 | } | |
332 | } | |
518fa0ee SL |
333 | // Deterministic order. |
334 | sort($files); | |
16cd1eca TO |
335 | $files = array_unique($files); |
336 | return array_map(function ($file) use ($path) { | |
337 | return CRM_Utils_File::relativize($file, "$path/"); | |
338 | }, $files); | |
339 | } | |
340 | ||
a0ee3941 EM |
341 | /** |
342 | * @return string | |
343 | */ | |
6a488035 TO |
344 | public function getCacheCode() { |
345 | return $this->cacheCode; | |
346 | } | |
347 | ||
a0ee3941 EM |
348 | /** |
349 | * @param $value | |
5badddc3 | 350 | * @return CRM_Core_Resources |
a0ee3941 | 351 | */ |
6a488035 TO |
352 | public function setCacheCode($value) { |
353 | $this->cacheCode = $value; | |
354 | if ($this->cacheCodeKey) { | |
08ef4ddd | 355 | Civi::settings()->set($this->cacheCodeKey, $value); |
6a488035 | 356 | } |
9762f6ff | 357 | return $this; |
6a488035 TO |
358 | } |
359 | ||
5badddc3 CW |
360 | /** |
361 | * @return CRM_Core_Resources | |
362 | */ | |
6a488035 TO |
363 | public function resetCacheCode() { |
364 | $this->setCacheCode(CRM_Utils_String::createRandom(5, CRM_Utils_String::ALPHANUMERIC)); | |
f091327b CW |
365 | // Also flush cms resource cache if needed |
366 | CRM_Core_Config::singleton()->userSystem->clearResourceCache(); | |
9762f6ff | 367 | return $this; |
6a488035 TO |
368 | } |
369 | ||
370 | /** | |
371 | * This adds CiviCRM's standard css and js to the specified region of the document. | |
372 | * It will only run once. | |
373 | * | |
2a6da8d7 | 374 | * @param string $region |
6a488035 | 375 | * @return CRM_Core_Resources |
6a488035 TO |
376 | */ |
377 | public function addCoreResources($region = 'html-header') { | |
8d2c99cf TO |
378 | if ($region !== 'html-header') { |
379 | // The signature of this method allowed different regions. However, this | |
380 | // doesn't appear to be used - based on grepping `universe` generally | |
381 | // and `civicrm-{core,backdrop,drupal,packages,wordpress,joomla}` specifically, | |
382 | // it appears that all callers use 'html-header' (either implicitly or explicitly). | |
383 | throw new \CRM_Core_Exception("Error: addCoreResources only supports html-header"); | |
384 | } | |
8d469336 TO |
385 | if (!self::isAjaxMode()) { |
386 | $this->addBundle('coreResources'); | |
6a488035 TO |
387 | $this->addCoreStyles($region); |
388 | } | |
389 | return $this; | |
390 | } | |
391 | ||
392 | /** | |
393 | * This will add CiviCRM's standard CSS | |
394 | * | |
6a488035 TO |
395 | * @param string $region |
396 | * @return CRM_Core_Resources | |
397 | */ | |
398 | public function addCoreStyles($region = 'html-header') { | |
8d2c99cf TO |
399 | if ($region !== 'html-header') { |
400 | // The signature of this method allowed different regions. However, this | |
401 | // doesn't appear to be used - based on grepping `universe` generally | |
402 | // and `civicrm-{core,backdrop,drupal,packages,wordpress,joomla}` specifically, | |
403 | // it appears that all callers use 'html-header' (either implicitly or explicitly). | |
404 | throw new \CRM_Core_Exception("Error: addCoreResources only supports html-header"); | |
405 | } | |
5526ab4d | 406 | $this->addBundle('coreStyles'); |
6a488035 TO |
407 | return $this; |
408 | } | |
409 | ||
627668e8 | 410 | /** |
d09edf64 | 411 | * Flushes cached translated strings. |
5badddc3 | 412 | * @return CRM_Core_Resources |
627668e8 CW |
413 | */ |
414 | public function flushStrings() { | |
fd7dc3f3 | 415 | $this->strings->flush(); |
9762f6ff CW |
416 | return $this; |
417 | } | |
418 | ||
6a488035 | 419 | /** |
fd7dc3f3 TO |
420 | * @return CRM_Core_Resources_Strings |
421 | */ | |
422 | public function getStrings() { | |
423 | return $this->strings; | |
6a488035 TO |
424 | } |
425 | ||
19f7e35e | 426 | /** |
8d7a9d07 | 427 | * Create dynamic script for localizing js widgets. |
19f7e35e | 428 | */ |
00be9182 | 429 | public static function outputLocalizationJS() { |
4cc9b813 | 430 | CRM_Core_Page_AJAX::setJsHeaders(); |
a88cf11a | 431 | $config = CRM_Core_Config::singleton(); |
be2fb01f | 432 | $vars = [ |
3d527838 CW |
433 | 'moneyFormat' => json_encode(CRM_Utils_Money::format(1234.56)), |
434 | 'contactSearch' => json_encode($config->includeEmailInName ? ts('Start typing a name or email...') : ts('Start typing a name...')), | |
435 | 'otherSearch' => json_encode(ts('Enter search term...')), | |
e695ee7c | 436 | 'entityRef' => self::getEntityRefMetadata(), |
7b83e312 | 437 | 'ajaxPopupsEnabled' => self::singleton()->ajaxPopupsEnabled, |
a9fb6123 | 438 | 'allowAlertAutodismissal' => (bool) Civi::settings()->get('allow_alert_autodismissal'), |
c7e39a79 | 439 | 'resourceCacheCode' => self::singleton()->getCacheCode(), |
b30809e4 CW |
440 | 'locale' => CRM_Core_I18n::getLocale(), |
441 | 'cid' => (int) CRM_Core_Session::getLoggedInContactID(), | |
be2fb01f | 442 | ]; |
3d4fb0ed | 443 | print CRM_Core_Smarty::singleton()->fetchWith('CRM/common/l10n.js.tpl', $vars); |
4cc9b813 | 444 | CRM_Utils_System::civiExit(); |
c66581f5 CW |
445 | } |
446 | ||
156fd9b9 | 447 | /** |
a6c01b45 CW |
448 | * @return bool |
449 | * is this page request an ajax snippet? | |
156fd9b9 | 450 | */ |
00be9182 | 451 | public static function isAjaxMode() { |
be2fb01f | 452 | if (in_array(CRM_Utils_Array::value('snippet', $_REQUEST), [ |
518fa0ee SL |
453 | CRM_Core_Smarty::PRINT_SNIPPET, |
454 | CRM_Core_Smarty::PRINT_NOFORM, | |
455 | CRM_Core_Smarty::PRINT_JSON, | |
456 | ]) | |
42a40a1c | 457 | ) { |
458 | return TRUE; | |
459 | } | |
f31f885e | 460 | list($arg0, $arg1) = array_pad(explode('/', CRM_Utils_System::currentPath()), 2, ''); |
60c3b6e9 | 461 | return ($arg0 === 'civicrm' && in_array($arg1, ['ajax', 'angularprofiles', 'asset'])); |
156fd9b9 | 462 | } |
b7ceb253 | 463 | |
1889d803 | 464 | /** |
518fa0ee | 465 | * @param \Civi\Core\Event\GenericHookEvent $e |
1889d803 CW |
466 | * @see \CRM_Utils_Hook::buildAsset() |
467 | */ | |
468 | public static function renderMenubarStylesheet(GenericHookEvent $e) { | |
469 | if ($e->asset !== 'crm-menubar.css') { | |
470 | return; | |
471 | } | |
472 | $e->mimeType = 'text/css'; | |
dcaf410f | 473 | $content = ''; |
1889d803 CW |
474 | $config = CRM_Core_Config::singleton(); |
475 | $cms = strtolower($config->userFramework); | |
476 | $cms = $cms === 'drupal' ? 'drupal7' : $cms; | |
477 | $items = [ | |
478 | 'bower_components/smartmenus/dist/css/sm-core-css.css', | |
479 | 'css/crm-menubar.css', | |
480 | "css/menubar-$cms.css", | |
481 | ]; | |
482 | foreach ($items as $item) { | |
dcaf410f | 483 | $content .= file_get_contents(self::singleton()->getPath('civicrm', $item)); |
8a52ae34 | 484 | } |
dcaf410f CW |
485 | $params = $e->params; |
486 | // "color" is deprecated in favor of the more specific "menubarColor" | |
487 | $menubarColor = $params['color'] ?? $params['menubarColor']; | |
1889d803 | 488 | $vars = [ |
dcaf410f CW |
489 | '$resourceBase' => rtrim($config->resourceBase, '/'), |
490 | '$menubarHeight' => $params['height'] . 'px', | |
491 | '$breakMin' => $params['breakpoint'] . 'px', | |
492 | '$breakMax' => ($params['breakpoint'] - 1) . 'px', | |
493 | '$menubarColor' => $menubarColor, | |
63c2508b | 494 | '$menuItemColor' => $params['menuItemColor'] ?? $menubarColor, |
dcaf410f CW |
495 | '$highlightColor' => $params['highlightColor'] ?? CRM_Utils_Color::getHighlight($menubarColor), |
496 | '$textColor' => $params['textColor'] ?? CRM_Utils_Color::getContrast($menubarColor, '#333', '#ddd'), | |
1889d803 | 497 | ]; |
dcaf410f CW |
498 | $vars['$highlightTextColor'] = $params['highlightTextColor'] ?? CRM_Utils_Color::getContrast($vars['$highlightColor'], '#333', '#ddd'); |
499 | $e->content = str_replace(array_keys($vars), array_values($vars), $content); | |
1889d803 CW |
500 | } |
501 | ||
b7ceb253 | 502 | /** |
f9e31d7f | 503 | * Provide a list of available entityRef filters. |
fd7c068f | 504 | * |
b7ceb253 CW |
505 | * @return array |
506 | */ | |
e695ee7c CW |
507 | public static function getEntityRefMetadata() { |
508 | $data = [ | |
509 | 'filters' => [], | |
510 | 'links' => [], | |
511 | ]; | |
06606cd1 | 512 | $config = CRM_Core_Config::singleton(); |
b7ceb253 | 513 | |
1d6f94ab CW |
514 | $disabledComponents = []; |
515 | $dao = CRM_Core_DAO::executeQuery("SELECT name, namespace FROM civicrm_component"); | |
516 | while ($dao->fetch()) { | |
517 | if (!in_array($dao->name, $config->enableComponents)) { | |
518 | $disabledComponents[$dao->name] = $dao->namespace; | |
06606cd1 CW |
519 | } |
520 | } | |
521 | ||
1d6f94ab CW |
522 | foreach (CRM_Core_DAO_AllCoreTables::daoToClass() as $entity => $daoName) { |
523 | // Skip DAOs of disabled components | |
524 | foreach ($disabledComponents as $nameSpace) { | |
525 | if (strpos($daoName, $nameSpace) === 0) { | |
526 | continue 2; | |
527 | } | |
528 | } | |
529 | $baoName = str_replace('_DAO_', '_BAO_', $daoName); | |
530 | if (class_exists($baoName)) { | |
e695ee7c CW |
531 | $filters = $baoName::getEntityRefFilters(); |
532 | if ($filters) { | |
2229cf4f | 533 | $data['filters'][$entity] = $filters; |
e695ee7c CW |
534 | } |
535 | if (is_callable([$baoName, 'getEntityRefCreateLinks'])) { | |
536 | $createLinks = $baoName::getEntityRefCreateLinks(); | |
537 | if ($createLinks) { | |
2229cf4f | 538 | $data['links'][$entity] = $createLinks; |
e695ee7c | 539 | } |
1d6f94ab CW |
540 | } |
541 | } | |
b7b528bc CW |
542 | } |
543 | ||
77d0bf4e | 544 | CRM_Utils_Hook::entityRefFilters($data['filters'], $data['links']); |
fd7c068f | 545 | |
e695ee7c | 546 | return $data; |
b7ceb253 | 547 | } |
96025800 | 548 | |
09a4dcd5 | 549 | /** |
d89d2545 | 550 | * Determine the minified file name. |
09a4dcd5 | 551 | * |
d89d2545 TO |
552 | * @param string $ext |
553 | * @param string $file | |
554 | * @return string | |
555 | * An updated $fileName. If a minified version exists and is supported by | |
556 | * system policy, the minified version will be returned. Otherwise, the original. | |
557 | */ | |
558 | public function filterMinify($ext, $file) { | |
559 | if (CRM_Core_Config::singleton()->debug && strpos($file, '.min.') !== FALSE) { | |
560 | $nonMiniFile = str_replace('.min.', '.', $file); | |
561 | if ($this->getPath($ext, $nonMiniFile)) { | |
562 | $file = $nonMiniFile; | |
09a4dcd5 CW |
563 | } |
564 | } | |
d89d2545 | 565 | return $file; |
09a4dcd5 CW |
566 | } |
567 | ||
6f12c6eb | 568 | /** |
569 | * @param string $url | |
570 | * @return string | |
571 | */ | |
572 | public function addCacheCode($url) { | |
33603e1d | 573 | $hasQuery = strpos($url, '?') !== FALSE; |
03449a5b | 574 | $operator = $hasQuery ? '&' : '?'; |
6f12c6eb | 575 | |
03449a5b | 576 | return $url . $operator . 'r=' . $this->cacheCode; |
6f12c6eb | 577 | } |
33603e1d | 578 | |
adcd4bf7 CW |
579 | /** |
580 | * Checks if the given URL is fully-formed | |
581 | * | |
582 | * @param string $url | |
583 | * | |
584 | * @return bool | |
585 | */ | |
586 | public static function isFullyFormedUrl($url) { | |
587 | return (substr($url, 0, 4) === 'http') || (substr($url, 0, 1) === '/'); | |
588 | } | |
589 | ||
f55f8f17 TO |
590 | /** |
591 | * @param string|NULL $region | |
592 | * Optional request for a specific region. If NULL/omitted, use global default. | |
593 | * @return \CRM_Core_Region | |
594 | */ | |
595 | private function getSettingRegion($region = NULL) { | |
596 | $region = $region ?: (self::isAjaxMode() ? 'ajax-snippet' : 'html-header'); | |
597 | return CRM_Core_Region::instance($region); | |
598 | } | |
599 | ||
6a488035 | 600 | } |