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); | |
100 | $bundle->addStyleUrl($customCSSURL, 99); | |
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) { | |
179 | $config = CRM_Core_Config::singleton(); | |
180 | ||
181 | // Scripts needed by everyone, everywhere | |
182 | // FIXME: This is too long; list needs finer-grained segmentation | |
183 | $items = [ | |
184 | "bower_components/jquery/dist/jquery.min.js", | |
185 | "bower_components/jquery-ui/jquery-ui.min.js", | |
186 | "bower_components/jquery-ui/themes/smoothness/jquery-ui.min.css", | |
187 | "bower_components/lodash-compat/lodash.min.js", | |
188 | "packages/jquery/plugins/jquery.mousewheel.min.js", | |
189 | "bower_components/select2/select2.min.js", | |
190 | "bower_components/select2/select2.min.css", | |
191 | "bower_components/font-awesome/css/font-awesome.min.css", | |
192 | "packages/jquery/plugins/jquery.form.min.js", | |
193 | "packages/jquery/plugins/jquery.timeentry.min.js", | |
194 | "packages/jquery/plugins/jquery.blockUI.min.js", | |
195 | "bower_components/datatables/media/js/jquery.dataTables.min.js", | |
196 | "bower_components/datatables/media/css/jquery.dataTables.min.css", | |
197 | "bower_components/jquery-validation/dist/jquery.validate.min.js", | |
198 | "bower_components/jquery-validation/dist/additional-methods.min.js", | |
199 | "packages/jquery/plugins/jquery.ui.datepicker.validation.min.js", | |
200 | "js/Common.js", | |
201 | "js/crm.datepicker.js", | |
202 | "js/crm.ajax.js", | |
203 | "js/wysiwyg/crm.wysiwyg.js", | |
204 | ]; | |
205 | ||
206 | // Dynamic localization script | |
207 | $items[] = Civi::resources()->addCacheCode( | |
208 | CRM_Utils_System::url('civicrm/ajax/l10n-js/' . CRM_Core_I18n::getLocale(), | |
209 | ['cid' => CRM_Core_Session::getLoggedInContactID()], FALSE, NULL, FALSE) | |
210 | ); | |
211 | ||
212 | // add wysiwyg editor | |
213 | $editor = Civi::settings()->get('editor_id'); | |
214 | if ($editor == "CKEditor") { | |
215 | CRM_Admin_Form_CKEditorConfig::setConfigDefault(); | |
216 | $items[] = [ | |
217 | 'config' => [ | |
218 | 'wysisygScriptLocation' => Civi::paths()->getUrl("[civicrm.root]/js/wysiwyg/crm.ckeditor.js"), | |
219 | 'CKEditorCustomConfig' => CRM_Admin_Form_CKEditorConfig::getConfigUrl(), | |
220 | ], | |
221 | ]; | |
222 | } | |
223 | ||
224 | // These scripts are only needed by back-office users | |
225 | if (CRM_Core_Permission::check('access CiviCRM')) { | |
226 | $items[] = "packages/jquery/plugins/jquery.tableHeader.js"; | |
227 | $items[] = "packages/jquery/plugins/jquery.notify.min.js"; | |
228 | } | |
229 | ||
230 | $contactID = CRM_Core_Session::getLoggedInContactID(); | |
231 | ||
232 | // Menubar | |
233 | $position = 'none'; | |
234 | if ( | |
235 | $contactID && !$config->userFrameworkFrontend | |
236 | && CRM_Core_Permission::check('access CiviCRM') | |
237 | && !@constant('CIVICRM_DISABLE_DEFAULT_MENU') | |
238 | && !CRM_Core_Config::isUpgradeMode() | |
239 | ) { | |
240 | $position = Civi::settings()->get('menubar_position') ?: 'over-cms-menu'; | |
241 | } | |
242 | if ($position !== 'none') { | |
243 | $items[] = 'bower_components/smartmenus/dist/jquery.smartmenus.min.js'; | |
244 | $items[] = 'bower_components/smartmenus/dist/addons/keyboard/jquery.smartmenus.keyboard.min.js'; | |
245 | $items[] = 'js/crm.menubar.js'; | |
246 | // @see CRM_Core_Resources::renderMenubarStylesheet | |
247 | $items[] = Civi::service('asset_builder')->getUrl('crm-menubar.css', [ | |
248 | 'menubarColor' => Civi::settings()->get('menubar_color'), | |
249 | 'height' => 40, | |
250 | 'breakpoint' => 768, | |
251 | ]); | |
252 | // Variables for crm.menubar.js | |
253 | $items[] = [ | |
254 | 'menubar' => [ | |
255 | 'position' => $position, | |
256 | 'qfKey' => CRM_Core_Key::get('CRM_Contact_Controller_Search', TRUE), | |
257 | 'cacheCode' => CRM_Core_BAO_Navigation::getCacheKey($contactID), | |
258 | ], | |
259 | ]; | |
260 | } | |
261 | ||
262 | // JS for multilingual installations | |
263 | if (!empty($config->languageLimit) && count($config->languageLimit) > 1 && CRM_Core_Permission::check('translate CiviCRM')) { | |
264 | $items[] = "js/crm.multilingual.js"; | |
265 | } | |
266 | ||
267 | // Enable administrators to edit option lists in a dialog | |
268 | if (CRM_Core_Permission::check('administer CiviCRM') && Civi::settings()->get('ajaxPopupsEnabled')) { | |
269 | $items[] = "js/crm.optionEdit.js"; | |
270 | } | |
271 | ||
272 | $tsLocale = CRM_Core_I18n::getLocale(); | |
273 | // Add localized jQuery UI files | |
274 | if ($tsLocale && $tsLocale != 'en_US') { | |
275 | // Search for i18n file in order of specificity (try fr-CA, then fr) | |
276 | list($lang) = explode('_', $tsLocale); | |
277 | $path = "bower_components/jquery-ui/ui/i18n"; | |
278 | foreach ([str_replace('_', '-', $tsLocale), $lang] as $language) { | |
279 | $localizationFile = "$path/datepicker-{$language}.js"; | |
280 | if (Civi::resources()->getPath('civicrm', $localizationFile)) { | |
281 | $items[] = $localizationFile; | |
282 | break; | |
283 | } | |
284 | } | |
285 | } | |
286 | ||
287 | // Allow hooks to modify this list | |
288 | CRM_Utils_Hook::coreResourceList($items, $region); | |
289 | ||
290 | // Oof, existing listeners would expect $items to typically begin with 'bower_components/' or 'packages/' | |
291 | // (using an implicit base of `[civicrm.root]`). We preserve the hook contract and cleanup $items post-hook. | |
292 | $map = [ | |
293 | 'bower_components' => rtrim(Civi::paths()->getUrl('[civicrm.bower]/.', 'absolute'), '/'), | |
294 | 'packages' => rtrim(Civi::paths()->getUrl('[civicrm.packages]/.', 'absolute'), '/'), | |
295 | ]; | |
296 | $filter = function($m) use ($map) { | |
297 | return $map[$m[1]] . $m[2]; | |
298 | }; | |
299 | $items = array_map(function($item) use ($filter) { | |
300 | return is_array($item) ? $item : preg_replace_callback(';^(bower_components|packages)(/.*);', $filter, $item); | |
301 | }, $items); | |
302 | ||
303 | return $items; | |
304 | } | |
305 | ||
b2d8361e | 306 | } |