3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 +--------------------------------------------------------------------+
13 * Define some common, global lists of resources.
15 class CRM_Core_Resources_Common
{
17 const REGION
= 'html-header';
20 * The 'bundle.coreStyles' service is a collection of resources used on some
21 * non-Civi pages (wherein Civi may be mixed-in).
25 * @return \CRM_Core_Resources_Bundle
26 * @see \Civi\Core\Container::createContainer()
28 public static function createStyleBundle($name) {
29 $bundle = new CRM_Core_Resources_Bundle($name);
31 // Load custom or core css
32 $config = CRM_Core_Config
::singleton();
33 if (!empty($config->customCSSURL
)) {
34 $customCSSURL = Civi
::resources()->addCacheCode($config->customCSSURL
);
35 $bundle->addStyleUrl($customCSSURL, 99);
37 if (!Civi
::settings()->get('disable_core_css')) {
38 $bundle->addStyleFile('civicrm', 'css/civicrm.css', -99);
40 // crm-i.css added ahead of other styles so it can be overridden by FA.
41 $bundle->addStyleFile('civicrm', 'css/crm-i.css', -101);
43 CRM_Utils_Hook
::alterBundle($bundle);
44 self
::useRegion($bundle, self
::REGION
);
49 * The 'bundle.coreResources' service is a collection of resources
50 * shared by Civi pages (ie pages where Civi controls rendering).
53 * i.e. 'coreResources'
54 * @return \CRM_Core_Resources_Bundle
55 * @see \Civi\Core\Container::createContainer()
57 public static function createFullBundle($name) {
58 $bundle = new CRM_Core_Resources_Bundle($name);
59 $config = CRM_Core_Config
::singleton();
61 // Add resources from coreResourceList
63 foreach (self
::coreResourceList(self
::REGION
) as $item) {
64 if (is_array($item)) {
65 $bundle->addSetting($item);
67 elseif (strpos($item, '.css')) {
68 Civi
::resources()->isFullyFormedUrl($item) ?
$bundle->addStyleUrl($item, -100) : $bundle->addStyleFile('civicrm', $item, -100);
70 elseif (Civi
::resources()->isFullyFormedUrl($item)) {
71 $bundle->addScriptUrl($item, $jsWeight++
);
74 // Don't bother looking for ts() calls in packages, there aren't any
75 $translate = (substr($item, 0, 3) == 'js/');
76 $bundle->addScriptFile('civicrm', $item, [
77 'weight' => $jsWeight++
,
78 'translate' => $translate,
82 // Add global settings
85 'isFrontend' => $config->userFrameworkFrontend
,
88 // Disable profile creation if user lacks permission
89 if (!CRM_Core_Permission
::check('edit all contacts') && !CRM_Core_Permission
::check('add contacts')) {
90 $settings['config']['entityRef']['contactCreate'] = FALSE;
92 $bundle->addSetting($settings);
94 // Give control of jQuery and _ back to the CMS - this loads last
95 $bundle->addScriptFile('civicrm', 'js/noconflict.js', [
100 CRM_Utils_Hook
::alterBundle($bundle);
101 self
::useRegion($bundle, self
::REGION
);
106 * List of core resources we add to every CiviCRM page.
108 * Note: non-compressed versions of .min files will be used in debug mode
110 * @param string $region
113 protected static function coreResourceList($region) {
114 $config = CRM_Core_Config
::singleton();
116 // Scripts needed by everyone, everywhere
117 // FIXME: This is too long; list needs finer-grained segmentation
119 "bower_components/jquery/dist/jquery.min.js",
120 "bower_components/jquery-ui/jquery-ui.min.js",
121 "bower_components/jquery-ui/themes/smoothness/jquery-ui.min.css",
122 "bower_components/lodash-compat/lodash.min.js",
123 "packages/jquery/plugins/jquery.mousewheel.min.js",
124 "bower_components/select2/select2.min.js",
125 "bower_components/select2/select2.min.css",
126 "bower_components/font-awesome/css/font-awesome.min.css",
127 "packages/jquery/plugins/jquery.form.min.js",
128 "packages/jquery/plugins/jquery.timeentry.min.js",
129 "packages/jquery/plugins/jquery.blockUI.min.js",
130 "bower_components/datatables/media/js/jquery.dataTables.min.js",
131 "bower_components/datatables/media/css/jquery.dataTables.min.css",
132 "bower_components/jquery-validation/dist/jquery.validate.min.js",
133 "bower_components/jquery-validation/dist/additional-methods.min.js",
134 "packages/jquery/plugins/jquery.ui.datepicker.validation.min.js",
136 "js/crm.datepicker.js",
138 "js/wysiwyg/crm.wysiwyg.js",
141 // Dynamic localization script
142 $items[] = Civi
::resources()->addCacheCode(
143 CRM_Utils_System
::url('civicrm/ajax/l10n-js/' . CRM_Core_I18n
::getLocale(),
144 ['cid' => CRM_Core_Session
::getLoggedInContactID()], FALSE, NULL, FALSE)
147 // add wysiwyg editor
148 $editor = Civi
::settings()->get('editor_id');
149 if ($editor == "CKEditor") {
150 CRM_Admin_Form_CKEditorConfig
::setConfigDefault();
153 'wysisygScriptLocation' => Civi
::paths()->getUrl("[civicrm.root]/js/wysiwyg/crm.ckeditor.js"),
154 'CKEditorCustomConfig' => CRM_Admin_Form_CKEditorConfig
::getConfigUrl(),
159 // These scripts are only needed by back-office users
160 if (CRM_Core_Permission
::check('access CiviCRM')) {
161 $items[] = "packages/jquery/plugins/jquery.tableHeader.js";
162 $items[] = "packages/jquery/plugins/jquery.notify.min.js";
165 $contactID = CRM_Core_Session
::getLoggedInContactID();
170 $contactID && !$config->userFrameworkFrontend
171 && CRM_Core_Permission
::check('access CiviCRM')
172 && !@constant
('CIVICRM_DISABLE_DEFAULT_MENU')
173 && !CRM_Core_Config
::isUpgradeMode()
175 $position = Civi
::settings()->get('menubar_position') ?
: 'over-cms-menu';
177 if ($position !== 'none') {
178 $items[] = 'bower_components/smartmenus/dist/jquery.smartmenus.min.js';
179 $items[] = 'bower_components/smartmenus/dist/addons/keyboard/jquery.smartmenus.keyboard.min.js';
180 $items[] = 'js/crm.menubar.js';
181 // @see CRM_Core_Resources::renderMenubarStylesheet
182 $items[] = Civi
::service('asset_builder')->getUrl('crm-menubar.css', [
183 'menubarColor' => Civi
::settings()->get('menubar_color'),
187 // Variables for crm.menubar.js
190 'position' => $position,
191 'qfKey' => CRM_Core_Key
::get('CRM_Contact_Controller_Search', TRUE),
192 'cacheCode' => CRM_Core_BAO_Navigation
::getCacheKey($contactID),
197 // JS for multilingual installations
198 if (!empty($config->languageLimit
) && count($config->languageLimit
) > 1 && CRM_Core_Permission
::check('translate CiviCRM')) {
199 $items[] = "js/crm.multilingual.js";
202 // Enable administrators to edit option lists in a dialog
203 if (CRM_Core_Permission
::check('administer CiviCRM') && Civi
::settings()->get('ajaxPopupsEnabled')) {
204 $items[] = "js/crm.optionEdit.js";
207 $tsLocale = CRM_Core_I18n
::getLocale();
208 // Add localized jQuery UI files
209 if ($tsLocale && $tsLocale != 'en_US') {
210 // Search for i18n file in order of specificity (try fr-CA, then fr)
211 list($lang) = explode('_', $tsLocale);
212 $path = "bower_components/jquery-ui/ui/i18n";
213 foreach ([str_replace('_', '-', $tsLocale), $lang] as $language) {
214 $localizationFile = "$path/datepicker-{$language}.js";
215 if (Civi
::resources()->getPath('civicrm', $localizationFile)) {
216 $items[] = $localizationFile;
222 // Allow hooks to modify this list
223 CRM_Utils_Hook
::coreResourceList($items, $region);
225 // Oof, existing listeners would expect $items to typically begin with 'bower_components/' or 'packages/'
226 // (using an implicit base of `[civicrm.root]`). We preserve the hook contract and cleanup $items post-hook.
228 'bower_components' => rtrim(Civi
::paths()->getUrl('[civicrm.bower]/.', 'absolute'), '/'),
229 'packages' => rtrim(Civi
::paths()->getUrl('[civicrm.packages]/.', 'absolute'), '/'),
231 $filter = function($m) use ($map) {
232 return $map[$m[1]] . $m[2];
234 $items = array_map(function($item) use ($filter) {
235 return is_array($item) ?
$item : preg_replace_callback(';^(bower_components|packages)(/.*);', $filter, $item);
242 * Ensure that all elements of the bundle are in the same region.
244 * @param CRM_Core_Resources_Bundle $bundle
245 * @param string $region
246 * @return CRM_Core_Resources_Bundle
248 protected static function useRegion($bundle, $region) {
249 $bundle->filter(function ($s) use ($region) {
250 if ($s['type'] !== 'settings' && !isset($s['region'])) {
251 $s['region'] = $region;