advagg_bundler.module

  1. nittany7 modules/contrib/advagg/advagg_bundler/advagg_bundler.module
  2. cis7 modules/contrib/advagg/advagg_bundler/advagg_bundler.module
  3. mooc7 modules/contrib/advagg/advagg_bundler/advagg_bundler.module

Advanced aggregation bundler module.

Functions

Namesort descending Description
advagg_bundler_advagg_hooks_implemented_alter Implement 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 Implement hook_form_FORM_ID_alter.
advagg_bundler_init Implement hook_init.
advagg_bundler_menu Implement 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

modules/contrib/advagg/advagg_bundler/advagg_bundler.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Advanced aggregation bundler module.
  5. *
  6. */
  7. /**
  8. * Default value of the maximum number of CSS bundles that can be generated in
  9. * a single request.
  10. */
  11. define('ADVAGG_BUNDLER_MAX_CSS', 4);
  12. /**
  13. * Default value of the maximum number of JS bundles that can be generated in
  14. * a single request.
  15. */
  16. define('ADVAGG_BUNDLER_MAX_JS', 4);
  17. /**
  18. * Default value of the last used time before the bundle is considered outdated.
  19. * 2 weeks in seconds.
  20. */
  21. define('ADVAGG_BUNDLER_OUTDATED', 1209600);
  22. /**
  23. * Default value to see if the bundler should be active or passive. If it is
  24. * passive, the bundler will only do analysis and not split up the aggregate.
  25. */
  26. define('ADVAGG_BUNDLER_ACTIVE', TRUE);
  27. /**
  28. * Implement hook_menu.
  29. */
  30. function advagg_bundler_menu() {
  31. $items = array();
  32. $file_path = drupal_get_path('module', 'advagg_bundler');
  33. $config_path = advagg_admin_config_root_path();
  34. $items[$config_path . '/advagg/bundler'] = array(
  35. 'title' => 'Bundler',
  36. 'description' => 'Adjust Bundler settings.',
  37. 'page callback' => 'drupal_get_form',
  38. 'page arguments' => array('advagg_bundler_admin_settings_form'),
  39. 'type' => MENU_LOCAL_TASK,
  40. 'access arguments' => array('administer site configuration'),
  41. 'file path' => $file_path,
  42. 'file' => 'advagg_bundler.admin.inc',
  43. 'weight' => 10,
  44. );
  45. return $items;
  46. }
  47. /**
  48. * Implement hook_advagg_hooks_implemented_alter.
  49. */
  50. function advagg_bundler_advagg_hooks_implemented_alter(&$hooks, $all) {
  51. if ($all) {
  52. $hooks['advagg_bundler_analysis_alter'] = array();
  53. }
  54. }
  55. /**
  56. * Implement hook_init.
  57. */
  58. function advagg_bundler_init() {
  59. if (advagg_bundler_enabled()) {
  60. $GLOBALS['conf']['advagg_core_groups'] = FALSE;
  61. }
  62. }
  63. /**
  64. * Implement hook_form_FORM_ID_alter.
  65. */
  66. function advagg_bundler_form_advagg_admin_settings_form_alter(&$form, $form_state) {
  67. if (advagg_bundler_enabled()) {
  68. $form['global']['advagg_core_groups']['#disabled'] = TRUE;
  69. $form['global']['advagg_core_groups']['#description'] = t('The bundler submodule disables core grouping logic.');
  70. }
  71. }
  72. /**
  73. * Returns TRUE if the bundler will run.
  74. */
  75. function advagg_bundler_enabled() {
  76. 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))) {
  77. return TRUE;
  78. }
  79. }
  80. /**
  81. * Given a filename return a bundle key.
  82. *
  83. * @param $filename
  84. * filename
  85. * @param $force
  86. * bypass the cache and get a fresh version of the analysis.
  87. * @return
  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. // Create join query for the advagg_aggregates_versions table.
  150. // 1209600 = 2 weeks.
  151. $subquery_aggregates_versions = db_select('advagg_aggregates_versions', 'aav')
  152. ->fields('aav')
  153. ->condition('aav.root', 1)
  154. ->condition('aav.atime', REQUEST_TIME - ADVAGG_BUNDLER_OUTDATED, '>');
  155. // Create join query for the advagg_aggregates table.
  156. $subquery_aggregates = db_select('advagg_aggregates', 'aa');
  157. $subquery_aggregates->join($subquery_aggregates_versions, 'aav', 'aav.aggregate_filenames_hash=aa.aggregate_filenames_hash');
  158. $subquery_aggregates->addExpression("LPAD(CAST(COUNT(aav.aggregate_filenames_hash) AS char(8)), 8, '0')", 'counter');
  159. $subquery_aggregates = $subquery_aggregates->fields('aav', array('aggregate_filenames_hash'))
  160. ->fields('aa', array('filename_hash', 'porder'))
  161. ->groupBy('aa.filename_hash');
  162. // Create main query for the advagg_files table.
  163. $query = db_select('advagg_files', 'af');
  164. $query->join($subquery_aggregates, 'aa', 'af.filename_hash=aa.filename_hash');
  165. $query = $query->fields('af', array('filename', 'filesize', 'mtime', 'changes', 'linecount'))
  166. ->fields('aa', array('counter', 'aggregate_filenames_hash'))
  167. ->orderBy('aa.counter', 'DESC')
  168. ->orderBy('aa.aggregate_filenames_hash', 'ASC')
  169. ->orderBy('aa.porder', 'ASC');
  170. $results = $query->execute();
  171. $analysis = array();
  172. foreach ($results as $row) {
  173. $analysis[$row->filename] = array(
  174. 'group_hash' => $row->counter . ' ' . $row->aggregate_filenames_hash,
  175. 'mtime' => $row->mtime,
  176. 'filesize' => $row->filesize,
  177. 'linecount' => $row->linecount,
  178. 'changes' => $row->changes,
  179. );
  180. }
  181. // Invoke hook_advagg_bundler_analysis_alter() to give installed modules a
  182. // chance to alter the analysis array.
  183. drupal_alter('advagg_bundler_analysis', $analysis);
  184. // Save results to the cache.
  185. cache_set($ideal_cid, $analysis, 'cache_advagg_aggregates', CACHE_TEMPORARY);
  186. }
  187. else {
  188. $analysis = $cache->data;
  189. }
  190. }
  191. // If no filename is given pass back then entire query results.
  192. if (empty($filename)) {
  193. return $analysis;
  194. }
  195. // Return a key to be used in groupings.
  196. if (!empty($analysis[$filename])) {
  197. return $analysis[$filename];
  198. }
  199. // We need to return a value that can be used as an array key if the query
  200. // didn't give us anything.
  201. return 0;
  202. }