advagg_mod.admin.inc

  1. cis7 sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc
  2. cle7 sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc
  3. ecd7 sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc
  4. elmsmedia7 sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc
  5. harmony7 sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc
  6. icor7 sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc
  7. meedjum_blog7 sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc
  8. mooc7 sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc

Admin page callbacks for the advagg bundler module.

Functions

Namesort descending Description
advagg_mod_admin_settings_form Form builder; Configure advagg settings.
advagg_mod_admin_settings_form_submit Clear out the advagg cache bin when the save configuration button is pressed.
advagg_mod_admin_settings_form_validate Make sure the unified multisite directory was created correctly.
advagg_mod_admin_test_css_files Test all CSS files seeing if any string translations do anything.

File

sites/all/modules/ulmus/advagg/advagg_mod/advagg_mod.admin.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Admin page callbacks for the advagg bundler module.
  5. */
  6. /**
  7. * Form builder; Configure advagg settings.
  8. *
  9. * @ingroup forms
  10. * @see system_settings_form()
  11. */
  12. function advagg_mod_admin_settings_form() {
  13. drupal_set_title(t('AdvAgg: Modifications'));
  14. $form = array();
  15. $form['js'] = array(
  16. '#type' => 'fieldset',
  17. '#title' => t('JS'),
  18. );
  19. $form['js']['advagg_mod_js_footer'] = array(
  20. '#type' => 'radios',
  21. '#title' => t('Move JS to the footer'),
  22. '#default_value' => variable_get('advagg_mod_js_footer', ADVAGG_MOD_JS_FOOTER),
  23. '#options' => array(
  24. 0 => t('Disabled'),
  25. 1 => t('All but JavaScript Libraries'),
  26. 2 => t('All'),
  27. ),
  28. '#description' => t("If you have JavaScript inline in the body of your document, such as if you are displaying ads, you may need to keep Drupal JS Libraries in the head instead of moving them to the footer. This will keep all JS added with the JS_LIBRARY group in the head while still moving all other JavaScript to the footer."),
  29. );
  30. $form['js']['advagg_mod_js_preprocess'] = array(
  31. '#type' => 'checkbox',
  32. '#title' => t('Enable preprocess on all JS'),
  33. '#default_value' => variable_get('advagg_mod_js_preprocess', ADVAGG_MOD_JS_PREPROCESS),
  34. '#description' => t('Force all JavaScript to have the preprocess attribute be set to TRUE. All JavaScript files will be aggregated if enabled.'),
  35. );
  36. $form['js']['advagg_mod_js_async_shim'] = array(
  37. '#type' => 'checkbox',
  38. '#title' => t('Rewrite asynchronous script tags to inline, old-browser-compatible scripts.'),
  39. '#default_value' => variable_get('advagg_mod_js_async_shim', ADVAGG_MOD_JS_ASYNC_SHIM),
  40. '#description' => t('Rewrites all scripts in the page with an "async" attribute to an inline JavaScript loading the script asynchronously in an old browser compatible way. List of <a href="@link">supported browsers</a>. Once all commonly used browsers support the "async" attribute you can happily disable this checkbox.', array('@link' => 'http://caniuse.com/script-async')),
  41. );
  42. $form['js']['advagg_mod_js_remove_unused'] = array(
  43. '#type' => 'checkbox',
  44. '#title' => t('Remove unused JavaScript tags if possible'),
  45. '#default_value' => variable_get('advagg_mod_js_remove_unused', ADVAGG_MOD_JS_REMOVE_UNUSED),
  46. '#description' => t('This will scan all included JS files for references to jquery and drupal. If none are found then the core JavaScript (jquery.js, drupal.js, & Drupal.settings) is removed and not loaded on that page. If you have a site that does not use a lot of Javascript this might be helpful as it could prevent unused JavaScript from being executed, thus speeding up your sites frontend performance.'),
  47. );
  48. $form['js']['adjust_sort'] = array(
  49. '#type' => 'fieldset',
  50. '#title' => t('Optimize JavaScript Ordering'),
  51. '#description' => t('The settings in here might change the order in which the JavaScript is loaded. It will move the scripts around so that more optimal aggregates are built. In most cases enabling these checkboxes will cause no negative side effects.'),
  52. );
  53. $form['js']['adjust_sort']['advagg_mod_js_adjust_sort_external'] = array(
  54. '#type' => 'checkbox',
  55. '#title' => t('Move all external scripts to the top of the execution order'),
  56. '#default_value' => variable_get('advagg_mod_js_adjust_sort_external', ADVAGG_MOD_JS_ADJUST_SORT_EXTERNAL),
  57. '#description' => t('This will group all external JavaScript files to be above all other JavaScript.'),
  58. );
  59. $form['js']['adjust_sort']['advagg_mod_js_adjust_sort_inline'] = array(
  60. '#type' => 'checkbox',
  61. '#title' => t('Move all inline scripts to the bottom of the execution order'),
  62. '#default_value' => variable_get('advagg_mod_js_adjust_sort_inline', ADVAGG_MOD_JS_ADJUST_SORT_INLINE),
  63. '#description' => t('This will group all inline JavaScript to be below all other JavaScript.'),
  64. );
  65. $form['js']['adjust_sort']['advagg_mod_js_adjust_sort_browsers'] = array(
  66. '#type' => 'checkbox',
  67. '#title' => t('Move all browser conditional JavaScript to the bottom of the group'),
  68. '#default_value' => variable_get('advagg_mod_js_adjust_sort_browsers', ADVAGG_MOD_JS_ADJUST_SORT_BROWSERS),
  69. '#description' => t('This will group all browser conditional JavaScript to be in the lowest group of that conditional rule.'),
  70. );
  71. $form['js']['expert'] = array(
  72. '#type' => 'fieldset',
  73. '#title' => t('Experimental Settings'),
  74. '#collapsible' => TRUE,
  75. '#collapsed' => TRUE,
  76. );
  77. $form['js']['expert']['advagg_mod_js_defer'] = array(
  78. '#type' => 'checkbox',
  79. '#title' => t('Deferred JavaScript Execution: Add The defer Tag To All Script Tags'),
  80. '#default_value' => variable_get('advagg_mod_js_defer', ADVAGG_MOD_JS_DEFER),
  81. '#description' => t('This will delay the script execution until the HTML parser has finished. This will have a similar effect to moving all JavaScript to the footer. This might break javascript on different browsers; only use after extensive testing! <a href="@link">More Info</a>', array(
  82. '@link' => 'http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/',
  83. )),
  84. );
  85. $config_path = advagg_admin_config_root_path();
  86. $form['css'] = array(
  87. '#type' => 'fieldset',
  88. '#title' => t('CSS'),
  89. );
  90. $form['css']['advagg_mod_css_preprocess'] = array(
  91. '#type' => 'checkbox',
  92. '#title' => t('Enable preprocess on all CSS'),
  93. '#default_value' => variable_get('advagg_mod_css_preprocess', ADVAGG_MOD_CSS_PREPROCESS),
  94. '#description' => t('Force all CSS to have the preprocess attribute be set to TRUE. All CSS files will be aggregated if enabled.'),
  95. );
  96. // @ignore security_fapi_title
  97. $form['css']['advagg_mod_css_preprocess']['#description'] .= module_exists('advagg_bundler') ? ' ' . t('You might want to increase the <a href="@link">CSS Bundles Per Page</a> if this is checked.', array('@link' => url($config_path . '/advagg/bundler'))) : '';
  98. // @ignore sniffer_commenting_inlinecomment_spacingbefore:3
  99. // Only test the translate option if
  100. // the locale function is defined OR
  101. // the locale_custom_strings variable is not empty.
  102. $locale_custom_strings = variable_get('locale_custom_strings_' . isset($GLOBALS['language']->language) ? $GLOBALS['language']->language : 'en', array());
  103. if (function_exists('locale') || !empty($locale_custom_strings)) {
  104. // Only show option if something comes back translated.
  105. $files = advagg_mod_admin_test_css_files('css');
  106. if (!empty($files)) {
  107. $form['css']['advagg_mod_css_translate'] = array(
  108. '#type' => 'checkbox',
  109. '#title' => t('Translate CSS content strings'),
  110. '#default_value' => variable_get('advagg_mod_css_translate', ADVAGG_MOD_CSS_TRANSLATE),
  111. '#description' => t('Run strings inside of quotes of the content attribute through the <a href="@t">t() function</a>. An alternative to this can be found in this <a href="@post">blog post</a>.', array(
  112. '@t' => 'https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/t/7',
  113. '@post' => 'http://fourkitchens.com/blog/2013/08/15/multilingual-css-generated-content-drupal',
  114. )),
  115. );
  116. }
  117. }
  118. $form['css']['adjust_sort'] = array(
  119. '#type' => 'fieldset',
  120. '#title' => t('Optimize CSS Ordering'),
  121. '#description' => t('The settings in here might change the order in which the CSS is loaded. It will move the CSS around so that more optimal aggregates are built. In most cases enabling these checkboxes will cause no negative side effects.'),
  122. );
  123. $form['css']['adjust_sort']['advagg_mod_css_adjust_sort_external'] = array(
  124. '#type' => 'checkbox',
  125. '#title' => t('Move all external CSS to the top of the execution order'),
  126. '#default_value' => variable_get('advagg_mod_css_adjust_sort_external', ADVAGG_MOD_CSS_ADJUST_SORT_EXTERNAL),
  127. '#description' => t('This is experimental. This will group all external CSS files to be above all other CSS.'),
  128. );
  129. $form['css']['adjust_sort']['advagg_mod_css_adjust_sort_inline'] = array(
  130. '#type' => 'checkbox',
  131. '#title' => t('Move all inline CSS to the bottom of the execution order'),
  132. '#default_value' => variable_get('advagg_mod_css_adjust_sort_inline', ADVAGG_MOD_CSS_ADJUST_SORT_INLINE),
  133. '#description' => t('This is experimental. This will group all inline CSS to be below all other CSS.'),
  134. );
  135. $form['css']['adjust_sort']['advagg_mod_css_adjust_sort_browsers'] = array(
  136. '#type' => 'checkbox',
  137. '#title' => t('Move all browser conditional CSS to the bottom of the group'),
  138. '#default_value' => variable_get('advagg_mod_css_adjust_sort_browsers', ADVAGG_MOD_CSS_ADJUST_SORT_BROWSERS),
  139. '#description' => t('This is experimental. This will group all browser conditional CSS to be in the lowest group of that conditional rule.'),
  140. );
  141. $form['landing_page'] = array(
  142. '#type' => 'fieldset',
  143. '#title' => t('Inline CSS/JS on specific pages'),
  144. '#description' => t('For most people this is a setting that should not be used. This will prevent all local CSS & JavaScript files from being downloaded; instead the contents of them will all be inlined. This will cause the raw HTML downloaded to be a lot bigger but it will cause less connections to your webserver from being created. This can sometimes be useful for certian landing pages.'),
  145. '#collapsible' => TRUE,
  146. '#collapsed' => TRUE,
  147. );
  148. // Taken from block_admin_configure().
  149. $access = user_access('use PHP for settings');
  150. $visibility = variable_get('advagg_mod_inline_visibility', BLOCK_VISIBILITY_LISTED);
  151. $pages = variable_get('advagg_mod_inline_pages', '');
  152. if ($visibility == BLOCK_VISIBILITY_PHP && !$access) {
  153. $form['landing_page']['path']['visibility'] = array(
  154. '#type' => 'value',
  155. '#value' => $visibility,
  156. );
  157. $form['landing_page']['path']['pages'] = array(
  158. '#type' => 'value',
  159. '#value' => $pages,
  160. );
  161. }
  162. else {
  163. $options = array(
  164. // BLOCK_VISIBILITY_NOTLISTED => t('All pages except those listed'),
  165. BLOCK_VISIBILITY_LISTED => t('Only the listed pages'),
  166. );
  167. $description = t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array(
  168. '%blog' => 'blog',
  169. '%blog-wildcard' => 'blog/*',
  170. '%front' => '<front>',
  171. ));
  172. if (module_exists('php') && $access) {
  173. $options += array(BLOCK_VISIBILITY_PHP => t('Pages on which this PHP code returns <code>TRUE</code> (experts only)'));
  174. $title = t('Pages or PHP code');
  175. $description .= ' ' . t('If the PHP option is chosen, enter PHP code between %php. Note that executing incorrect PHP code can break your Drupal site.', array('%php' => '<?php ?>'));
  176. }
  177. else {
  178. $title = t('Pages');
  179. }
  180. $form['landing_page']['path']['advagg_mod_inline_settings'] = array(
  181. '#type' => 'radios',
  182. '#title' => t('Inline CSS/JS on specific pages'),
  183. '#options' => $options,
  184. '#default_value' => $visibility,
  185. );
  186. $form['landing_page']['path']['advagg_mod_inline_pages'] = array(
  187. '#type' => 'textarea',
  188. '#title' => '<span class="element-invisible">' . $title . '</span>',
  189. '#default_value' => $pages,
  190. '#description' => $description,
  191. );
  192. }
  193. $form['unified_multisite'] = array(
  194. '#type' => 'fieldset',
  195. '#title' => t('Unified Multisite'),
  196. '#description' => t('For most people this is a setting that should not be used.'),
  197. '#collapsible' => TRUE,
  198. '#collapsed' => TRUE,
  199. );
  200. $form['unified_multisite']['advagg_mod_unified_multisite_dir'] = array(
  201. '#type' => 'textfield',
  202. '#title' => t('Shared Directory'),
  203. '#default_value' => variable_get('advagg_mod_unified_multisite_dir', ''),
  204. '#size' => 60,
  205. '#maxlength' => 128,
  206. '#description' => t('This allows you to have a shared directory for all CSS/JS aggregates if this install of drupal is used as a <a href="@multisite">multisite</a>. If this servers multisites share a similar CSS/JS structure then a lot of resources can be saved by not rebuilding the same aggregates in each site of the multisite. Make sure that you use the same directory and advagg settings in each multisite for this setting to work efficiently. Current <a href="@info">hash value</a> of settings on this site: %value. If this value is different across the servers multisites then this will not save server resources as a different file will be built due to AdvAgg having different settings. Note that $base_path is used in the hash value so in some multisite cases it will be impossible to use this setting.', array(
  207. '@multisite' => 'https://drupal.org/documentation/install/multi-site',
  208. '@info' => url($config_path . '/advagg/info'),
  209. '%value' => advagg_get_current_hooks_hash(),
  210. )),
  211. );
  212. // Make sure the multisite_dir is writable.
  213. $form['#validate'][] = 'advagg_mod_admin_settings_form_validate';
  214. // Clear the cache bins on submit.
  215. $form['#submit'][] = 'advagg_mod_admin_settings_form_submit';
  216. return system_settings_form($form);
  217. }
  218. // Validate callback.
  219. /**
  220. * Make sure the unified multisite directory was created correctly.
  221. */
  222. function advagg_mod_admin_settings_form_validate($form, &$form_state) {
  223. $multisite_dir = rtrim($form_state['values']['advagg_mod_unified_multisite_dir'], '/');
  224. // Return if unified_multisite_dir is not set.
  225. if (empty($multisite_dir)) {
  226. return;
  227. }
  228. // Prepare directory.
  229. $css_dir = $multisite_dir . '/advagg_css';
  230. $js_dir = $multisite_dir . '/advagg_js';
  231. // @ignore sniffer_whitespace_openbracketspacing_openingwhitespace
  232. if ( !file_prepare_directory($css_dir, FILE_CREATE_DIRECTORY)
  233. || !file_prepare_directory($js_dir, FILE_CREATE_DIRECTORY)
  234. ) {
  235. if (!is_dir($multisite_dir) || !is_writable($multisite_dir)) {
  236. form_set_error('advagg_mod_unified_multisite_dir', t('%dir is not a directory or can not be written to. The shared directory needs to have the same permissions as the "Public file system path" found on the <a href="@file_system_link">File System configuration page</a>.', array(
  237. '%dir' => $multisite_dir,
  238. '@file_system_link' => url('admin/config/media/file-system'),
  239. )));
  240. return;
  241. }
  242. }
  243. }
  244. // Submit callback.
  245. /**
  246. * Clear out the advagg cache bin when the save configuration button is pressed.
  247. */
  248. function advagg_mod_admin_settings_form_submit($form, &$form_state) {
  249. $cache_bins = advagg_flush_caches();
  250. foreach ($cache_bins as $bin) {
  251. cache_clear_all('*', $bin, TRUE);
  252. }
  253. // If unified_multisite_dir has changed, flush menu router at the end of the
  254. // request.
  255. $multisite_dir = rtrim($form_state['values']['advagg_mod_unified_multisite_dir'], '/');
  256. $dir = rtrim(variable_get('advagg_mod_unified_multisite_dir', ''), '/');
  257. if ($multisite_dir != $dir) {
  258. register_shutdown_function('advagg_get_root_files_dir', TRUE);
  259. register_shutdown_function('menu_rebuild');
  260. }
  261. }
  262. /**
  263. * Test all CSS files seeing if any string translations do anything.
  264. *
  265. * @return array
  266. * An array with the filename key and the before => after translation value.
  267. */
  268. function advagg_mod_admin_test_css_files() {
  269. $output = array();
  270. // Get list of files.
  271. $query_files = db_select('advagg_files', 'af')
  272. ->fields('af', array('filename_hash', 'filename'))
  273. ->condition('af.filetype', 'css')
  274. ->orderBy('filename', 'DESC')
  275. ->execute()
  276. ->fetchAllKeyed();
  277. $files = array_values($query_files);
  278. // Exit if no files were found.
  279. if (empty($files)) {
  280. return $output;
  281. }
  282. foreach ($files as $filename) {
  283. // Skip missing files.
  284. if (!file_exists($filename)) {
  285. continue;
  286. }
  287. // Load CSS file.
  288. $file_contents = drupal_load_stylesheet_content(file_get_contents($filename), TRUE);
  289. // Code taken from drupal_load_stylesheet_content().
  290. // Regexp to match double quoted strings.
  291. $double_quot = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
  292. // Regexp to match single quoted strings.
  293. $single_quot = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'";
  294. // Extract all content inside of quotes.
  295. $css_content_pattern = "/content:.*?($double_quot|$single_quot|(\\;|\\})).*?(?:\\;|\\})/";
  296. // Get strings inside of quotes of the content attribute.
  297. preg_match_all($css_content_pattern, $file_contents, $matches);
  298. // Skip if no matches.
  299. if (empty($matches[1])) {
  300. continue;
  301. }
  302. foreach ($matches[1] as $value) {
  303. // Skip if equal to ; or }.
  304. if ($value == ';' || $value == '}') {
  305. continue;
  306. }
  307. // Remove quotes for t function.
  308. $before = substr($value, 1, -1);
  309. // Only test if it contains A-Za-z.
  310. if (!preg_match('/[A-Za-z]/', $before)) {
  311. continue;
  312. }
  313. // Only test if it contains characters other than unicode.
  314. $css_unicode_pattern = '/\\\\[0-9a-fA-F]{1,6}(?:\\r\\n|[ \\t\\r\\n\\f])?/';
  315. $unicode_removed = preg_replace($css_unicode_pattern, '', $before);
  316. if (empty($unicode_removed)) {
  317. continue;
  318. }
  319. // Run t function.
  320. // @ignore sniffer_semantics_functioncall_notliteralstring
  321. $after = t($before);
  322. // Only include it if strings are different.
  323. if ($before !== $after) {
  324. if (!isset($output[$filename])) {
  325. $output[$filename] = '';
  326. }
  327. $output[$filename] .= $before . ' => ' . $after;
  328. }
  329. }
  330. }
  331. return $output;
  332. }