advagg_bundler.module

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

Advanced aggregation bundler module.

Functions

Namesort descending Description
advagg_bundler_advagg_hooks_implemented_alter Implements hook_advagg_hooks_implemented_alter().
advagg_bundler_analysis Given a filename return a bundle key.
advagg_bundler_enabled Returns TRUE if the bundler will run.
advagg_bundler_form_advagg_admin_settings_form_alter Implements hook_form_FORM_ID_alter().
advagg_bundler_init Implements hook_init().
advagg_bundler_menu Implements hook_menu().

Constants

Namesort descending Description
ADVAGG_BUNDLER_ACTIVE Default value to see if the bundler should be active or passive. If it is passive, the bundler will only do analysis and not split up the aggregate.
ADVAGG_BUNDLER_MAX_CSS Default value of the maximum number of CSS bundles that can be generated in a single request.
ADVAGG_BUNDLER_MAX_JS Default value of the maximum number of JS bundles that can be generated in a single request.
ADVAGG_BUNDLER_OUTDATED Default value of the last used time before the bundle is considered outdated. 2 weeks in seconds.

File

sites/all/modules/ulmus/advagg/advagg_bundler/advagg_bundler.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Advanced aggregation bundler module.
  5. */
  6. /**
  7. * Default value of the maximum number of CSS bundles that can be generated in
  8. * a single request.
  9. */
  10. define('ADVAGG_BUNDLER_MAX_CSS', 4);
  11. /**
  12. * Default value of the maximum number of JS bundles that can be generated in
  13. * a single request.
  14. */
  15. define('ADVAGG_BUNDLER_MAX_JS', 4);
  16. /**
  17. * Default value of the last used time before the bundle is considered outdated.
  18. * 2 weeks in seconds.
  19. */
  20. define('ADVAGG_BUNDLER_OUTDATED', 1209600);
  21. /**
  22. * Default value to see if the bundler should be active or passive. If it is
  23. * passive, the bundler will only do analysis and not split up the aggregate.
  24. */
  25. define('ADVAGG_BUNDLER_ACTIVE', TRUE);
  26. /**
  27. * Implements hook_menu().
  28. */
  29. function advagg_bundler_menu() {
  30. $file_path = drupal_get_path('module', 'advagg_bundler');
  31. $config_path = advagg_admin_config_root_path();
  32. $items[$config_path . '/advagg/bundler'] = array(
  33. 'title' => 'Bundler',
  34. 'description' => 'Adjust Bundler settings.',
  35. 'page callback' => 'drupal_get_form',
  36. 'page arguments' => array('advagg_bundler_admin_settings_form'),
  37. 'type' => MENU_LOCAL_TASK,
  38. 'access arguments' => array('administer site configuration'),
  39. 'file path' => $file_path,
  40. 'file' => 'advagg_bundler.admin.inc',
  41. 'weight' => 10,
  42. );
  43. return $items;
  44. }
  45. /**
  46. * Implements hook_advagg_hooks_implemented_alter().
  47. */
  48. function advagg_bundler_advagg_hooks_implemented_alter(&$hooks, $all) {
  49. if ($all) {
  50. $hooks['advagg_bundler_analysis_alter'] = array();
  51. }
  52. }
  53. /**
  54. * Implements hook_init().
  55. */
  56. function advagg_bundler_init() {
  57. if (advagg_bundler_enabled()) {
  58. $GLOBALS['conf']['advagg_core_groups'] = FALSE;
  59. }
  60. }
  61. /**
  62. * Implements hook_form_FORM_ID_alter().
  63. */
  64. function advagg_bundler_form_advagg_admin_settings_form_alter(&$form, $form_state) {
  65. if (advagg_bundler_enabled()) {
  66. $form['global']['advagg_core_groups']['#disabled'] = TRUE;
  67. $form['global']['advagg_core_groups']['#description'] = t('The bundler submodule disables core grouping logic.');
  68. $form['global']['advagg_core_groups']['#states'] = array();
  69. }
  70. }
  71. /**
  72. * Returns TRUE if the bundler will run.
  73. */
  74. function advagg_bundler_enabled() {
  75. if (variable_get('advagg_bundler_active', ADVAGG_BUNDLER_ACTIVE) && (variable_get('advagg_bundler_max_css', ADVAGG_BUNDLER_MAX_CSS) || variable_get('advagg_bundler_max_js', ADVAGG_BUNDLER_MAX_JS))) {
  76. return TRUE;
  77. }
  78. }
  79. /**
  80. * Given a filename return a bundle key.
  81. *
  82. * @param string $filename
  83. * filename
  84. * @param bool $force
  85. * bypass the cache and get a fresh version of the analysis.
  86. *
  87. * @return string
  88. * string to be used for the grouping key.
  89. */
  90. function advagg_bundler_analysis($filename = '', $force = FALSE) {
  91. // Cache query in a static.
  92. static $analysis = array();
  93. if (empty($analysis)) {
  94. // See if we have a cached version of this. Generate cache ID.
  95. $query = db_select('advagg_aggregates_versions', 'aav')
  96. ->condition('aav.root', 1)
  97. ->condition('aav.atime', REQUEST_TIME - ADVAGG_BUNDLER_OUTDATED, '>');
  98. $query->addExpression('COUNT(aggregate_filenames_hash)', 'counter');
  99. $count = $query->execute()->fetchField();
  100. $ideal_cid = 'advagg:bundler_analysis:' . $count;
  101. if (!$force) {
  102. // Generate cache IDs.
  103. $counts = range(max(0, $count - 3), $count + 3);
  104. foreach ($counts as $count) {
  105. $cache_ids[] = 'advagg:bundler_analysis:' . $count;
  106. }
  107. // Get a range of cached bundler_analysis data.
  108. $cache_hits = cache_get_multiple($cache_ids, 'cache_advagg_aggregates');
  109. if (!empty($cache_hits)) {
  110. if (isset($cache_hits[$ideal_cid])) {
  111. $cache = $cache_hits[$ideal_cid];
  112. }
  113. elseif (!$force && module_exists('httprl') && httprl_is_background_callback_capable()) {
  114. // Setup callback options array.
  115. $callback_options = array(
  116. array(
  117. 'function' => 'advagg_bundler_analysis',
  118. ),
  119. $filename, TRUE,
  120. );
  121. // Queue up the request.
  122. httprl_queue_background_callback($callback_options);
  123. // Execute request.
  124. httprl_send_request();
  125. // Use most recent bundler_analysis data.
  126. $max = 0;
  127. foreach ($cache_hits as $cid => $data) {
  128. if ($data->created > $max) {
  129. $max = $data->created;
  130. $cache = $data;
  131. }
  132. }
  133. }
  134. }
  135. }
  136. if ($force || empty($cache->data)) {
  137. // "Magic Query"; only needs to run once.
  138. // Return a count of how many root bundles all files are used in. Count is
  139. // padded with eight zeros so the count can be key sorted as a string
  140. // without worrying about it getting put in the wrong order.
  141. // Return the bundle_md5's value; we need something more unique than count
  142. // when grouping together.
  143. // Return the filename. Used for lookup.
  144. // We join the advagg bundles and files together making sure to only use
  145. // root bundles that have been used in the last 2 weeks. This prevents an
  146. // old site structure from influencing new bundles.
  147. // Grouping by the filename gives us the count and makes it so we don't
  148. // return a lot of rows;
  149. // @ignore sniffer_commenting_inlinecomment_spacingafter
  150. // Create join query for the advagg_aggregates_versions table.
  151. // 1209600 = 2 weeks.
  152. $subquery_aggregates_versions = db_select('advagg_aggregates_versions', 'aav')
  153. ->fields('aav')
  154. ->condition('aav.root', 1)
  155. ->condition('aav.atime', REQUEST_TIME - ADVAGG_BUNDLER_OUTDATED, '>');
  156. // Create join query for the advagg_aggregates table.
  157. $subquery_aggregates = db_select('advagg_aggregates', 'aa');
  158. $subquery_aggregates->join($subquery_aggregates_versions, 'aav', 'aav.aggregate_filenames_hash=aa.aggregate_filenames_hash');
  159. $subquery_aggregates->addExpression("LPAD(CAST(COUNT(aav.aggregate_filenames_hash) AS char(8)), 8, '0')", 'counter');
  160. $fields = array('counter');
  161. $db_type = Database::getConnection()->databaseType();
  162. if ($db_type == 'mysql') {
  163. db_query('SET SESSION group_concat_max_len = 65535');
  164. $fields = array('counter', 'hashlist');
  165. $subquery_aggregates->addExpression('GROUP_CONCAT(DISTINCT aa.aggregate_filenames_hash ORDER BY aa.aggregate_filenames_hash ASC)', 'hashlist');
  166. }
  167. $subquery_aggregates = $subquery_aggregates->fields('aa', array('filename_hash'))
  168. ->groupBy('aa.filename_hash');
  169. // Create main query for the advagg_files table.
  170. $query = db_select('advagg_files', 'af');
  171. $query->join($subquery_aggregates, 'aa', 'af.filename_hash=aa.filename_hash');
  172. $query = $query->fields('af', array(
  173. 'filename',
  174. 'filesize',
  175. 'mtime',
  176. 'changes',
  177. 'linecount',
  178. 'filename_hash',
  179. ))
  180. ->fields('aa', $fields)
  181. ->orderBy('aa.counter', 'DESC');
  182. $query->comment('Query called from ' . __FUNCTION__ . '()');
  183. $results = $query->execute();
  184. $analysis = array();
  185. foreach ($results as $row) {
  186. // Implement slower GROUP_CONCAT functionality for non mysql databases.
  187. if (empty($row->hashlist)) {
  188. $subquery_aggregates_versions = db_select('advagg_aggregates_versions', 'aav')
  189. ->fields('aav')
  190. ->condition('aav.root', 1)
  191. ->condition('aav.atime', REQUEST_TIME - ADVAGG_BUNDLER_OUTDATED, '>');
  192. $subquery_aggregates = db_select('advagg_aggregates', 'aa');
  193. $subquery_aggregates->join($subquery_aggregates_versions, 'aav', 'aav.aggregate_filenames_hash=aa.aggregate_filenames_hash');
  194. $subquery_aggregates = $subquery_aggregates->fields('aa', array('aggregate_filenames_hash'))
  195. ->condition('aa.filename_hash', $row->filename_hash)
  196. ->groupBy('aa.aggregate_filenames_hash')
  197. ->orderBy('aa.aggregate_filenames_hash', 'ASC');
  198. $subquery_aggregates->comment('Query called from ' . __FUNCTION__ . '()');
  199. $aa_results = $subquery_aggregates->execute();
  200. $aa_rows = array();
  201. foreach ($aa_results as $aa_row) {
  202. $aa_rows[] = $aa_row->aggregate_filenames_hash;
  203. }
  204. $row->hashlist = implode(',', $aa_rows);
  205. }
  206. $analysis[$row->filename] = array(
  207. 'group_hash' => $row->counter . ' ' . drupal_hash_base64($row->hashlist),
  208. 'mtime' => $row->mtime,
  209. 'filesize' => $row->filesize,
  210. 'linecount' => $row->linecount,
  211. 'changes' => $row->changes,
  212. );
  213. }
  214. arsort($analysis);
  215. // Invoke hook_advagg_bundler_analysis_alter() to give installed modules a
  216. // chance to alter the analysis array.
  217. drupal_alter('advagg_bundler_analysis', $analysis);
  218. // Save results to the cache.
  219. cache_set($ideal_cid, $analysis, 'cache_advagg_aggregates', CACHE_TEMPORARY);
  220. }
  221. else {
  222. $analysis = $cache->data;
  223. }
  224. }
  225. // If no filename is given pass back then entire query results.
  226. if (empty($filename)) {
  227. return $analysis;
  228. }
  229. // Return a key to be used in groupings.
  230. if (!empty($analysis[$filename])) {
  231. return $analysis[$filename];
  232. }
  233. // We need to return a value that can be used as an array key if the query
  234. // didn't give us anything.
  235. return 0;
  236. }