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