core security update
This commit is contained in:
@@ -116,38 +116,62 @@ function image_gd_rotate(stdClass $image, $degrees, $background = NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$width = $image->info['width'];
|
||||
$height = $image->info['height'];
|
||||
// PHP 5.5 GD bug: https://bugs.php.net/bug.php?id=65148: To prevent buggy
|
||||
// behavior on negative multiples of 90 degrees we convert any negative
|
||||
// angle to a positive one between 0 and 360 degrees.
|
||||
$degrees -= floor($degrees / 360) * 360;
|
||||
|
||||
// Convert the hexadecimal background value to a color index value.
|
||||
// Convert the hexadecimal background value to a RGBA array.
|
||||
if (isset($background)) {
|
||||
$rgb = array();
|
||||
for ($i = 16; $i >= 0; $i -= 8) {
|
||||
$rgb[] = (($background >> $i) & 0xFF);
|
||||
}
|
||||
$background = imagecolorallocatealpha($image->resource, $rgb[0], $rgb[1], $rgb[2], 0);
|
||||
$background = array(
|
||||
'red' => $background >> 16 & 0xFF,
|
||||
'green' => $background >> 8 & 0xFF,
|
||||
'blue' => $background & 0xFF,
|
||||
'alpha' => 0,
|
||||
);
|
||||
}
|
||||
// Set the background color as transparent if $background is NULL.
|
||||
else {
|
||||
// Get the current transparent color.
|
||||
$background = imagecolortransparent($image->resource);
|
||||
|
||||
// If no transparent colors, use white.
|
||||
if ($background == 0) {
|
||||
$background = imagecolorallocatealpha($image->resource, 255, 255, 255, 0);
|
||||
}
|
||||
// Background color is not specified: use transparent white as background.
|
||||
$background = array(
|
||||
'red' => 255,
|
||||
'green' => 255,
|
||||
'blue' => 255,
|
||||
'alpha' => 127
|
||||
);
|
||||
}
|
||||
|
||||
// Store the color index for the background as that is what GD uses.
|
||||
$background_idx = imagecolorallocatealpha($image->resource, $background['red'], $background['green'], $background['blue'], $background['alpha']);
|
||||
|
||||
// Images are assigned a new color palette when rotating, removing any
|
||||
// transparency flags. For GIF images, keep a record of the transparent color.
|
||||
if ($image->info['extension'] == 'gif') {
|
||||
$transparent_index = imagecolortransparent($image->resource);
|
||||
if ($transparent_index != 0) {
|
||||
$transparent_gif_color = imagecolorsforindex($image->resource, $transparent_index);
|
||||
// GIF does not work with a transparency channel, but can define 1 color
|
||||
// in its palette to act as transparent.
|
||||
|
||||
// Get the current transparent color, if any.
|
||||
$gif_transparent_id = imagecolortransparent($image->resource);
|
||||
if ($gif_transparent_id !== -1) {
|
||||
// The gif already has a transparent color set: remember it to set it on
|
||||
// the rotated image as well.
|
||||
$transparent_gif_color = imagecolorsforindex($image->resource, $gif_transparent_id);
|
||||
|
||||
if ($background['alpha'] >= 127) {
|
||||
// We want a transparent background: use the color already set to act
|
||||
// as transparent, as background.
|
||||
$background_idx = $gif_transparent_id;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The gif does not currently have a transparent color set.
|
||||
if ($background['alpha'] >= 127) {
|
||||
// But as the background is transparent, it should get one.
|
||||
$transparent_gif_color = $background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$image->resource = imagerotate($image->resource, 360 - $degrees, $background);
|
||||
$image->resource = imagerotate($image->resource, 360 - $degrees, $background_idx);
|
||||
|
||||
// GIFs need to reassign the transparent color after performing the rotate.
|
||||
if (isset($transparent_gif_color)) {
|
||||
|
@@ -1856,7 +1856,7 @@ function system_image_toolkit_settings() {
|
||||
if (count($toolkits_available) == 0) {
|
||||
variable_del('image_toolkit');
|
||||
$form['image_toolkit_help'] = array(
|
||||
'#markup' => t("No image toolkits were detected. Drupal includes support for <a href='!gd-link'>PHP's built-in image processing functions</a> but they were not detected on this system. You should consult your system administrator to have them enabled, or try using a third party toolkit.", array('gd-link' => url('http://php.net/gd'))),
|
||||
'#markup' => t("No image toolkits were detected. Drupal includes support for <a href='!gd-link'>PHP's built-in image processing functions</a> but they were not detected on this system. You should consult your system administrator to have them enabled, or try using a third party toolkit.", array('!gd-link' => url('http://php.net/gd'))),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
@@ -2202,6 +2202,11 @@ function system_add_date_format_type_form_submit($form, &$form_state) {
|
||||
* Return the date for a given format string via Ajax.
|
||||
*/
|
||||
function system_date_time_lookup() {
|
||||
// This callback is protected with a CSRF token because user input from the
|
||||
// query string is reflected in the output.
|
||||
if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], 'admin/config/regional/date-time/formats/lookup')) {
|
||||
return MENU_ACCESS_DENIED;
|
||||
}
|
||||
$result = format_date(REQUEST_TIME, 'custom', $_GET['format']);
|
||||
drupal_json_output($result);
|
||||
}
|
||||
@@ -2592,6 +2597,8 @@ function theme_status_report($variables) {
|
||||
if (empty($requirement['#type'])) {
|
||||
$severity = $severities[isset($requirement['severity']) ? (int) $requirement['severity'] : REQUIREMENT_OK];
|
||||
$severity['icon'] = '<div title="' . $severity['title'] . '"><span class="element-invisible">' . $severity['title'] . '</span></div>';
|
||||
// The requirement's 'value' key is optional, provide a default value.
|
||||
$requirement['value'] = isset($requirement['value']) ? $requirement['value'] : '';
|
||||
|
||||
// Output table row(s)
|
||||
if (!empty($requirement['description'])) {
|
||||
@@ -2875,13 +2882,14 @@ function system_date_time_formats() {
|
||||
* Allow users to add additional date formats.
|
||||
*/
|
||||
function system_configure_date_formats_form($form, &$form_state, $dfid = 0) {
|
||||
$ajax_path = 'admin/config/regional/date-time/formats/lookup';
|
||||
$js_settings = array(
|
||||
'type' => 'setting',
|
||||
'data' => array(
|
||||
'dateTime' => array(
|
||||
'date-format' => array(
|
||||
'text' => t('Displayed as'),
|
||||
'lookup' => url('admin/config/regional/date-time/formats/lookup'),
|
||||
'lookup' => url($ajax_path, array('query' => array('token' => drupal_get_token($ajax_path)))),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@@ -113,21 +113,21 @@ function hook_hook_info_alter(&$hooks) {
|
||||
* translation handlers. Array keys are the module names, array values
|
||||
* can be any data structure the module uses to provide field translation.
|
||||
* Any empty value disallows the module to appear as a translation handler.
|
||||
* - entity keys: An array describing how the Field API can extract the
|
||||
* information it needs from the objects of the type. Elements:
|
||||
* - entity keys: (optional) An array describing how the Field API can extract
|
||||
* the information it needs from the objects of the type. Elements:
|
||||
* - id: The name of the property that contains the primary id of the
|
||||
* entity. Every entity object passed to the Field API must have this
|
||||
* property and its value must be numeric.
|
||||
* - revision: The name of the property that contains the revision id of
|
||||
* the entity. The Field API assumes that all revision ids are unique
|
||||
* across all entities of a type. This entry can be omitted if the
|
||||
* entities of this type are not versionable.
|
||||
* entities of this type are not versionable. Defaults to an empty string.
|
||||
* - bundle: The name of the property that contains the bundle name for the
|
||||
* entity. The bundle name defines which set of fields are attached to
|
||||
* the entity (e.g. what nodes call "content type"). This entry can be
|
||||
* omitted if this entity type exposes a single bundle (all entities have
|
||||
* the same collection of fields). The name of this single bundle will be
|
||||
* the same as the entity type.
|
||||
* the same as the entity type. Defaults to an empty string.
|
||||
* - label: The name of the property that contains the entity label. For
|
||||
* example, if the entity's label is located in $entity->subject, then
|
||||
* 'subject' should be specified here. If complex logic is required to
|
||||
@@ -606,7 +606,7 @@ function hook_cron() {
|
||||
* @return
|
||||
* An associative array where the key is the queue name and the value is
|
||||
* again an associative array. Possible keys are:
|
||||
* - 'worker callback': A PHP callable to call that is an implementation of
|
||||
* - 'worker callback': The name of an implementation of
|
||||
* callback_queue_worker().
|
||||
* - 'time': (optional) How much time Drupal should spend on calling this
|
||||
* worker in seconds. Defaults to 15.
|
||||
@@ -643,28 +643,6 @@ function hook_cron_queue_info_alter(&$queues) {
|
||||
$queues['aggregator_feeds']['time'] = 90;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work on a single queue item.
|
||||
*
|
||||
* Callback for hook_queue_info().
|
||||
*
|
||||
* @param $queue_item_data
|
||||
* The data that was passed to DrupalQueue::createItem() when the item was
|
||||
* queued.
|
||||
*
|
||||
* @throws \Exception
|
||||
* The worker callback may throw an exception to indicate there was a problem.
|
||||
* The cron process will log the exception, and leave the item in the queue to
|
||||
* be processed again later.
|
||||
*
|
||||
* @see drupal_cron_run()
|
||||
*/
|
||||
function callback_queue_worker($queue_item_data) {
|
||||
$node = node_load($queue_item_data);
|
||||
$node->title = 'Updated title';
|
||||
$node->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows modules to declare their own Form API element types and specify their
|
||||
* default values.
|
||||
@@ -1819,6 +1797,8 @@ function hook_form_BASE_FORM_ID_alter(&$form, &$form_state, $form_id) {
|
||||
* the $form_id input matched your module's format for dynamically-generated
|
||||
* form IDs, and if so, act appropriately.
|
||||
*
|
||||
* Third, forms defined in classes can be defined this way.
|
||||
*
|
||||
* @param $form_id
|
||||
* The unique string identifying the desired form.
|
||||
* @param $args
|
||||
@@ -1829,19 +1809,22 @@ function hook_form_BASE_FORM_ID_alter(&$form, &$form_state, $form_id) {
|
||||
* @return
|
||||
* An associative array whose keys define form_ids and whose values are an
|
||||
* associative array defining the following keys:
|
||||
* - callback: The name of the form builder function to invoke. This will be
|
||||
* used for the base form ID, for example, to target a base form using
|
||||
* hook_form_BASE_FORM_ID_alter().
|
||||
* - callback: The callable returning the form array. If it is the name of
|
||||
* the form builder function then this will be used for the base
|
||||
* form ID, for example, to target a base form using
|
||||
* hook_form_BASE_FORM_ID_alter(). Otherwise use the base_form_id key to
|
||||
* define the base form ID.
|
||||
* - callback arguments: (optional) Additional arguments to pass to the
|
||||
* function defined in 'callback', which are prepended to $args.
|
||||
* - wrapper_callback: (optional) The name of a form builder function to
|
||||
* invoke before the form builder defined in 'callback' is invoked. This
|
||||
* wrapper callback may prepopulate the $form array with form elements,
|
||||
* which will then be already contained in the $form that is passed on to
|
||||
* the form builder defined in 'callback'. For example, a wrapper callback
|
||||
* could setup wizard-alike form buttons that are the same for a variety of
|
||||
* forms that belong to the wizard, which all share the same wrapper
|
||||
* callback.
|
||||
* - base_form_id: The base form ID can be specified explicitly. This is
|
||||
* required when callback is not the name of a function.
|
||||
* - wrapper_callback: (optional) Any callable to invoke before the form
|
||||
* builder defined in 'callback' is invoked. This wrapper callback may
|
||||
* prepopulate the $form array with form elements, which will then be
|
||||
* already contained in the $form that is passed on to the form builder
|
||||
* defined in 'callback'. For example, a wrapper callback could setup
|
||||
* wizard-like form buttons that are the same for a variety of forms that
|
||||
* belong to the wizard, which all share the same wrapper callback.
|
||||
*/
|
||||
function hook_forms($form_id, $args) {
|
||||
// Simply reroute the (non-existing) $form_id 'mymodule_first_form' to
|
||||
@@ -1865,6 +1848,15 @@ function hook_forms($form_id, $args) {
|
||||
'wrapper_callback' => 'mymodule_main_form_wrapper',
|
||||
);
|
||||
|
||||
// Build a form with a static class callback.
|
||||
$forms['mymodule_class_generated_form'] = array(
|
||||
// This will call: MyClass::generateMainForm().
|
||||
'callback' => array('MyClass', 'generateMainForm'),
|
||||
// The base_form_id is required when the callback is a static function in
|
||||
// a class. This can also be used to keep newer code backwards compatible.
|
||||
'base_form_id' => 'mymodule_main_form',
|
||||
);
|
||||
|
||||
return $forms;
|
||||
}
|
||||
|
||||
@@ -2654,6 +2646,8 @@ function hook_flush_caches() {
|
||||
* module_enable() for a detailed description of the order in which install and
|
||||
* enable hooks are invoked.
|
||||
*
|
||||
* This hook should be implemented in a .module file, not in an .install file.
|
||||
*
|
||||
* @param $modules
|
||||
* An array of the modules that were installed.
|
||||
*
|
||||
@@ -3195,7 +3189,9 @@ function hook_requirements($phase) {
|
||||
* creation and alteration of the supported database engines.
|
||||
*
|
||||
* See the Schema API Handbook at http://drupal.org/node/146843 for details on
|
||||
* schema definition structures.
|
||||
* schema definition structures. Note that foreign key definitions are for
|
||||
* documentation purposes only; foreign keys are not created in the database,
|
||||
* nor are they enforced by Drupal.
|
||||
*
|
||||
* @return array
|
||||
* A schema definition structure array. For each element of the
|
||||
@@ -3247,6 +3243,8 @@ function hook_schema() {
|
||||
'nid_vid' => array('nid', 'vid'),
|
||||
'vid' => array('vid'),
|
||||
),
|
||||
// For documentation purposes only; foreign keys are not created in the
|
||||
// database.
|
||||
'foreign keys' => array(
|
||||
'node_revision' => array(
|
||||
'table' => 'node_revision',
|
||||
@@ -3715,8 +3713,9 @@ function hook_registry_files_alter(&$files, $modules) {
|
||||
*
|
||||
* Any tasks you define here will be run, in order, after the installer has
|
||||
* finished the site configuration step but before it has moved on to the
|
||||
* final import of languages and the end of the installation. You can have any
|
||||
* number of custom tasks to perform during this phase.
|
||||
* final import of languages and the end of the installation. This is invoked
|
||||
* by install_tasks(). You can have any number of custom tasks to perform
|
||||
* during this phase.
|
||||
*
|
||||
* Each task you define here corresponds to a callback function which you must
|
||||
* separately define and which is called when your task is run. This function
|
||||
@@ -3809,6 +3808,8 @@ function hook_registry_files_alter(&$files, $modules) {
|
||||
*
|
||||
* @see install_state_defaults()
|
||||
* @see batch_set()
|
||||
* @see hook_install_tasks_alter()
|
||||
* @see install_tasks()
|
||||
*/
|
||||
function hook_install_tasks(&$install_state) {
|
||||
// Here, we define a variable to allow tasks to indicate that a particular,
|
||||
@@ -3911,6 +3912,8 @@ function hook_html_head_alter(&$head_elements) {
|
||||
/**
|
||||
* Alter the full list of installation tasks.
|
||||
*
|
||||
* This hook is invoked on the install profile in install_tasks().
|
||||
*
|
||||
* @param $tasks
|
||||
* An array of all available installation tasks, including those provided by
|
||||
* Drupal core. You can modify this array to change or replace any part of
|
||||
@@ -3918,6 +3921,9 @@ function hook_html_head_alter(&$head_elements) {
|
||||
* is selected.
|
||||
* @param $install_state
|
||||
* An array of information about the current installation state.
|
||||
*
|
||||
* @see hook_install_tasks()
|
||||
* @see install_tasks()
|
||||
*/
|
||||
function hook_install_tasks_alter(&$tasks, $install_state) {
|
||||
// Replace the "Choose language" installation task provided by Drupal core
|
||||
@@ -4804,6 +4810,28 @@ function hook_filetransfer_info_alter(&$filetransfer_info) {
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Work on a single queue item.
|
||||
*
|
||||
* Callback for hook_cron_queue_info().
|
||||
*
|
||||
* @param $queue_item_data
|
||||
* The data that was passed to DrupalQueueInterface::createItem() when the
|
||||
* item was queued.
|
||||
*
|
||||
* @throws Exception
|
||||
* The worker callback may throw an exception to indicate there was a problem.
|
||||
* The cron process will log the exception, and leave the item in the queue to
|
||||
* be processed again later.
|
||||
*
|
||||
* @see drupal_cron_run()
|
||||
*/
|
||||
function callback_queue_worker($queue_item_data) {
|
||||
$node = node_load($queue_item_data);
|
||||
$node->title = 'Updated title';
|
||||
node_save($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URI for an entity.
|
||||
*
|
||||
|
@@ -12,8 +12,8 @@ files[] = system.test
|
||||
required = TRUE
|
||||
configure = admin/config/system
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -196,6 +196,12 @@ function system_requirements($phase) {
|
||||
);
|
||||
}
|
||||
|
||||
// Test database-specific multi-byte UTF-8 related requirements.
|
||||
$charset_requirements = _system_check_db_utf8mb4_requirements($phase);
|
||||
if (!empty($charset_requirements)) {
|
||||
$requirements['database_charset'] = $charset_requirements;
|
||||
}
|
||||
|
||||
// Test PHP memory_limit
|
||||
$memory_limit = ini_get('memory_limit');
|
||||
$requirements['php_memory_limit'] = array(
|
||||
@@ -517,6 +523,75 @@ function system_requirements($phase) {
|
||||
return $requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the requirements for multi-byte UTF-8 support are met.
|
||||
*
|
||||
* @param string $phase
|
||||
* The hook_requirements() stage.
|
||||
*
|
||||
* @return array
|
||||
* A requirements array with the result of the charset check.
|
||||
*/
|
||||
function _system_check_db_utf8mb4_requirements($phase) {
|
||||
global $install_state;
|
||||
// In the requirements check of the installer, skip the utf8mb4 check unless
|
||||
// the database connection info has been preconfigured by hand with valid
|
||||
// information before running the installer, as otherwise we cannot get a
|
||||
// valid database connection object.
|
||||
if (isset($install_state['settings_verified']) && !$install_state['settings_verified']) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$connection = Database::getConnection();
|
||||
$t = get_t();
|
||||
$requirements['title'] = $t('Database 4 byte UTF-8 support');
|
||||
|
||||
$utf8mb4_configurable = $connection->utf8mb4IsConfigurable();
|
||||
$utf8mb4_active = $connection->utf8mb4IsActive();
|
||||
$utf8mb4_supported = $connection->utf8mb4IsSupported();
|
||||
$driver = $connection->driver();
|
||||
$documentation_url = 'https://www.drupal.org/node/2754539';
|
||||
|
||||
if ($utf8mb4_active) {
|
||||
if ($utf8mb4_supported) {
|
||||
if ($phase != 'install' && $utf8mb4_configurable && !variable_get('drupal_all_databases_are_utf8mb4', FALSE)) {
|
||||
// Supported, active, and configurable, but not all database tables
|
||||
// have been converted yet.
|
||||
$requirements['value'] = $t('Enabled, but database tables need conversion');
|
||||
$requirements['description'] = $t('Please convert all database tables to utf8mb4 prior to enabling it in settings.php. See the <a href="@url">documentation on adding 4 byte UTF-8 support</a> for more information.', array('@url' => $documentation_url));
|
||||
$requirements['severity'] = REQUIREMENT_ERROR;
|
||||
}
|
||||
else {
|
||||
// Supported, active.
|
||||
$requirements['value'] = $t('Enabled');
|
||||
$requirements['description'] = $t('4 byte UTF-8 for @driver is enabled.', array('@driver' => $driver));
|
||||
$requirements['severity'] = REQUIREMENT_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Not supported, active.
|
||||
$requirements['value'] = $t('Not supported');
|
||||
$requirements['description'] = $t('4 byte UTF-8 for @driver is activated, but not supported on your system. Please turn this off in settings.php, or ensure that all database-related requirements are met. See the <a href="@url">documentation on adding 4 byte UTF-8 support</a> for more information.', array('@driver' => $driver, '@url' => $documentation_url));
|
||||
$requirements['severity'] = REQUIREMENT_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($utf8mb4_supported) {
|
||||
// Supported, not active.
|
||||
$requirements['value'] = $t('Not enabled');
|
||||
$requirements['description'] = $t('4 byte UTF-8 for @driver is not activated, but it is supported on your system. It is recommended that you enable this to allow 4-byte UTF-8 input such as emojis, Asian symbols and mathematical symbols to be stored correctly. See the <a href="@url">documentation on adding 4 byte UTF-8 support</a> for more information.', array('@driver' => $driver, '@url' => $documentation_url));
|
||||
$requirements['severity'] = REQUIREMENT_INFO;
|
||||
}
|
||||
else {
|
||||
// Not supported, not active.
|
||||
$requirements['value'] = $t('Disabled');
|
||||
$requirements['description'] = $t('4 byte UTF-8 for @driver is disabled. See the <a href="@url">documentation on adding 4 byte UTF-8 support</a> for more information.', array('@driver' => $driver, '@url' => $documentation_url));
|
||||
$requirements['severity'] = REQUIREMENT_INFO;
|
||||
}
|
||||
}
|
||||
return $requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
@@ -532,6 +607,9 @@ function system_install() {
|
||||
module_list(TRUE);
|
||||
module_implements('', FALSE, TRUE);
|
||||
|
||||
// Ensure the schema versions are not based on a previous module list.
|
||||
drupal_static_reset('drupal_get_schema_versions');
|
||||
|
||||
// Load system theme data appropriately.
|
||||
system_rebuild_theme_data();
|
||||
|
||||
@@ -800,6 +878,7 @@ function system_schema() {
|
||||
'type' => 'varchar',
|
||||
'length' => 100,
|
||||
'not null' => TRUE,
|
||||
'binary' => TRUE,
|
||||
),
|
||||
'type' => array(
|
||||
'description' => 'The date format type, e.g. medium.',
|
||||
@@ -2803,6 +2882,16 @@ function system_update_7061(&$sandbox) {
|
||||
->from($query)
|
||||
->execute();
|
||||
|
||||
// Retrieve a list of duplicate files with the same filepath. Only the
|
||||
// most-recently uploaded of these will be moved to the new {file_managed}
|
||||
// table (and all references will be updated to point to it), since
|
||||
// duplicate file URIs are not allowed in Drupal 7.
|
||||
// Since the Drupal 6 to 7 upgrade path leaves the {files} table behind
|
||||
// after it's done, custom or contributed modules which need to migrate
|
||||
// file references of their own can use a similar query to determine the
|
||||
// file IDs that duplicate filepaths were mapped to.
|
||||
$sandbox['duplicate_filepath_fids_to_use'] = db_query("SELECT filepath, MAX(fid) FROM {files} GROUP BY filepath HAVING COUNT(*) > 1")->fetchAllKeyed();
|
||||
|
||||
// Initialize batch update information.
|
||||
$sandbox['progress'] = 0;
|
||||
$sandbox['last_vid_processed'] = -1;
|
||||
@@ -2832,6 +2921,16 @@ function system_update_7061(&$sandbox) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this file has a duplicate filepath, replace it with the
|
||||
// most-recently uploaded file that has the same filepath.
|
||||
if (isset($sandbox['duplicate_filepath_fids_to_use'][$file['filepath']]) && $record->fid != $sandbox['duplicate_filepath_fids_to_use'][$file['filepath']]) {
|
||||
$file = db_select('files', 'f')
|
||||
->fields('f', array('fid', 'uid', 'filename', 'filepath', 'filemime', 'filesize', 'status', 'timestamp'))
|
||||
->condition('f.fid', $sandbox['duplicate_filepath_fids_to_use'][$file['filepath']])
|
||||
->execute()
|
||||
->fetchAssoc();
|
||||
}
|
||||
|
||||
// Add in the file information from the upload table.
|
||||
$file['description'] = $record->description;
|
||||
$file['display'] = $record->list;
|
||||
@@ -3157,6 +3256,35 @@ function system_update_7079() {
|
||||
db_change_field('file_managed', 'filesize', 'filesize', $spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the 'format' column in {date_format_locale} to case sensitive varchar.
|
||||
*/
|
||||
function system_update_7080() {
|
||||
$spec = array(
|
||||
'description' => 'The date format string.',
|
||||
'type' => 'varchar',
|
||||
'length' => 100,
|
||||
'not null' => TRUE,
|
||||
'binary' => TRUE,
|
||||
);
|
||||
db_change_field('date_format_locale', 'format', 'format', $spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the Drupal 6 default install profile if it is still in the database.
|
||||
*/
|
||||
function system_update_7081() {
|
||||
// Sites which used the default install profile in Drupal 6 and then updated
|
||||
// to Drupal 7.44 or earlier will still have a record of this install profile
|
||||
// in the database that needs to be deleted.
|
||||
db_delete('system')
|
||||
->condition('filename', 'profiles/default/default.profile')
|
||||
->condition('type', 'module')
|
||||
->condition('status', 0)
|
||||
->condition('schema_version', 0)
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "defgroup updates-7.x-extra".
|
||||
* The next series of updates should start at 8000.
|
||||
|
@@ -105,7 +105,7 @@ Drupal.behaviors.dateTime = {
|
||||
// Attach keyup handler to custom format inputs.
|
||||
$('input' + source, context).once('date-time').keyup(function () {
|
||||
var input = $(this);
|
||||
var url = fieldSettings.lookup + (/\?q=/.test(fieldSettings.lookup) ? '&format=' : '?format=') + encodeURIComponent(input.val());
|
||||
var url = fieldSettings.lookup + (/\?/.test(fieldSettings.lookup) ? '&format=' : '?format=') + encodeURIComponent(input.val());
|
||||
$.getJSON(url, function (data) {
|
||||
$(suffix).empty().append(' ' + fieldSettings.text + ': <em>' + data + '</em>');
|
||||
});
|
||||
|
@@ -359,7 +359,7 @@ function system_element_info() {
|
||||
'#size' => 60,
|
||||
'#maxlength' => 128,
|
||||
'#autocomplete_path' => FALSE,
|
||||
'#process' => array('ajax_process_form'),
|
||||
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
|
||||
'#theme' => 'textfield',
|
||||
'#theme_wrappers' => array('form_element'),
|
||||
);
|
||||
@@ -2030,7 +2030,6 @@ function system_user_timezone(&$form, &$form_state) {
|
||||
'#description' => t('Select the desired local time and time zone. Dates and times throughout this site will be displayed using this time zone.'),
|
||||
);
|
||||
if (!isset($account->timezone) && $account->uid == $user->uid && empty($form_state['input']['timezone'])) {
|
||||
$form['timezone']['#description'] = t('Your time zone setting will be automatically detected if possible. Confirm the selection and click save.');
|
||||
$form['timezone']['timezone']['#attributes'] = array('class' => array('timezone-detect'));
|
||||
drupal_add_js('misc/timezone.js');
|
||||
}
|
||||
@@ -2412,6 +2411,10 @@ function _system_rebuild_module_data() {
|
||||
// Merge in defaults and save.
|
||||
$modules[$key]->info = $module->info + $defaults;
|
||||
|
||||
// The "name" key is required, but to avoid a fatal error in the menu system
|
||||
// we set a reasonable default if it is not provided.
|
||||
$modules[$key]->info += array('name' => $key);
|
||||
|
||||
// Prefix stylesheets and scripts with module path.
|
||||
$path = dirname($module->uri);
|
||||
if (isset($module->info['stylesheets'])) {
|
||||
@@ -2547,6 +2550,10 @@ function _system_rebuild_theme_data() {
|
||||
$themes[$key]->filename = $theme->uri;
|
||||
$themes[$key]->info = drupal_parse_info_file($theme->uri) + $defaults;
|
||||
|
||||
// The "name" key is required, but to avoid a fatal error in the menu system
|
||||
// we set a reasonable default if it is not provided.
|
||||
$themes[$key]->info += array('name' => $key);
|
||||
|
||||
// Add the info file modification time, so it becomes available for
|
||||
// contributed modules to use for ordering theme lists.
|
||||
$themes[$key]->info['mtime'] = filemtime($theme->uri);
|
||||
@@ -2698,10 +2705,17 @@ function system_find_base_themes($themes, $key, $used_keys = array()) {
|
||||
* @param $show
|
||||
* Possible values: REGIONS_ALL or REGIONS_VISIBLE. Visible excludes hidden
|
||||
* regions.
|
||||
* @return
|
||||
* An array of regions in the form $region['name'] = 'description'.
|
||||
* @param bool $labels
|
||||
* (optional) Boolean to specify whether the human readable machine names
|
||||
* should be returned or not. Defaults to TRUE, but calling code can set
|
||||
* this to FALSE for better performance, if it only needs machine names.
|
||||
*
|
||||
* @return array
|
||||
* An associative array of regions in the form $region['name'] = 'description'
|
||||
* if $labels is set to TRUE, or $region['name'] = 'name', if $labels is set
|
||||
* to FALSE.
|
||||
*/
|
||||
function system_region_list($theme_key, $show = REGIONS_ALL) {
|
||||
function system_region_list($theme_key, $show = REGIONS_ALL, $labels = TRUE) {
|
||||
$themes = list_themes();
|
||||
if (!isset($themes[$theme_key])) {
|
||||
return array();
|
||||
@@ -2712,10 +2726,14 @@ function system_region_list($theme_key, $show = REGIONS_ALL) {
|
||||
// If requested, suppress hidden regions. See block_admin_display_form().
|
||||
foreach ($info['regions'] as $name => $label) {
|
||||
if ($show == REGIONS_ALL || !isset($info['regions_hidden']) || !in_array($name, $info['regions_hidden'])) {
|
||||
$list[$name] = t($label);
|
||||
if ($labels) {
|
||||
$list[$name] = t($label);
|
||||
}
|
||||
else {
|
||||
$list[$name] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
@@ -2736,12 +2754,13 @@ function system_system_info_alter(&$info, $file, $type) {
|
||||
*
|
||||
* @param $theme
|
||||
* The name of a theme.
|
||||
*
|
||||
* @return
|
||||
* A string that is the region name.
|
||||
*/
|
||||
function system_default_region($theme) {
|
||||
$regions = array_keys(system_region_list($theme, REGIONS_VISIBLE));
|
||||
return isset($regions[0]) ? $regions[0] : '';
|
||||
$regions = system_region_list($theme, REGIONS_VISIBLE, FALSE);
|
||||
return $regions ? reset($regions) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2808,7 +2827,7 @@ function system_settings_form_submit($form, &$form_state) {
|
||||
function _system_sort_requirements($a, $b) {
|
||||
if (!isset($a['weight'])) {
|
||||
if (!isset($b['weight'])) {
|
||||
return strcmp($a['title'], $b['title']);
|
||||
return strcasecmp($a['title'], $b['title']);
|
||||
}
|
||||
return -$b['weight'];
|
||||
}
|
||||
@@ -3049,8 +3068,20 @@ function system_cron() {
|
||||
}
|
||||
}
|
||||
|
||||
$core = array('cache', 'cache_path', 'cache_filter', 'cache_page', 'cache_form', 'cache_menu');
|
||||
$cache_tables = array_merge(module_invoke_all('flush_caches'), $core);
|
||||
// Delete expired cache entries.
|
||||
// Avoid invoking hook_flush_cashes() on every cron run because some modules
|
||||
// use this hook to perform expensive rebuilding operations (which are only
|
||||
// designed to happen on full cache clears), rather than just returning a
|
||||
// list of cache tables to be cleared.
|
||||
$cache_object = cache_get('system_cache_tables');
|
||||
if (empty($cache_object)) {
|
||||
$core = array('cache', 'cache_path', 'cache_filter', 'cache_page', 'cache_form', 'cache_menu');
|
||||
$cache_tables = array_merge(module_invoke_all('flush_caches'), $core);
|
||||
cache_set('system_cache_tables', $cache_tables);
|
||||
}
|
||||
else {
|
||||
$cache_tables = $cache_object->data;
|
||||
}
|
||||
foreach ($cache_tables as $table) {
|
||||
cache_clear_all(NULL, $table);
|
||||
}
|
||||
@@ -3298,7 +3329,7 @@ function system_goto_action_form($context) {
|
||||
$form['url'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('URL'),
|
||||
'#description' => t('The URL to which the user should be redirected. This can be an internal URL like node/1234 or an external URL like http://drupal.org.'),
|
||||
'#description' => t('The URL to which the user should be redirected. This can be an internal path like node/1234 or an external URL like http://example.com.'),
|
||||
'#default_value' => isset($context['url']) ? $context['url'] : '',
|
||||
'#required' => TRUE,
|
||||
);
|
||||
@@ -3335,7 +3366,8 @@ function system_goto_action($entity, $context) {
|
||||
*/
|
||||
function system_block_ip_action() {
|
||||
$ip = ip_address();
|
||||
db_insert('blocked_ips')
|
||||
db_merge('blocked_ips')
|
||||
->key(array('ip' => $ip))
|
||||
->fields(array('ip' => $ip))
|
||||
->execute();
|
||||
watchdog('action', 'Banned IP address %ip', array('%ip' => $ip));
|
||||
@@ -3497,8 +3529,7 @@ function system_retrieve_file($url, $destination = NULL, $managed = FALSE, $repl
|
||||
function system_page_alter(&$page) {
|
||||
// Find all non-empty page regions, and add a theme wrapper function that
|
||||
// allows them to be consistently themed.
|
||||
$regions = system_region_list($GLOBALS['theme']);
|
||||
foreach (array_keys($regions) as $region) {
|
||||
foreach (system_region_list($GLOBALS['theme'], REGIONS_ALL, FALSE) as $region) {
|
||||
if (!empty($page[$region])) {
|
||||
$page[$region]['#theme_wrappers'][] = 'region';
|
||||
$page[$region]['#region'] = $region;
|
||||
|
@@ -231,7 +231,7 @@ class SystemQueue implements DrupalReliableQueueInterface {
|
||||
// until an item is successfully claimed or we are reasonably sure there
|
||||
// are no unclaimed items left.
|
||||
while (TRUE) {
|
||||
$item = db_query_range('SELECT data, item_id FROM {queue} q WHERE expire = 0 AND name = :name ORDER BY created ASC', 0, 1, array(':name' => $this->name))->fetchObject();
|
||||
$item = db_query_range('SELECT data, item_id FROM {queue} q WHERE expire = 0 AND name = :name ORDER BY created, item_id ASC', 0, 1, array(':name' => $this->name))->fetchObject();
|
||||
if ($item) {
|
||||
// Try to update the item. Only one thread can succeed in UPDATEing the
|
||||
// same row. We cannot rely on REQUEST_TIME because items might be
|
||||
@@ -326,6 +326,7 @@ class MemoryQueue implements DrupalQueueInterface {
|
||||
$item->created = time();
|
||||
$item->expire = 0;
|
||||
$this->queue[$item->item_id] = $item;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function numberOfItems() {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -389,6 +389,18 @@ class ModuleDependencyTestCase extends ModuleTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks functionality of project namespaces for dependencies.
|
||||
*/
|
||||
function testProjectNamespaceForDependencies() {
|
||||
// Enable module with project namespace to ensure nothing breaks.
|
||||
$edit = array(
|
||||
'modules[Testing][system_project_namespace_test][enable]' => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/modules', $edit, t('Save configuration'));
|
||||
$this->assertModules(array('system_project_namespace_test'), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to enable translation module without locale enabled.
|
||||
*/
|
||||
@@ -714,7 +726,7 @@ class IPAddressBlockingTestCase extends DrupalWebTestCase {
|
||||
|
||||
// Block a valid IP address.
|
||||
$edit = array();
|
||||
$edit['ip'] = '192.168.1.1';
|
||||
$edit['ip'] = '1.2.3.3';
|
||||
$this->drupalPost('admin/config/people/ip-blocking', $edit, t('Add'));
|
||||
$ip = db_query("SELECT iid from {blocked_ips} WHERE ip = :ip", array(':ip' => $edit['ip']))->fetchField();
|
||||
$this->assertTrue($ip, t('IP address found in database.'));
|
||||
@@ -722,7 +734,7 @@ class IPAddressBlockingTestCase extends DrupalWebTestCase {
|
||||
|
||||
// Try to block an IP address that's already blocked.
|
||||
$edit = array();
|
||||
$edit['ip'] = '192.168.1.1';
|
||||
$edit['ip'] = '1.2.3.3';
|
||||
$this->drupalPost('admin/config/people/ip-blocking', $edit, t('Add'));
|
||||
$this->assertText(t('This IP address is already blocked.'));
|
||||
|
||||
@@ -758,6 +770,25 @@ class IPAddressBlockingTestCase extends DrupalWebTestCase {
|
||||
// $this->drupalPost('admin/config/people/ip-blocking', $edit, t('Save'));
|
||||
// $this->assertText(t('You may not block your own IP address.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test duplicate IP addresses are not present in the 'blocked_ips' table.
|
||||
*/
|
||||
function testDuplicateIpAddress() {
|
||||
drupal_static_reset('ip_address');
|
||||
$submit_ip = $_SERVER['REMOTE_ADDR'] = '192.168.1.1';
|
||||
system_block_ip_action();
|
||||
system_block_ip_action();
|
||||
$ip_count = db_query("SELECT iid from {blocked_ips} WHERE ip = :ip", array(':ip' => $submit_ip))->rowCount();
|
||||
$this->assertEqual('1', $ip_count);
|
||||
drupal_static_reset('ip_address');
|
||||
$submit_ip = $_SERVER['REMOTE_ADDR'] = ' ';
|
||||
system_block_ip_action();
|
||||
system_block_ip_action();
|
||||
system_block_ip_action();
|
||||
$ip_count = db_query("SELECT iid from {blocked_ips} WHERE ip = :ip", array(':ip' => $submit_ip))->rowCount();
|
||||
$this->assertEqual('1', $ip_count);
|
||||
}
|
||||
}
|
||||
|
||||
class CronRunTestCase extends DrupalWebTestCase {
|
||||
@@ -893,6 +924,29 @@ class CronRunTestCase extends DrupalWebTestCase {
|
||||
$result = variable_get('common_test_cron');
|
||||
$this->assertEqual($result, 'success', 'Cron correctly handles exceptions thrown during hook_cron() invocations.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that hook_flush_caches() is not invoked on every single cron run.
|
||||
*
|
||||
* @see system_cron()
|
||||
*/
|
||||
public function testCronCacheExpiration() {
|
||||
module_enable(array('system_cron_test'));
|
||||
variable_del('system_cron_test_flush_caches');
|
||||
|
||||
// Invoke cron the first time: hook_flush_caches() should be called and then
|
||||
// get cached.
|
||||
drupal_cron_run();
|
||||
$this->assertEqual(variable_get('system_cron_test_flush_caches'), 1, 'hook_flush_caches() was invoked the first time.');
|
||||
$cache = cache_get('system_cache_tables');
|
||||
$this->assertEqual(empty($cache), FALSE, 'Cache is filled with cache table data.');
|
||||
|
||||
// Run cron again and ensure that hook_flush_caches() is not called.
|
||||
variable_del('system_cron_test_flush_caches');
|
||||
drupal_cron_run();
|
||||
$this->assertNull(variable_get('system_cron_test_flush_caches'), 'hook_flush_caches() was not invoked the second time.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -911,7 +965,7 @@ class CronQueueTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('common_test', 'common_test_cron_helper'));
|
||||
parent::setUp(array('common_test', 'common_test_cron_helper', 'cron_queue_test'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -931,6 +985,23 @@ class CronQueueTestCase extends DrupalWebTestCase {
|
||||
$this->assertEqual($queue->numberOfItems(), 1, 'Failing item still in the queue after throwing an exception.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests worker defined as a class method callable.
|
||||
*/
|
||||
function testCallable() {
|
||||
$queue = DrupalQueue::get('cron_queue_test_callback');
|
||||
|
||||
// Enqueue an item for processing.
|
||||
$queue->createItem(array($this->randomName() => $this->randomName()));
|
||||
|
||||
// Run cron; the worker should perform the task and delete the item from the
|
||||
// queue.
|
||||
$this->cronRun();
|
||||
|
||||
// The queue should be empty.
|
||||
$this->assertEqual($queue->numberOfItems(), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AdminMetaTagTestCase extends DrupalWebTestCase {
|
||||
@@ -1068,6 +1139,11 @@ class PageNotFoundTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
$node = $this->drupalCreateNode($edit);
|
||||
|
||||
// As node IDs must be integers, make sure requests for non-integer IDs
|
||||
// return a page not found error.
|
||||
$this->drupalGet('node/invalid');
|
||||
$this->assertResponse(404);
|
||||
|
||||
// Use a custom 404 page.
|
||||
$this->drupalPost('admin/config/system/site-information', array('site_404' => 'node/' . $node->nid), t('Save configuration'));
|
||||
|
||||
@@ -1293,7 +1369,23 @@ class DateTimeFunctionalTest extends DrupalWebTestCase {
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), 'Correct page redirection.');
|
||||
$this->assertText(t('Custom date format updated.'), 'Custom date format successfully updated.');
|
||||
|
||||
// Check that ajax callback is protected by CSRF token.
|
||||
$this->drupalGet('admin/config/regional/date-time/formats/lookup', array('query' => array('format' => 'Y m d')));
|
||||
$this->assertResponse(403, 'Access denied with no token');
|
||||
$this->drupalGet('admin/config/regional/date-time/formats/lookup', array('query' => array('token' => 'invalid', 'format' => 'Y m d')));
|
||||
$this->assertResponse(403, 'Access denied with invalid token');
|
||||
$this->drupalGet('admin/config/regional/date-time/formats');
|
||||
$this->clickLink(t('edit'));
|
||||
$settings = $this->drupalGetSettings();
|
||||
$lookup_url = $settings['dateTime']['date-format']['lookup'];
|
||||
preg_match('/token=([^&]+)/', $lookup_url, $matches);
|
||||
$this->assertFalse(empty($matches[1]), 'Found token value');
|
||||
$this->drupalGet('admin/config/regional/date-time/formats/lookup', array('query' => array('token' => $matches[1], 'format' => 'Y m d')));
|
||||
$this->assertResponse(200, 'Access allowed with valid token');
|
||||
$this->assertText(format_date(time(), 'custom', 'Y m d'));
|
||||
|
||||
// Delete custom date format.
|
||||
$this->drupalGet('admin/config/regional/date-time/formats');
|
||||
$this->clickLink(t('delete'));
|
||||
$this->drupalPost($this->getUrl(), array(), t('Remove'));
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/regional/date-time/formats', array('absolute' => TRUE)), 'Correct page redirection.');
|
||||
@@ -2281,6 +2373,20 @@ class UpdateScriptFunctionalTest extends DrupalWebTestCase {
|
||||
$this->update_user = $this->drupalCreateUser(array('administer software updates'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that there are no pending updates for the first test method.
|
||||
*/
|
||||
function testNoPendingUpdates() {
|
||||
// Ensure that for the first test method in a class, there are no pending
|
||||
// updates. This tests a drupal_get_schema_versions() bug that previously
|
||||
// led to the wrong schema version being recorded for the initial install
|
||||
// of a child site during automated testing.
|
||||
$this->drupalLogin($this->update_user);
|
||||
$this->drupalGet($this->update_url, array('external' => TRUE));
|
||||
$this->drupalPost(NULL, array(), t('Continue'));
|
||||
$this->assertText(t('No pending updates.'), 'End of update process was reached.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests access to the update script.
|
||||
*/
|
||||
@@ -2362,6 +2468,12 @@ class UpdateScriptFunctionalTest extends DrupalWebTestCase {
|
||||
$this->assertText('This is a requirements error provided by the update_script_test module.');
|
||||
$this->clickLink('try again');
|
||||
$this->assertText('This is a requirements error provided by the update_script_test module.');
|
||||
|
||||
// Check if the optional 'value' key displays without a notice.
|
||||
variable_set('update_script_test_requirement_type', REQUIREMENT_INFO);
|
||||
$this->drupalGet($this->update_url, array('external' => TRUE));
|
||||
$this->assertText('This is a requirements info provided by the update_script_test module.');
|
||||
$this->assertNoText('Notice: Undefined index: value in theme_status_report()');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -24,7 +24,7 @@ class ModuleUpdater extends Updater implements DrupalUpdaterInterface {
|
||||
* found on your system, and if there was a copy in sites/all, we'd see it.
|
||||
*/
|
||||
public function getInstallDirectory() {
|
||||
if ($relative_path = drupal_get_path('module', $this->name)) {
|
||||
if ($this->isInstalled() && ($relative_path = drupal_get_path('module', $this->name))) {
|
||||
$relative_path = dirname($relative_path);
|
||||
}
|
||||
else {
|
||||
@@ -34,7 +34,7 @@ class ModuleUpdater extends Updater implements DrupalUpdaterInterface {
|
||||
}
|
||||
|
||||
public function isInstalled() {
|
||||
return (bool) drupal_get_path('module', $this->name);
|
||||
return (bool) drupal_get_filename('module', $this->name, NULL, FALSE);
|
||||
}
|
||||
|
||||
public static function canUpdateDirectory($directory) {
|
||||
@@ -109,7 +109,7 @@ class ThemeUpdater extends Updater implements DrupalUpdaterInterface {
|
||||
* found on your system, and if there was a copy in sites/all, we'd see it.
|
||||
*/
|
||||
public function getInstallDirectory() {
|
||||
if ($relative_path = drupal_get_path('theme', $this->name)) {
|
||||
if ($this->isInstalled() && ($relative_path = drupal_get_path('theme', $this->name))) {
|
||||
$relative_path = dirname($relative_path);
|
||||
}
|
||||
else {
|
||||
@@ -119,7 +119,7 @@ class ThemeUpdater extends Updater implements DrupalUpdaterInterface {
|
||||
}
|
||||
|
||||
public function isInstalled() {
|
||||
return (bool) drupal_get_path('theme', $this->name);
|
||||
return (bool) drupal_get_filename('theme', $this->name, NULL, FALSE);
|
||||
}
|
||||
|
||||
static function canUpdateDirectory($directory) {
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1475694174"
|
||||
|
||||
|
@@ -7,9 +7,21 @@ function cron_queue_test_cron_queue_info() {
|
||||
$queues['cron_queue_test_exception'] = array(
|
||||
'worker callback' => 'cron_queue_test_exception',
|
||||
);
|
||||
$queues['cron_queue_test_callback'] = array(
|
||||
'worker callback' => array('CronQueueTestCallbackClass', 'foo'),
|
||||
);
|
||||
|
||||
return $queues;
|
||||
}
|
||||
|
||||
function cron_queue_test_exception($item) {
|
||||
throw new Exception('That is not supposed to happen.');
|
||||
}
|
||||
|
||||
class CronQueueTestCallbackClass {
|
||||
|
||||
static public function foo() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
}
|
||||
|
12
modules/system/tests/system_cron_test.info
Normal file
12
modules/system/tests/system_cron_test.info
Normal file
@@ -0,0 +1,12 @@
|
||||
name = System Cron Test
|
||||
description = 'Support module for testing the system_cron().'
|
||||
package = Testing
|
||||
version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2016-10-05
|
||||
version = "7.51"
|
||||
project = "drupal"
|
||||
datestamp = "1475694174"
|
||||
|
15
modules/system/tests/system_cron_test.module
Normal file
15
modules/system/tests/system_cron_test.module
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Helper module for CronRunTestCase::testCronCacheExpiration().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_flush_caches().
|
||||
*/
|
||||
function system_cron_test_flush_caches() {
|
||||
// Set a variable to indicate that this hook was invoked.
|
||||
variable_set('system_cron_test_flush_caches', 1);
|
||||
return array();
|
||||
}
|
Reference in New Issue
Block a user