diff --git a/docroot/profiles/publisher/modules/contrib/expire/expire.admin.inc b/docroot/profiles/publisher/modules/contrib/expire/expire.admin.inc index b6f19b6..5a1f705 100644 --- a/docroot/profiles/publisher/modules/contrib/expire/expire.admin.inc +++ b/docroot/profiles/publisher/modules/contrib/expire/expire.admin.inc @@ -764,3 +764,225 @@ function expire_node_settings_form(&$form) { // Attach js. $form['#attached']['js'][] = drupal_get_path('module', 'expire') . '/js/expire.admin.js'; } + +/** + * Menu callback to fulfill autocompletes on expire_manualexpire_form. + * + * @returns + * A standard Form API form-array. + */ +function expire_manualexpire_autocomplete($string) { + $query_limit = 10; + $matches = array(); + + // Overwrite $string and work around Drupal buggingly ignoring slashes. + $string = implode('/', array_slice(explode('/', $_GET['q']), 6)); + + // Scan for node/ lookups as they're quite common. + if (substr($string, 0, 1) == 'n') { + $query = db_select('node', 'n') + ->fields('n', array('nid')) + ->range(0, $query_limit); + + // Lookup node IDs if the user entered node/, else limit on 15. + if (strlen($string) > 5) { + $string = (int) str_replace('node/', '', $string); + $query->condition('n.nid', '%' . db_like($string) . '%', 'LIKE'); + } + + $results = $query->execute(); + foreach ($results as $nid) { + $path = 'node/' . $nid->nid; + $matches[] = $path; + } + } + + // Scan for URL aliases when the path module is enabled. + if (module_exists('path')) { + $query = db_select('url_alias', 'u') + ->fields('u', array('alias')) + ->condition('alias', db_like($string) . '%', 'LIKE') + ->range(0, $query_limit) + ->execute(); + foreach ($query as $alias) { + $matches[] = $alias->alias; + } + } + + // Scan for menu_router paths, as long as they don't contain % characters. + if (module_exists('menu')) { + $query = db_select('menu_router', 'm') + ->fields('m', array('path')) + ->condition('path', db_like($string) . '%', 'LIKE') + ->condition('path', 'admin%', 'NOT LIKE') + ->range(0, $query_limit) + ->execute(); + foreach ($query as $path) { + if (strpos($path->path, '%') !== FALSE) { + continue; + } + $matches[] = $path->path; + } + } + + // Sort the values alphabetically. + sort($matches); + + // Rewrite the matches array by copying the values into keys. + $clean_url = variable_get('clean_url', 0); + foreach ($matches as $key => $path) { + if (!$clean_url) { + $path = "index.php?q=$path"; + } + unset($matches[$key]); + $matches[$path] = $path; + } + + // Return the output JSON'ed. + drupal_json_output($matches); +} + +/** + * Menu callback to drupal_get_form; let users manual expire pages. + * + * @returns + * A standard Form API form-array. + */ +function expire_manualexpire_form($form, &$form_state) { + $form['description'] = array( + '#markup' => t('

This form allows you to expire one or more paths. This + form is not intended for day-to-day use and only meant for site + administrators, for instance in emergency cases when a outdated copy of a + page remains being served. It is highly recommended to automate these + expirations using rules so editorial users can rely on a fully fresh site + instead of relying on this form.

'), + ); + + // Because we have many fields with the same values, we have to set + // #tree to be able to access them. + $form['#tree'] = TRUE; + + // Allow the user to limit expire to selected modules + $modules = drupal_map_assoc(module_implements('expire_cache')); + $form['modules'] = array( + '#type' => 'checkboxes', + '#options' => $modules, + '#title' => t('Limit cache expiration to the following modules'), + '#default_value' => $modules, + ); + + // We'll group all paths both in a HTML wrapper and logically in the form. + $title = t('Paths to be expired:'); + $form['paths'] = array( + '#prefix' => '

' . $title . '

', + ); + + // Fill paths with the right amount of form items according to num_paths. + $ac_path = 'admin/config/system/expire/manualexpire/autocomplete'; + if (empty($form_state['num_paths'])) { + $form_state['num_paths'] = 1; + } + for ($i = 0; $i < $form_state['num_paths']; $i++) { + $form['paths']['path'][$i] = array( + '#type' => 'textfield', + '#autocomplete_path' => $ac_path, + '#size' => 30, + '#prefix' => '
  • ', + '#suffix' => '
  • ', + ); + } + + // Declare the add and remove buttons. + $form['paths']['add_path'] = array( + '#type' => 'submit', + '#value' => t('Add'), + '#submit' => array('expire_manualexpire_form_add_one'), + '#ajax' => array( + 'callback' => 'expire_manualexpire_form_callback', + 'wrapper' => 'paths-wrapper', + ), + ); + if ($form_state['num_paths'] > 1) { + $form['paths']['remove_path'] = array( + '#type' => 'submit', + '#value' => t('Remove last item'), + '#submit' => array('expire_manualexpire_form_remove_one'), + '#limit_validation_errors' => array(), + '#ajax' => array( + 'callback' => 'expire_manualexpire_form_callback', + 'wrapper' => 'paths-wrapper', + ), + ); + } + + // Render the submit button and return the form. + $form['submit'] = array( + '#type' => 'submit', + '#value' => t("I know the risks, expire!"), + ); + return $form; +} + +/** + * Callback to drupal_get_form: the AJAX callback to paths-wrapper. + */ +function expire_manualexpire_form_callback($form, $form_state) { + return $form['paths']; +} + +/** + * Callback to drupal_get_form: add a path textfield. + */ +function expire_manualexpire_form_add_one($form, &$form_state) { + $form_state['num_paths']++; + $form_state['rebuild'] = TRUE; +} + +/** + * Callback to drupal_get_form: remove a path textfield. + */ +function expire_manualexpire_form_remove_one($form, &$form_state) { + if ($form_state['num_paths'] > 1) { + $form_state['num_paths']--; + } + $form_state['rebuild'] = TRUE; +} + +/** + * Callback to drupal_get_form: validate the form. + */ +function expire_manualexpire_form_validate($form, &$form_state) { + $paths = array(); + foreach ($form_state['values']['paths']['path'] as $id => $path) { + if (empty($path)) { + form_set_error('paths][path][' . $id, + t('The path can not be empty, use <front> for your frontpage!')); + } + elseif (!is_string($path)) { + form_set_error('paths][path][' . $id, + t("The path has to be a string!")); + } + elseif (stristr($path, 'http:') || stristr($path, 'https:')) { + form_set_error('paths][path][' . $id, + t("You can't provide a URL, only paths!")); + } + elseif (preg_match('/\s/', $path)) { + form_set_error('paths][path][' . $id, + t('The path can not contain a space!')); + } + elseif (in_array($path, $paths)) { + form_set_error('paths][path][' . $id, + t('You have already listed this path!')); + } + $paths[] = $path; + } +} + +/** + * Callback to drupal_get_form: handle the form submit. + */ +function expire_manualexpire_form_submit($form, &$form_state) { + $modules = array_filter($form_state['values']['modules']); + ExpireAPI::executeExpiration($form_state['values']['paths']['path'], '', NULL, FALSE, $modules); +} diff --git a/docroot/profiles/publisher/modules/contrib/expire/expire.module b/docroot/profiles/publisher/modules/contrib/expire/expire.module index 7d9b294..21bbeef 100644 --- a/docroot/profiles/publisher/modules/contrib/expire/expire.module +++ b/docroot/profiles/publisher/modules/contrib/expire/expire.module @@ -100,10 +100,48 @@ function expire_menu() { 'file' => 'expire.admin.inc', ); + // Default local task for the above menu item. + $items['admin/config/system/expire/default'] = array( + 'title' => 'Cache Expiration', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -5, + ); + + // Allow administrators to manual queue purge paths on the performance page. + $items['admin/config/system/expire/manualexpire'] = array( + 'type' => MENU_LOCAL_TASK, + 'title' => 'Manual expire', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('expire_manualexpire_form'), + 'access arguments' => array('administer site configuration'), + 'file' => 'expire.admin.inc', + ); + + // Autocomplete callback for the manual expire field + $items['admin/config/system/expire/manualexpire/autocomplete'] = array( + 'type' => MENU_CALLBACK, + 'page callback' => 'expire_manualexpire_autocomplete', + 'access arguments' => array('administer site configuration'), + 'file' => 'expire.admin.inc', + ); + return $items; } /** + * Implements hook_menu_alter(). + */ +function expire_menu_alter(&$items) { + // Hide the Acquia Purge Manual Purge admin for if present + if (isset($items['admin/config/development/performance/manualpurge'])) { + unset($items['admin/config/development/performance/manualpurge']); + } + if (isset($items['admin/config/system/expire/manualpurge'])) { + unset($items['admin/config/system/expire/manualpurge']); + } +} + +/** * Implements hook_form_FORM_ID_alter(). */ function expire_form_node_type_form_alter(&$form, &$form_state) { diff --git a/docroot/profiles/publisher/modules/contrib/expire/includes/expire.api.inc b/docroot/profiles/publisher/modules/contrib/expire/includes/expire.api.inc index d49a94f..bdbbbd1 100644 --- a/docroot/profiles/publisher/modules/contrib/expire/includes/expire.api.inc +++ b/docroot/profiles/publisher/modules/contrib/expire/includes/expire.api.inc @@ -21,8 +21,12 @@ class ExpireAPI { * * @param $absolute_urls_passed * Indicates whether absolute URLs or internal paths were passed. + * + * @param $modules + * Array with a list of modules for which to trigger expire. Empty array + * triggers expire on all modules implementing hook_cache_expire. */ - public static function executeExpiration($urls, $object_type = '', $object = NULL, $absolute_urls_passed = FALSE) { + public static function executeExpiration($urls, $object_type = '', $object = NULL, $absolute_urls_passed = FALSE, $modules = array()) { // Allow other modules to modify the list prior to expiring. drupal_alter('expire_cache', $urls, $object_type, $object, $absolute_urls_passed); @@ -83,7 +87,7 @@ class ExpireAPI { self::executeInternalExpiration($urls, $wildcards); } elseif ($status == EXPIRE_STATUS_ENABLED_EXTERNAL) { - self::executeExternalExpiration($urls, $wildcards, $object_type, $object); + self::executeExternalExpiration($urls, $wildcards, $object_type, $object, $modules); } } @@ -124,9 +128,16 @@ class ExpireAPI { * * @param $object * Object (node, comment, user, etc) for which expiration is executes. + * + * @param $modules + * Array with a list of modules for which to trigger expire. Empty array + * triggers expire on all modules implementing hook_cache_expire. */ - protected static function executeExternalExpiration($urls, $wildcards, $object_type, $object) { - $modules = module_implements('expire_cache'); + protected static function executeExternalExpiration($urls, $wildcards, $object_type, $object, $modules = array()) { + // Default to expiring for all modules. + if (empty($modules)) { + $modules = module_implements('expire_cache'); + } foreach ($modules as $module) { module_invoke($module, 'expire_cache', $urls, $wildcards, $object_type, $object); }