Commit | Line | Data |
---|---|---|
b2d8361e TO |
1 | <?php |
2 | /* | |
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 | +--------------------------------------------------------------------+ | |
10 | */ | |
11 | ||
12 | /** | |
13 | * Define some common, global lists of resources. | |
14 | */ | |
15 | class CRM_Core_Resources_Common { | |
16 | ||
17 | const REGION = 'html-header'; | |
18 | ||
8eb00bd1 TO |
19 | /** |
20 | * A "basic" bundle has an | |
21 | * | |
22 | * @param string $name | |
23 | * Symbolic name of the bundle. | |
24 | * @param callable|NULL $init | |
25 | * Optional initialization function. Populate default resources. | |
26 | * ie `function($bundle): void` | |
27 | * @param string|string[] $types | |
28 | * List of resource-types to permit in this bundle. NULL for a default list. | |
29 | * Ex: ['styleFile', 'styleUrl'] | |
30 | * The following aliases are allowed: '*all*', '*default*', '*script*', '*style*' | |
31 | * @return CRM_Core_Resources_Bundle | |
32 | */ | |
33 | public static function createBasicBundle($name, $init = NULL, $types = NULL) { | |
34 | $bundle = new CRM_Core_Resources_Bundle($name, $types); | |
35 | if ($init !== NULL) { | |
36 | $init($bundle); | |
37 | } | |
38 | CRM_Utils_Hook::alterBundle($bundle); | |
39 | $bundle->fillDefaults(); | |
40 | return $bundle; | |
41 | } | |
42 | ||
6e7adedc TO |
43 | /** |
44 | * The 'bundle.bootstrap3' service is a collection of resources which are | |
45 | * loaded when a page needs to support Boostrap CSS v3. | |
46 | * | |
47 | * @param string $name | |
48 | * i.e. 'bootstrap3' | |
49 | * @return \CRM_Core_Resources_Bundle | |
50 | */ | |
51 | public static function createBootstrap3Bundle($name) { | |
d853edea TO |
52 | $bundle = new CRM_Core_Resources_Bundle($name, ['script', 'scriptFile', 'scriptUrl', 'settings', 'style', 'styleFile', 'styleUrl', 'markup']); |
53 | // Leave it to the theme/provider to register specific resources. | |
54 | // $bundle->addStyleFile('civicrm', 'css/bootstrap3.css'); | |
55 | // $bundle->addScriptFile('civicrm', 'js/bootstrap3.js', [ | |
56 | // 'translate' => FALSE, | |
57 | //]); | |
58 | ||
59 | // This warning will show if bootstrap is unavailable. Normally it will be hidden by the bootstrap .collapse class. | |
60 | $bundle->addMarkup(' | |
61 | <div id="bootstrap-theme"> | |
62 | <div class="messages warning no-popup collapse"> | |
63 | <p> | |
64 | <i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i> | |
65 | <strong>' . ts('Bootstrap theme not found.') . '</strong> | |
66 | </p> | |
67 | <p>' . ts('This screen may not work correctly without a bootstrap-based theme such as Shoreditch installed.') . '</p> | |
68 | </div> | |
69 | </div>', | |
70 | ['region' => 'page-header'] | |
71 | ); | |
72 | ||
6e7adedc | 73 | CRM_Utils_Hook::alterBundle($bundle); |
924d1dc8 | 74 | $bundle->fillDefaults(); |
6e7adedc TO |
75 | return $bundle; |
76 | } | |
77 | ||
b2d8361e TO |
78 | /** |
79 | * The 'bundle.coreStyles' service is a collection of resources used on some | |
80 | * non-Civi pages (wherein Civi may be mixed-in). | |
81 | * | |
82 | * @param string $name | |
83 | * i.e. 'coreStyles' | |
84 | * @return \CRM_Core_Resources_Bundle | |
950538ac | 85 | * @see \Civi\Core\Container::createContainer() |
b2d8361e TO |
86 | */ |
87 | public static function createStyleBundle($name) { | |
88 | $bundle = new CRM_Core_Resources_Bundle($name); | |
5526ab4d TO |
89 | |
90 | // Load custom or core css | |
91 | $config = CRM_Core_Config::singleton(); | |
92 | if (!empty($config->customCSSURL)) { | |
93 | $customCSSURL = Civi::resources()->addCacheCode($config->customCSSURL); | |
94 | $bundle->addStyleUrl($customCSSURL, 99); | |
95 | } | |
96 | if (!Civi::settings()->get('disable_core_css')) { | |
97 | $bundle->addStyleFile('civicrm', 'css/civicrm.css', -99); | |
98 | } | |
99 | // crm-i.css added ahead of other styles so it can be overridden by FA. | |
100 | $bundle->addStyleFile('civicrm', 'css/crm-i.css', -101); | |
101 | ||
b2d8361e | 102 | CRM_Utils_Hook::alterBundle($bundle); |
924d1dc8 | 103 | $bundle->fillDefaults(); |
b2d8361e TO |
104 | return $bundle; |
105 | } | |
106 | ||
107 | /** | |
108 | * The 'bundle.coreResources' service is a collection of resources | |
109 | * shared by Civi pages (ie pages where Civi controls rendering). | |
110 | * | |
111 | * @param string $name | |
112 | * i.e. 'coreResources' | |
113 | * @return \CRM_Core_Resources_Bundle | |
950538ac | 114 | * @see \Civi\Core\Container::createContainer() |
b2d8361e TO |
115 | */ |
116 | public static function createFullBundle($name) { | |
117 | $bundle = new CRM_Core_Resources_Bundle($name); | |
8d469336 TO |
118 | $config = CRM_Core_Config::singleton(); |
119 | ||
120 | // Add resources from coreResourceList | |
121 | $jsWeight = -9999; | |
122 | foreach (self::coreResourceList(self::REGION) as $item) { | |
123 | if (is_array($item)) { | |
124 | $bundle->addSetting($item); | |
125 | } | |
126 | elseif (strpos($item, '.css')) { | |
127 | Civi::resources()->isFullyFormedUrl($item) ? $bundle->addStyleUrl($item, -100) : $bundle->addStyleFile('civicrm', $item, -100); | |
128 | } | |
129 | elseif (Civi::resources()->isFullyFormedUrl($item)) { | |
130 | $bundle->addScriptUrl($item, $jsWeight++); | |
131 | } | |
132 | else { | |
133 | // Don't bother looking for ts() calls in packages, there aren't any | |
134 | $translate = (substr($item, 0, 3) == 'js/'); | |
135 | $bundle->addScriptFile('civicrm', $item, [ | |
136 | 'weight' => $jsWeight++, | |
137 | 'translate' => $translate, | |
138 | ]); | |
139 | } | |
140 | } | |
141 | // Add global settings | |
142 | $settings = [ | |
143 | 'config' => [ | |
144 | 'isFrontend' => $config->userFrameworkFrontend, | |
145 | ], | |
146 | ]; | |
147 | // Disable profile creation if user lacks permission | |
148 | if (!CRM_Core_Permission::check('edit all contacts') && !CRM_Core_Permission::check('add contacts')) { | |
149 | $settings['config']['entityRef']['contactCreate'] = FALSE; | |
150 | } | |
151 | $bundle->addSetting($settings); | |
152 | ||
153 | // Give control of jQuery and _ back to the CMS - this loads last | |
154 | $bundle->addScriptFile('civicrm', 'js/noconflict.js', [ | |
155 | 'weight' => 9999, | |
156 | 'translate' => FALSE, | |
157 | ]); | |
158 | ||
b2d8361e | 159 | CRM_Utils_Hook::alterBundle($bundle); |
924d1dc8 | 160 | $bundle->fillDefaults(); |
b2d8361e TO |
161 | return $bundle; |
162 | } | |
163 | ||
8d469336 TO |
164 | /** |
165 | * List of core resources we add to every CiviCRM page. | |
166 | * | |
167 | * Note: non-compressed versions of .min files will be used in debug mode | |
168 | * | |
169 | * @param string $region | |
170 | * @return array | |
171 | */ | |
172 | protected static function coreResourceList($region) { | |
173 | $config = CRM_Core_Config::singleton(); | |
174 | ||
175 | // Scripts needed by everyone, everywhere | |
176 | // FIXME: This is too long; list needs finer-grained segmentation | |
177 | $items = [ | |
178 | "bower_components/jquery/dist/jquery.min.js", | |
179 | "bower_components/jquery-ui/jquery-ui.min.js", | |
180 | "bower_components/jquery-ui/themes/smoothness/jquery-ui.min.css", | |
181 | "bower_components/lodash-compat/lodash.min.js", | |
182 | "packages/jquery/plugins/jquery.mousewheel.min.js", | |
183 | "bower_components/select2/select2.min.js", | |
184 | "bower_components/select2/select2.min.css", | |
185 | "bower_components/font-awesome/css/font-awesome.min.css", | |
186 | "packages/jquery/plugins/jquery.form.min.js", | |
187 | "packages/jquery/plugins/jquery.timeentry.min.js", | |
188 | "packages/jquery/plugins/jquery.blockUI.min.js", | |
189 | "bower_components/datatables/media/js/jquery.dataTables.min.js", | |
190 | "bower_components/datatables/media/css/jquery.dataTables.min.css", | |
191 | "bower_components/jquery-validation/dist/jquery.validate.min.js", | |
192 | "bower_components/jquery-validation/dist/additional-methods.min.js", | |
193 | "packages/jquery/plugins/jquery.ui.datepicker.validation.min.js", | |
194 | "js/Common.js", | |
195 | "js/crm.datepicker.js", | |
196 | "js/crm.ajax.js", | |
197 | "js/wysiwyg/crm.wysiwyg.js", | |
198 | ]; | |
199 | ||
200 | // Dynamic localization script | |
201 | $items[] = Civi::resources()->addCacheCode( | |
202 | CRM_Utils_System::url('civicrm/ajax/l10n-js/' . CRM_Core_I18n::getLocale(), | |
203 | ['cid' => CRM_Core_Session::getLoggedInContactID()], FALSE, NULL, FALSE) | |
204 | ); | |
205 | ||
206 | // add wysiwyg editor | |
207 | $editor = Civi::settings()->get('editor_id'); | |
208 | if ($editor == "CKEditor") { | |
209 | CRM_Admin_Form_CKEditorConfig::setConfigDefault(); | |
210 | $items[] = [ | |
211 | 'config' => [ | |
212 | 'wysisygScriptLocation' => Civi::paths()->getUrl("[civicrm.root]/js/wysiwyg/crm.ckeditor.js"), | |
213 | 'CKEditorCustomConfig' => CRM_Admin_Form_CKEditorConfig::getConfigUrl(), | |
214 | ], | |
215 | ]; | |
216 | } | |
217 | ||
218 | // These scripts are only needed by back-office users | |
219 | if (CRM_Core_Permission::check('access CiviCRM')) { | |
220 | $items[] = "packages/jquery/plugins/jquery.tableHeader.js"; | |
221 | $items[] = "packages/jquery/plugins/jquery.notify.min.js"; | |
222 | } | |
223 | ||
224 | $contactID = CRM_Core_Session::getLoggedInContactID(); | |
225 | ||
226 | // Menubar | |
227 | $position = 'none'; | |
228 | if ( | |
229 | $contactID && !$config->userFrameworkFrontend | |
230 | && CRM_Core_Permission::check('access CiviCRM') | |
231 | && !@constant('CIVICRM_DISABLE_DEFAULT_MENU') | |
232 | && !CRM_Core_Config::isUpgradeMode() | |
233 | ) { | |
234 | $position = Civi::settings()->get('menubar_position') ?: 'over-cms-menu'; | |
235 | } | |
236 | if ($position !== 'none') { | |
237 | $items[] = 'bower_components/smartmenus/dist/jquery.smartmenus.min.js'; | |
238 | $items[] = 'bower_components/smartmenus/dist/addons/keyboard/jquery.smartmenus.keyboard.min.js'; | |
239 | $items[] = 'js/crm.menubar.js'; | |
240 | // @see CRM_Core_Resources::renderMenubarStylesheet | |
241 | $items[] = Civi::service('asset_builder')->getUrl('crm-menubar.css', [ | |
242 | 'menubarColor' => Civi::settings()->get('menubar_color'), | |
243 | 'height' => 40, | |
244 | 'breakpoint' => 768, | |
245 | ]); | |
246 | // Variables for crm.menubar.js | |
247 | $items[] = [ | |
248 | 'menubar' => [ | |
249 | 'position' => $position, | |
250 | 'qfKey' => CRM_Core_Key::get('CRM_Contact_Controller_Search', TRUE), | |
251 | 'cacheCode' => CRM_Core_BAO_Navigation::getCacheKey($contactID), | |
252 | ], | |
253 | ]; | |
254 | } | |
255 | ||
256 | // JS for multilingual installations | |
257 | if (!empty($config->languageLimit) && count($config->languageLimit) > 1 && CRM_Core_Permission::check('translate CiviCRM')) { | |
258 | $items[] = "js/crm.multilingual.js"; | |
259 | } | |
260 | ||
261 | // Enable administrators to edit option lists in a dialog | |
262 | if (CRM_Core_Permission::check('administer CiviCRM') && Civi::settings()->get('ajaxPopupsEnabled')) { | |
263 | $items[] = "js/crm.optionEdit.js"; | |
264 | } | |
265 | ||
266 | $tsLocale = CRM_Core_I18n::getLocale(); | |
267 | // Add localized jQuery UI files | |
268 | if ($tsLocale && $tsLocale != 'en_US') { | |
269 | // Search for i18n file in order of specificity (try fr-CA, then fr) | |
270 | list($lang) = explode('_', $tsLocale); | |
271 | $path = "bower_components/jquery-ui/ui/i18n"; | |
272 | foreach ([str_replace('_', '-', $tsLocale), $lang] as $language) { | |
273 | $localizationFile = "$path/datepicker-{$language}.js"; | |
274 | if (Civi::resources()->getPath('civicrm', $localizationFile)) { | |
275 | $items[] = $localizationFile; | |
276 | break; | |
277 | } | |
278 | } | |
279 | } | |
280 | ||
281 | // Allow hooks to modify this list | |
282 | CRM_Utils_Hook::coreResourceList($items, $region); | |
283 | ||
284 | // Oof, existing listeners would expect $items to typically begin with 'bower_components/' or 'packages/' | |
285 | // (using an implicit base of `[civicrm.root]`). We preserve the hook contract and cleanup $items post-hook. | |
286 | $map = [ | |
287 | 'bower_components' => rtrim(Civi::paths()->getUrl('[civicrm.bower]/.', 'absolute'), '/'), | |
288 | 'packages' => rtrim(Civi::paths()->getUrl('[civicrm.packages]/.', 'absolute'), '/'), | |
289 | ]; | |
290 | $filter = function($m) use ($map) { | |
291 | return $map[$m[1]] . $m[2]; | |
292 | }; | |
293 | $items = array_map(function($item) use ($filter) { | |
294 | return is_array($item) ? $item : preg_replace_callback(';^(bower_components|packages)(/.*);', $filter, $item); | |
295 | }, $items); | |
296 | ||
297 | return $items; | |
298 | } | |
299 | ||
b2d8361e | 300 | } |