acquia_purge.module in Acquia Purge 7
Same filename and directory in other branches
Acquia Purge, Top-notch Varnish purging on Acquia Cloud!
File
acquia_purge.moduleView source
<?php
/**
* @file
* Acquia Purge, Top-notch Varnish purging on Acquia Cloud!
*/
/**
* The current module version.
*/
define('ACQUIA_PURGE_VERSION', '7.x-1.4-DEVELOPMENT');
/**
* Cache ID prefix string.
*
* All calls to cache_get()/cache_set() in this module are prefixed with this
* constant, which contains the current version number. This helps upgrading
* users that don't clear their caches greatly and makes changing code easier.
*/
define('ACQUIA_PURGE_CID_PREFIX', 'acquia_purge_714');
/**
* File on disk to store our state data in (if memcached disabled).
*/
define('ACQUIA_PURGE_STATE_FILE', 'public://acquia_purge_state.raw');
/**
* Memcached key used to store our state data in (if enabled).
*/
define('ACQUIA_PURGE_STATE_MEMKEY', 'acquia_purge_state');
/**
* Memcached bin used to store our state data in memcached (if enabled).
*/
define('ACQUIA_PURGE_STATE_MEMBIN', 'acquia_purge');
/**
* Diagnostic severity levels: Informational.
*/
define('ACQUIA_PURGE_SEVLEVEL_INFO', -1);
/**
* Diagnostic severity levels: Good condition.
*/
define('ACQUIA_PURGE_SEVLEVEL_OK', 0);
/**
* Diagnostic severity levels: Warning condition, proceed but flag warning.
*/
define('ACQUIA_PURGE_SEVLEVEL_WARNING', 1);
/**
* Requirement severity: Error condition, do not purge items in the queue.
*/
define('ACQUIA_PURGE_SEVLEVEL_ERROR', 2);
/**
* Load deprecation wrappers introduced in 7.x-1.2, 7.x-1.3 and 7.x-1.4.
*
* It is costly to carry barely used function definitions, yet at the other hand
* it prevents users upgrading their sites from just breaking. It has been
* considered to load the deprecated wrappers from hook_init or even hook_boot,
* but the code was defined in this file before and could still mean too late.
*
* THIS FILE WILL BE DELETED IN 7.X-1.5 - SO PORT YOUR INTEGRATION CODE NOW!!
*/
require_once dirname(__FILE__) . '/acquia_purge.deprecated.inc';
/**
* Implements hook_init().
*/
function acquia_purge_init() {
_acquia_purge_service()
->processors()
->emit('onInit');
}
/**
* Implements hook_permission().
*/
function acquia_purge_permission() {
return array(
'purge on-screen' => array(
'title' => t('Purge on-screen'),
'description' => t('Allow user to see purges as they are processed. Includes text and a progress bar.'),
),
'use manual purge blocks' => array(
'title' => t('Use manual purge blocks'),
'description' => t('Allows editors to utilize the "Manual purge form (current page)" and "Manual purge form (paths)" blocks.'),
),
);
}
/**
* Implements hook_cron().
*/
function acquia_purge_cron() {
_acquia_purge_service()
->processors()
->emit('onCron');
}
/**
* Implements hook_menu().
*/
function acquia_purge_menu() {
$items = array();
_acquia_purge_service()
->processors()
->emit('onMenu', $items);
// Define the autocomplete callback for the administration forms.
$items['acquia_purge_ajax_autocomplete'] = array(
'type' => MENU_CALLBACK,
'page callback' => 'acquia_purge_autocomplete',
'access arguments' => array(
'purge on-screen',
),
'file' => 'acquia_purge.admin.inc',
);
// Turn Expire's configuration section into a tabbed interface and add a fake
// 'Performance' tab, which will redirect to core's form. Then add our full
// manual purge form as last tab.
$items['admin/config/system/expire/performance'] = array(
'type' => MENU_LOCAL_TASK,
'title' => 'Performance',
'weight' => -20,
'page callback' => 'drupal_goto',
'page arguments' => array(
'admin/config/development/performance',
),
'access arguments' => array(
'administer site configuration',
),
);
$items['admin/config/system/expire/default'] = array(
'title' => 'Cache Expiration',
'type' => MENU_DEFAULT_LOCAL_TASK,
'file path' => drupal_get_path('module', 'expire'),
'weight' => -5,
);
$items['admin/config/system/expire/manualpurge'] = array(
'type' => MENU_LOCAL_TASK,
'title' => 'Manual purge',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'acquia_purge_manualpurge_form_full',
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'acquia_purge.admin.inc',
);
// We'll also do the opposite here, by replicating the tabs from above on
// core's 'Performance' tab, but by letting them redirect back to the 'Cache
// Expiration' and 'Manual purge' tabs as admin/config/system/expire.
$items['admin/config/development/performance/default'] = array(
'title' => 'Performance',
'type' => MENU_DEFAULT_LOCAL_TASK,
'file path' => drupal_get_path('module', 'system'),
'weight' => -5,
);
$items['admin/config/development/performance/expire'] = array(
'type' => MENU_LOCAL_TASK,
'title' => 'Cache Expiration',
'page callback' => 'drupal_goto',
'page arguments' => array(
'admin/config/system/expire',
),
'access arguments' => array(
'administer site configuration',
),
);
$items['admin/config/development/performance/manualpurge'] = array(
'type' => MENU_LOCAL_TASK,
'title' => 'Manual purge',
'page callback' => 'drupal_goto',
'page arguments' => array(
'admin/config/system/expire/manualpurge',
),
'access arguments' => array(
'administer site configuration',
),
);
return $items;
}
/**
* Implements hook_expire_cache().
*/
function acquia_purge_expire_cache($urls, $wildcards, $object_type, $object) {
// When running in passive mode, we stop automatic queuing.
if (_acquia_purge_variable('acquia_purge_passivemode')) {
return;
}
// Check for errors once, but refuse operation during the entire request.
static $error;
if (is_null($error)) {
$diagnostics = _acquia_purge_service()
->diagnostics();
if ($diagnostics
->isSystemBlocked()) {
$errors = $diagnostics
->get(ACQUIA_PURGE_SEVLEVEL_ERROR);
$diagnostics
->log($errors);
// Only visualize errors when the user has permission and isn't silenced.
$notsilent = !_acquia_purge_variable('acquia_purge_silentmode');
$notcli = php_sapi_name() !== 'cli';
if ($notsilent && $notcli && user_access('purge on-screen')) {
foreach ($errors as $i => $error) {
$errors[$i] = '<p>' . $error['description'] . '</p>';
}
drupal_set_message(t("<p>The system cannot publicly refresh the changes you just made,\n because of the following error conditions:</p>!items<p>Please\n contact your system administrator or development partner!</p>", array(
'!items' => theme('item_list', array(
'items' => $errors,
)),
)), 'error');
}
}
}
if ($error) {
return;
}
// Add '<front>' to the list as empty strings don't pass validation.
if (in_array('', $urls)) {
$urls['<front>'] = '<front>';
}
// Now test every item against our strict validation checks.
foreach ($urls as $id => $path) {
if (_acquia_purge_input_validate($path)) {
unset($urls[$id]);
}
elseif (_acquia_purge_variable('acquia_purge_trim_slashes')) {
$urls[$id] = rtrim($path, '/');
}
else {
$urls[$id] = $path;
}
}
// Queue all paths that we received from Expire.
_acquia_purge_service()
->addPaths($urls);
}
/**
* Implements hook_form_BASE_FORM_ID_alter().
*/
function acquia_purge_form_expire_admin_settings_form_alter(&$form, &$form_state, $form_id) {
if (!isset($form['tabs']['status'])) {
return;
}
$form['tabs']['status']['#title'] = t('Acquia Purge overview');
// Remove 'expire_status' and 'expire_debug' from Expire's status tab as we
// really don't want users to change them, UNLESS they need to be changed.
$trouble = array(
(bool) variable_get('expire_include_base_url', EXPIRE_INCLUDE_BASE_URL),
(bool) variable_get('expire_debug', EXPIRE_DEBUG_DISABLED),
intval(variable_get('expire_status', EXPIRE_STATUS_DISABLED)) !== EXPIRE_STATUS_ENABLED_EXTERNAL,
);
if (!in_array(TRUE, $trouble)) {
unset($form['tabs']['status']['common']);
unset($form['tabs']['status']['debug']);
}
// Add a full-blown status report on how Acquia Purge is doing.
$form['tabs']['status']['ap_status'] = array(
'#markup' => theme('acquia_purge_status_report', array(
'diagnostics' => _acquia_purge_service()
->diagnostics()
->get(),
)),
'#type' => 'item',
);
}
/**
* Implements hook_form_BASE_FORM_ID_alter().
*/
function acquia_purge_form_system_performance_settings_alter(&$form, &$form_state, $form_id) {
$form['clear_cache']['clear_acquia_purge'] = array(
'#type' => 'submit',
'#value' => t('Clear the Acquia Purge queue'),
'#weight' => 100,
'#submit' => array(
'acquia_purge_form_system_performance_settings_submit',
),
);
}
/**
* Form submit callback.
*
* @see acquia_purge_form_system_performance_settings_alter()
*/
function acquia_purge_form_system_performance_settings_submit($form, &$form_state) {
$service = _acquia_purge_service();
drupal_set_message(t("Removed @remaining items from the queue.", array(
'@remaining' => $service
->stats('remaining'),
)));
$service
->clear();
}
/**
* Implements hook_block_info().
*/
function acquia_purge_block_info() {
return array(
'page' => array(
'info' => t('Manual purge form (current page)'),
'cache' => DRUPAL_NO_CACHE,
'status' => 0,
'weight' => 1,
'region' => 'sidebar_first',
'visibility' => 0,
'properties' => array(
'administrative' => TRUE,
),
),
'paths' => array(
'info' => t('Manual purge form (paths)'),
'cache' => DRUPAL_NO_CACHE,
'status' => 0,
'weight' => 1,
'region' => 'sidebar_first',
'visibility' => 0,
'properties' => array(
'administrative' => TRUE,
),
),
);
}
/**
* Implements hook_block_view().
*/
function acquia_purge_block_view($delta = '') {
// Render one of the manual purge blocks.
if (in_array($delta, array(
'page',
'paths',
))) {
if (!user_access('use manual purge blocks')) {
return array();
}
if ($_GET['q'] == 'admin/config/development/performance/manualpurge') {
return array();
}
if (_acquia_purge_service()
->diagnostics()
->isSystemBlocked()) {
return array();
}
// Load acquia_purge.admin.inc to be able to call our form callback.
module_load_include('inc', 'acquia_purge', 'acquia_purge.admin');
return array(
'subject' => $delta === 'paths' ? t('Refresh paths') : NULL,
'content' => drupal_get_form("acquia_purge_manualpurge_form_{$delta}"),
);
}
return array();
}
/**
* Implements hook_acquia_purge_diagnostics().
*/
function acquia_purge_acquia_purge_diagnostics() {
return array(
'_acquia_purge_diagnostics_status',
'_acquia_purge_diagnostics_acquia_purge',
'_acquia_purge_diagnostics_acquia_environment',
'_acquia_purge_diagnostics_acquia_auth_token',
'_acquia_purge_diagnostics_backends_statestorage',
'_acquia_purge_diagnostics_backends_processor',
'_acquia_purge_diagnostics_backends_executor',
'_acquia_purge_diagnostics_backends_queue',
'_acquia_purge_diagnostics_inv_schemes',
'_acquia_purge_diagnostics_inv_domains',
'_acquia_purge_diagnostics_inv_balancers',
'_acquia_purge_diagnostics_expire_module',
'_acquia_purge_diagnostics_page_cache',
'_acquia_purge_diagnostics_page_caching_time_ttl',
'_acquia_purge_diagnostics_capacity',
'_acquia_purge_diagnostics_logging',
'_acquia_purge_diagnostics_queue_safety',
'_acquia_purge_diagnostics_queue',
'module_load_include' => array(
'inc',
'acquia_purge',
'acquia_purge.diagnostics',
),
);
}
/**
* Implements hook_theme().
*/
function acquia_purge_theme($existing, $type, $theme, $path) {
return array(
'acquia_purge_status_bar_widget' => array(
'variables' => array(
'total' => 0,
'remaining' => 0,
'good' => 0,
'bad' => 0,
'percent' => 100,
'running' => FALSE,
'purgehistory' => array(),
),
'file' => 'acquia_purge.admin.inc',
),
'acquia_purge_status_report' => array(
'variables' => array(
'requirements' => array(),
),
'file' => 'acquia_purge.admin.inc',
),
'acquia_purge_status_widget' => array(
'variables' => array(
'total' => 0,
'remaining' => 0,
'good' => 0,
'bad' => 0,
'percent' => 100,
'running' => FALSE,
'purgehistory' => array(),
),
'file' => 'acquia_purge.admin.inc',
),
);
}
/**
* Implements hook_exit().
*/
function acquia_purge_exit() {
_acquia_purge_service()
->processors()
->emit('onExit');
}
/**
* Perform necessary string cleaning on a provided path string.
*
* Whenever working with user input it is required to first validate
* with _acquia_purge_input_validate() before cleaning it.
*
* @param string $path
* The Drupal path (for example: '<front>', 'user/1' or a alias).
*
* @return string
* The cleaned version of the path.
*/
function _acquia_purge_input_clean($path) {
if (!is_string($path)) {
return '';
}
$path = trim($path);
if (empty($path) || $path === '/') {
return '';
}
// Remove double slashes that might occur in strings.
$path = str_replace('//', '/', $path);
// Remove leading slashes as we add those in later too.
$path = ltrim($path, '/');
// Rewrite '<front>' to '', which will always be the frontpage. By using
// substr() and str_replace() we still allow cases like '<front>?param=1'.
if (drupal_substr($path, 0, 7) === '<front>') {
$path = str_replace('<front>', '', $path);
}
return $path;
}
/**
* Make up variations on the given paths for lazier administrative cleaning.
*
* As every URL gets uniquely cached, purging a path like 'news' will not purge
* potentially existing variations like 'news/' or 'news?page=0'. This helper
* is only meant to be used in places where an administrator is manually
* purging a few paths, for instance through Drush or the manual purge form.
*
* @param array $paths
* Non-associative array with Drupal paths like '<front>' or 'user/1'.
* @param string $path
* (optional) INTERNAL, don't use directly! Used to add made up variations to
* the list by reference and to prevent duplicate paths.
*
* @see acquia_purge_manualpurge_form_submit()
* @see drush_acquia_purge_ap_purge()
*/
function _acquia_purge_input_path_variations(array &$paths, $path = NULL) {
// Are we supposed to just add a path to $paths? This only happens as we call
// ourselves here, a closure would have been better but that's PHP 5.3 :(.
if (!is_null($path)) {
if (!in_array($path, $paths)) {
$paths[] = $path;
}
return;
}
// Alias this function as $add, which reads better because of what it does.
$add = __FUNCTION__;
// Iterate all paths, build up $variations for every path and allow other
// modules to alter the variations. Then add all variations to $paths_new.
$paths_new = array();
foreach ($paths as $path) {
$path_original = $path;
$path_has_wildcard = strpos($path_original, '*') !== FALSE;
$variations = array();
// Begin all the madness by splitting the path by parameter.
$path = explode('?', _acquia_purge_input_clean($path));
$path[0] = rtrim($path[0], '/');
$add($variations, $path[0]);
if (!$path_has_wildcard) {
$add($variations, $path[0] . '/');
}
if (module_exists('path')) {
$add($variations, drupal_get_path_alias($path[0]));
$add($variations, drupal_get_normal_path($path[0]));
if (!$path_has_wildcard) {
$add($variations, drupal_get_path_alias($path[0]) . '/');
$add($variations, drupal_get_normal_path($path[0]) . '/');
}
}
if (isset($path[1])) {
$add($variations, implode('?', $path));
$add($variations, str_replace('?', '/?', implode('?', $path)));
$path_0 = $path[0];
$path[0] = drupal_get_path_alias($path_0);
$add($variations, implode('?', $path));
$path[0] = drupal_get_normal_path($path_0);
$add($variations, implode('?', $path));
if (!$path_has_wildcard) {
$path[0] = drupal_get_path_alias($path_0) . '/';
$add($variations, implode('?', $path));
$path[0] = drupal_get_normal_path($path_0) . '/';
$add($variations, implode('?', $path));
}
}
// Let hook_acquia_purge_variations_alter() implementations edit the list.
foreach (module_implements('acquia_purge_variations_alter') as $module) {
$function = $module . '_acquia_purge_variations_alter';
$function($path_original, $variations);
}
// Now pump all those variations over into $paths_new.
foreach ($variations as $variation) {
$add($paths_new, $variation);
}
}
$paths = $paths_new;
}
/**
* Validate a user provided path string.
*
* @param string $path
* The Drupal path (for example: '<front>', 'user/1' or a alias).
*
* @return false|string
* FALSE on success (!!) or a translated string describing what's wrong with
* the given user input.
*/
function _acquia_purge_input_validate($path) {
static $history;
if (is_null($history)) {
$history = array();
}
// Start all the validation checks.
if (empty($path)) {
return _acquia_purge_input_validate_msgs('empty');
}
if (!is_string($path)) {
return _acquia_purge_input_validate_msgs('nostring');
}
if (stristr($path, 'http:') || stristr($path, 'https:')) {
return _acquia_purge_input_validate_msgs('url');
}
if (preg_match('/\\s/', $path)) {
return _acquia_purge_input_validate_msgs('space');
}
if (in_array($path, $history)) {
return _acquia_purge_input_validate_msgs('double');
}
// All tests passed, remember it for future duplication testing.
$history[] = $path;
return FALSE;
}
/**
* Retrieve validation messages on user provided path strings.
*
* @param string $msg
* The message you would like to retrieve, see implementation.
*
* @return string|null
* Returns a fully translated string, or NULL.
*
* @see _acquia_purge_input_validate()
*/
function _acquia_purge_input_validate_msgs($msg) {
static $messages;
if (is_null($messages)) {
$messages = array();
$messages['space'] = t('The path cannot contain a space!');
$messages['double'] = t('You have already listed this path!');
$messages['nostring'] = t('The path is not a string!');
$messages['url'] = t('You provided a URL which is not compatible with the way Acquia Purge works, as it constructs full URLs for its configured domains.');
$messages['empty'] = t('The path cannot be empty, if you intended to purge the frontpage of your site, use "/" or "!front".', array(
'!front' => php_sapi_name() === 'cli' ? '<front>' : '<front>',
));
}
return isset($messages[$msg]) ? $messages[$msg] : NULL;
}
/**
* Load code on which Acquia Purge depends.
*
* This function is a complex code loader and dependency injection container for
* Acquia Purge's object oriented core, which got introduced in 7.x-1.3. From
* files listed in acquia_purge.info, a "service name" is derived that is used
* as primary $dependency value throughout the Acquia Purge code.
*
* This "dependency name" is generated by _acquia_purge_registry() and gets then
* fed to _acquia_purge_variable(). The latter comes up with the default class
* name or a file path when the dependency name is overridden using the variable
* system. This allows all classes to be swapped from settings.php like this:
* - $conf['_acquia_purge_service'] = "sites/all/modules/custommodule/s.php";
* - $conf['_acquia_purge_hosting_info'] = "sites.../myhostinginfo.php";
*
* In order to find all default services and the classes they point to, run:
* $ drush php-eval "print_r(_acquia_purge_registry()['services']);"
*
* The name of the derived file is assumed to also be the name of the class it
* contains, so if the "_acquia_purge_executors" service is pointed to the
* path "sites/all/modules/my/MyExecutor.php", the returned $class value is
* going to be "MyExecutor". Acquia Purge will instantiate that class by its
* derived name, so make sure to not just copy a file but rename the class!
*
* @param string|string[] $dependency
* - string[]: Unassociative array of dependencies, the last sets the class.
* - string: a relative or absolute file path (must contain '.' character).
* - string: dependency name derived from acquia_purge.info, see the drush
* command hereabove to find the possible values.
*
* @return string
* The name of the class defined in the requested dependency.
*
* @see _acquia_purge_registry
*/
function _acquia_purge_load($dependency) {
// When $dependency is an array, load all items and return the last class.
if (is_array($dependency)) {
foreach ($dependency as $subdependency) {
$class = _acquia_purge_load($subdependency);
}
return $class;
}
// Initialize statically cached variables.
static $path_module, $loaded;
if (is_null($path_module)) {
require_once DRUPAL_ROOT . '/includes/common.inc';
require_once DRUPAL_ROOT . '/' . variable_get('path_inc', 'includes/path.inc');
require_once DRUPAL_ROOT . '/includes/cache.inc';
require_once DRUPAL_ROOT . '/includes/unicode.inc';
$path_module = DRUPAL_ROOT . '/' . drupal_get_path('module', 'acquia_purge');
}
if (is_null($loaded)) {
$loaded = array();
}
// Retrieve the code registry.
$registry = _acquia_purge_registry();
// SERVICES: lookup the actual class and file and recurse.
$dependency_is_a_service = !(strpos($dependency, '.') !== FALSE);
if ($dependency_is_a_service) {
$class_or_path = _acquia_purge_variable($dependency);
if (!(strpos($class_or_path, '.') !== FALSE)) {
$path_index = $registry['classes'][$class_or_path];
$class_or_path = $registry['paths'][$path_index];
}
if (!(strpos($class_or_path, '.') !== FALSE)) {
throw new LogicException("{$variable} doesn't point to a class known to AP or a file on disk.");
}
return _acquia_purge_load($class_or_path);
}
elseif (strpos($dependency, 'lib/') === 0) {
$dependency = $path_module . '/' . $dependency;
// The files in acquia_purge.info are ordered by dependency order, so we
// always load files defined prior to our dependency.
$load_up_to_index = FALSE;
foreach ($registry['paths'] as $index => $path) {
$path = $path_module . '/' . $path;
if (strpos($dependency, $path) === 0) {
$load_up_to_index = $index;
}
}
if ($load_up_to_index) {
foreach ($registry['paths'] as $index => $path) {
$path = $path_module . '/' . $path;
if (in_array($path, $loaded)) {
continue;
}
if ($index < $load_up_to_index) {
_acquia_purge_load($path);
}
}
}
return _acquia_purge_load($dependency);
}
else {
if (!in_array($dependency, $loaded)) {
$loaded[] = $dependency;
require_once $dependency;
}
// Return the classname which to help instantiating it.
return str_replace('.php', '', basename($dependency));
}
}
/**
* Manual purge form: require inclusion wrapper.
*
* @see __acquia_purge_manualpurge_add()
*/
function _acquia_purge_manualpurge_add($form, &$form_state) {
module_load_include('inc', 'acquia_purge', 'acquia_purge.admin');
return __acquia_purge_manualpurge_add($form, $form_state);
}
/**
* Manual purge form: require inclusion wrapper.
*
* @see __acquia_purge_manualpurge_remove()
*/
function _acquia_purge_manualpurge_remove($form, &$form_state) {
module_load_include('inc', 'acquia_purge', 'acquia_purge.admin');
return __acquia_purge_manualpurge_remove($form, $form_state);
}
/**
* Manual purge form: require inclusion wrapper.
*
* @see __acquia_purge_manualpurge_paths()
*/
function _acquia_purge_manualpurge_paths($form, &$form_state) {
module_load_include('inc', 'acquia_purge', 'acquia_purge.admin');
return __acquia_purge_manualpurge_paths($form, $form_state);
}
/**
* Manual purge form: require inclusion wrapper.
*
* @see __acquia_purge_manualpurge_validate()
*/
function _acquia_purge_manualpurge_validate($form, &$form_state) {
module_load_include('inc', 'acquia_purge', 'acquia_purge.admin');
return __acquia_purge_manualpurge_validate($form, $form_state);
}
/**
* Manual purge form: require inclusion wrapper.
*
* @see __acquia_purge_manualpurge_add()
*/
function _acquia_purge_manualpurge_submit($form, &$form_state) {
module_load_include('inc', 'acquia_purge', 'acquia_purge.admin');
return __acquia_purge_manualpurge_submit($form, $form_state);
}
/**
* Retrieve the Acquia Purge code registry.
*
* Although Drupal 7 has its own code registry, we can't rely on it without
* taking the risk of breaking upgrading sites. Since we introduced an object
* oriented core in 7.x-1.3, all the legacy code got decoupled into many
* different classes.
*
* The registry is simple and has low overhead. It parses acquia_purge.info once
* the parsed information is stored using cache_set(). Everytime changes are
* made to acquia_purge.info, the '_v<N>' cache key is manually changed to let
* upgrading users automatically rebuild it.
*
* @return array[]
* Acquia Purge code registry array, with the following keys:
* - 'classes': assoc. array with class names as key, path-array as value.
* - 'services': assoc. array with service names as key, classes as value.
* - 'paths': array with path names, key's are referred to from 'classes'.
*
* @see acquia_purge.info
* @see _acquia_purge_load
*/
function _acquia_purge_registry() {
static $registry;
if (is_null($registry)) {
$cache_key = ACQUIA_PURGE_CID_PREFIX . '_registry';
if ($cache = cache_get($cache_key)) {
$registry = $cache->data;
}
else {
// Parse the module's .info file to retrieve all registered files.
require_once DRUPAL_ROOT . '/includes/common.inc';
$path = drupal_get_path('module', 'acquia_purge') . '/acquia_purge.info';
$info = drupal_parse_info_file($path);
// Begin the registry's datastructure.
$registry = array(
'classes' => array(),
'services' => array(),
'paths' => array(),
);
// Add each files[] row in the .info file, to the $registry variable.
foreach ($info['files'] as $path) {
// Add the class with the number of paths so far as orderable ID.
$class = str_replace('.php', '', basename($path));
$registry['classes'][$class] = count($registry['paths']);
// Add the path to the second listing.
$registry['paths'][] = $path;
// Generate a service name based on the class by applying a few rules.
$service = str_replace('AcquiaPurge', '', $class);
$service = preg_replace('/(?<!^)[A-Z]/', '_$0', $service);
$service = str_replace('_service', '', drupal_strtolower($service));
$registry['services']['_acquia_purge_' . $service] = $class;
}
cache_set($cache_key, $registry);
}
}
return $registry;
}
/**
* Retrieve the global AcquiaPurgeService instance.
*
* @return AcquiaPurgeService
* The Acquia Purge service object.
*/
function _acquia_purge_service() {
static $service;
if (is_null($service)) {
$class = _acquia_purge_load('_acquia_purge_service');
$service = new $class();
}
return $service;
}
/**
* Retrieve a Drupal variable or its default.
*
* The sole reason this helper exists is to prevent a wilderness of direct calls
* to variable_get() and to mitigate the risk of different default values. In
* Drupal 8, this problem is addressed in its shiny configuration API but here
* we have to deal with it this way by keeping all defaults in one place.
*
* @param string $name
* The name of the variable to return.
*
* @see variable_get()
*
* @return bool|string|array
* The value of the variable or its default.
*/
function _acquia_purge_variable($name) {
static $defaults;
if (is_null($defaults)) {
// All default variable values, see INSTALL.md as well for further info.
$defaults = array(
'acquia_purge_domains' => FALSE,
'acquia_purge_sphpskippath' => TRUE,
'acquia_purge_stripports' => array(
80,
443,
8080,
),
'acquia_purge_cron' => TRUE,
'acquia_purge_lateruntime' => FALSE,
'acquia_purge_http' => TRUE,
'acquia_purge_https' => FALSE,
'acquia_purge_token' => FALSE,
// For the usage of $GLOBALS, see https://www.drupal.org/node/2506881.
'acquia_purge_base_path' => $GLOBALS['base_path'],
'acquia_purge_errorlimit' => TRUE,
'acquia_purge_log_success' => TRUE,
'acquia_purge_variations' => TRUE,
'acquia_purge_memcache' => TRUE,
'acquia_purge_trim_slashes' => TRUE,
'acquia_purge_passivemode' => FALSE,
'acquia_purge_silentmode' => FALSE,
'acquia_purge_allriskmode' => FALSE,
'acquia_purge_smartqueue' => FALSE,
);
// Add all code registry services so that these can be overloaded.
foreach (_acquia_purge_registry()['services'] as $service => $dfltclass) {
$defaults[$service] = $dfltclass;
}
}
// Be explicit about requested variables we don't know about.
if (!isset($defaults[$name])) {
throw new Exception("_acquia_purge_variable: invalid variable '{$name}'!");
}
return variable_get($name, $defaults[$name]);
}
Functions
Constants
Name | Description |
---|---|
ACQUIA_PURGE_CID_PREFIX | Cache ID prefix string. |
ACQUIA_PURGE_SEVLEVEL_ERROR | Requirement severity: Error condition, do not purge items in the queue. |
ACQUIA_PURGE_SEVLEVEL_INFO | Diagnostic severity levels: Informational. |
ACQUIA_PURGE_SEVLEVEL_OK | Diagnostic severity levels: Good condition. |
ACQUIA_PURGE_SEVLEVEL_WARNING | Diagnostic severity levels: Warning condition, proceed but flag warning. |
ACQUIA_PURGE_STATE_FILE | File on disk to store our state data in (if memcached disabled). |
ACQUIA_PURGE_STATE_MEMBIN | Memcached bin used to store our state data in memcached (if enabled). |
ACQUIA_PURGE_STATE_MEMKEY | Memcached key used to store our state data in (if enabled). |
ACQUIA_PURGE_VERSION | The current module version. |