update core to 7.36

This commit is contained in:
Bachir Soussi Chiadmi
2015-04-19 19:33:23 +02:00
parent 6de56c702c
commit 802ec0c6f3
271 changed files with 4111 additions and 1227 deletions

View File

@@ -27,7 +27,7 @@ function aggregator_aggregator_fetch($feed) {
$headers['If-None-Match'] = $feed->etag;
}
if ($feed->modified) {
$headers['If-Modified-Since'] = gmdate(DATE_RFC1123, $feed->modified);
$headers['If-Modified-Since'] = gmdate(DATE_RFC7231, $feed->modified);
}
// Request feed.

View File

@@ -7,8 +7,8 @@ files[] = aggregator.test
configure = admin/config/services/aggregator/settings
stylesheets[all][] = aggregator.css
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -32,7 +32,7 @@ function aggregator_test_feed($use_last_modified = FALSE, $use_etag = FALSE) {
// Send appropriate response. We respond with a 304 not modified on either
// etag or on last modified.
if ($use_last_modified) {
drupal_add_http_header('Last-Modified', gmdate(DATE_RFC1123, $last_modified));
drupal_add_http_header('Last-Modified', gmdate(DATE_RFC7231, $last_modified));
}
if ($use_etag) {
drupal_add_http_header('ETag', $etag);

View File

@@ -272,7 +272,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
$form['settings']['title'] = array(
'#type' => 'textfield',
'#title' => t('Block title'),
'#maxlength' => 64,
'#maxlength' => 255,
'#description' => $block->module == 'block' ? t('The title of the block as shown to the user.') : t('Override the default title for the block. Use <em>!placeholder</em> to display no title, or leave blank to use the default block title.', array('!placeholder' => '&lt;none&gt;')),
'#default_value' => isset($block->title) ? $block->title : '',
'#weight' => -19,

View File

@@ -6,8 +6,8 @@ core = 7.x
files[] = block.test
configure = admin/structure/block
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -79,7 +79,7 @@ function block_schema() {
),
'title' => array(
'type' => 'varchar',
'length' => 64,
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'Custom title for the block. (Empty string will use block default title, <none> will remove the title, text will cause block to use specified title.)',
@@ -472,6 +472,22 @@ function block_update_7008() {
db_drop_field('block', 'throttle');
}
/**
* Increase {block}.title length to 255 characters.
*/
function block_update_7009() {
db_change_field('block', 'title', 'title',
array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'Custom title for the block. (Empty string will use block default title, <none> will remove the title, text will cause block to use specified title.)',
'translatable' => TRUE,
)
);
}
/**
* @} End of "addtogroup updates-7.x-extra".
*/

View File

@@ -66,7 +66,7 @@ function block_help($path, $arg) {
$demo_theme = !empty($arg[4]) ? $arg[4] : variable_get('theme_default', 'bartik');
$themes = list_themes();
$output = '<p>' . t('This page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions. Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the <em>Save blocks</em> button at the bottom of the page. Click the <em>configure</em> link next to each block to configure its specific title and visibility settings.') . '</p>';
$output .= '<p>' . l(t('Demonstrate block regions (@theme)', array('@theme' => $themes[$demo_theme]->info['name'])), 'admin/structure/block/demo/' . $demo_theme) . '</p>';
$output .= '<p>' . l(t('Demonstrate block regions (!theme)', array('!theme' => $themes[$demo_theme]->info['name'])), 'admin/structure/block/demo/' . $demo_theme) . '</p>';
return $output;
}
}
@@ -143,7 +143,7 @@ function block_menu() {
);
foreach (list_themes() as $key => $theme) {
$items['admin/structure/block/list/' . $key] = array(
'title' => check_plain($theme->info['name']),
'title' => $theme->info['name'],
'page arguments' => array($key),
'type' => $key == $default_theme ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
'weight' => $key == $default_theme ? -10 : 0,
@@ -162,7 +162,7 @@ function block_menu() {
);
}
$items['admin/structure/block/demo/' . $key] = array(
'title' => check_plain($theme->info['name']),
'title' => $theme->info['name'],
'page callback' => 'block_admin_demo',
'page arguments' => array($key),
'type' => MENU_CALLBACK,
@@ -692,6 +692,9 @@ function block_list($region) {
/**
* Loads a block object from the database.
*
* This function returns the first block matching the module and delta
* parameters, so it should not be used for theme-specific functionality.
*
* @param $module
* Name of the module that implements the block to load.
* @param $delta
@@ -848,10 +851,19 @@ function block_block_list_alter(&$blocks) {
* An array of visible blocks as expected by drupal_render().
*/
function _block_render_blocks($region_blocks) {
// Block caching is not compatible with node access modules. We also
// preserve the submission of forms in blocks, by fetching from cache only
$cacheable = TRUE;
// We preserve the submission of forms in blocks, by fetching from cache only
// if the request method is 'GET' (or 'HEAD').
$cacheable = !count(module_implements('node_grants')) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD');
if ($_SERVER['REQUEST_METHOD'] != 'GET' && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
$cacheable = FALSE;
}
// Block caching is not usually compatible with node access modules, so by
// default it is disabled when node access modules exist. However, it can be
// allowed by using the variable 'block_cache_bypass_node_grants'.
elseif (!variable_get('block_cache_bypass_node_grants', FALSE) && count(module_implements('node_grants'))) {
$cacheable = FALSE;
}
// Proceed to loop over all blocks in order to compute their respective cache
// identifiers; this allows us to do one single cache_get_multiple() call
@@ -1054,7 +1066,7 @@ function block_menu_delete($menu) {
* Implements hook_form_FORM_ID_alter().
*/
function block_form_system_performance_settings_alter(&$form, &$form_state) {
$disabled = count(module_implements('node_grants'));
$disabled = (!variable_get('block_cache_bypass_node_grants', FALSE) && count(module_implements('node_grants')));
$form['caching']['block_cache'] = array(
'#type' => 'checkbox',
'#title' => t('Cache blocks'),

View File

@@ -75,7 +75,7 @@ class BlockTestCase extends DrupalWebTestCase {
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
// Check to see if the custom block was created by checking that it's in the database.
$this->assertNotNull($bid, 'Custom block found in database');
$this->assertTrue($bid, 'Custom block found in database');
// Check that block_block_view() returns the correct title and content.
$data = block_block_view($bid);
@@ -305,7 +305,7 @@ class BlockTestCase extends DrupalWebTestCase {
))->fetchField();
// Check to see if the block was created by checking that it's in the database.
$this->assertNotNull($bid, 'Block found in database');
$this->assertTrue($bid, 'Block found in database');
// Check whether the block can be moved to all available regions.
foreach ($this->regions as $region) {

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -13,8 +13,8 @@ regions[footer] = Footer
regions[highlighted] = Highlighted
regions[help] = Help
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = blog.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -7,8 +7,8 @@ files[] = book.test
configure = admin/content/book/settings
stylesheets[all][] = book.css
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = color.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -9,8 +9,8 @@ files[] = comment.test
configure = admin/content/comment
stylesheets[all][] = comment.css
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -993,12 +993,7 @@ function comment_build_content($comment, $node, $view_mode = 'full', $langcode =
$comment->content = array();
// Allow modules to change the view mode.
$context = array(
'entity_type' => 'comment',
'entity' => $comment,
'langcode' => $langcode,
);
drupal_alter('entity_view_mode', $view_mode, $context);
$view_mode = key(entity_view_mode_prepare('comment', array($comment->cid => $comment), $view_mode, $langcode));
// Build fields content.
field_attach_prepare_view('comment', array($comment->cid => $comment), $view_mode, $langcode);
@@ -1108,17 +1103,26 @@ function comment_links($comment, $node) {
* An array in the format expected by drupal_render().
*/
function comment_view_multiple($comments, $node, $view_mode = 'full', $weight = 0, $langcode = NULL) {
field_attach_prepare_view('comment', $comments, $view_mode, $langcode);
entity_prepare_view('comment', $comments, $langcode);
$build = array();
$entities_by_view_mode = entity_view_mode_prepare('comment', $comments, $view_mode, $langcode);
foreach ($entities_by_view_mode as $entity_view_mode => $entities) {
field_attach_prepare_view('comment', $entities, $entity_view_mode, $langcode);
entity_prepare_view('comment', $entities, $langcode);
foreach ($entities as $entity) {
$build[$entity->cid] = comment_view($entity, $node, $entity_view_mode, $langcode);
}
}
$build = array(
'#sorted' => TRUE,
);
foreach ($comments as $comment) {
$build[$comment->cid] = comment_view($comment, $node, $view_mode, $langcode);
$build[$comment->cid]['#weight'] = $weight;
$weight++;
}
// Sort here, to preserve the input order of the entities that were passed to
// this function.
uasort($build, 'element_sort');
$build['#sorted'] = TRUE;
return $build;
}
@@ -2603,7 +2607,7 @@ function comment_unpublish_action($comment, $context = array()) {
/**
* Unpublishes a comment if it contains certain keywords.
*
* @param $comment
* @param object $comment
* Comment object to modify.
* @param array $context
* Array with components:
@@ -2615,10 +2619,13 @@ function comment_unpublish_action($comment, $context = array()) {
* @see comment_unpublish_by_keyword_action_submit()
*/
function comment_unpublish_by_keyword_action($comment, $context) {
$node = node_load($comment->nid);
$build = comment_view($comment, $node);
$text = drupal_render($build);
foreach ($context['keywords'] as $keyword) {
$text = drupal_render($comment);
if (strpos($text, $keyword) !== FALSE) {
$comment->status = COMMENT_NOT_PUBLISHED;
comment_save($comment);
watchdog('action', 'Unpublished comment %subject.', array('%subject' => $comment->subject));
break;
}

View File

@@ -13,7 +13,7 @@ class CommentHelperCase extends DrupalWebTestCase {
function setUp() {
parent::setUp('comment', 'search');
// Create users and test node.
$this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks'));
$this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks', 'administer actions'));
$this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'create article content', 'edit own comments'));
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->uid));
}
@@ -1973,6 +1973,41 @@ class CommentActionsTestCase extends CommentHelperCase {
$this->clearWatchdog();
}
/**
* Tests the unpublish comment by keyword action.
*/
public function testCommentUnpublishByKeyword() {
$this->drupalLogin($this->admin_user);
$callback = 'comment_unpublish_by_keyword_action';
$hash = drupal_hash_base64($callback);
$comment_text = $keywords = $this->randomName();
$edit = array(
'actions_label' => $callback,
'keywords' => $keywords,
);
$this->drupalPost("admin/config/system/actions/configure/$hash", $edit, t('Save'));
$action = db_query("SELECT aid, type, callback, parameters, label FROM {actions} WHERE callback = :callback", array(':callback' => $callback))->fetchObject();
$this->assertTrue($action, 'The action could be loaded.');
$comment = $this->postComment($this->node, $comment_text, $this->randomName());
// Load the full comment so that status is available.
$comment = comment_load($comment->id);
$this->assertTrue($comment->status == COMMENT_PUBLISHED, 'The comment status was set to published.');
comment_unpublish_by_keyword_action($comment, array('keywords' => array($keywords)));
// We need to make sure that the comment has been saved with status
// unpublished.
$this->assertEqual(comment_load($comment->cid)->status, COMMENT_NOT_PUBLISHED, 'Comment was unpublished.');
$this->assertWatchdogMessage('Unpublished comment %subject.', array('%subject' => $comment->subject), 'Found watchdog message.');
$this->clearWatchdog();
}
/**
* Verify that a watchdog message has been entered.
*

View File

@@ -6,8 +6,8 @@ core = 7.x
files[] = contact.test
configure = admin/structure/contact
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -134,7 +134,7 @@ function contact_site_form_submit($form, &$form_state) {
global $user, $language;
$values = $form_state['values'];
$values['sender'] = $user;
$values['sender'] = clone $user;
$values['sender']->name = $values['name'];
$values['sender']->mail = $values['mail'];
$values['category'] = contact_load($values['cid']);
@@ -270,7 +270,7 @@ function contact_personal_form_submit($form, &$form_state) {
global $user, $language;
$values = $form_state['values'];
$values['sender'] = $user;
$values['sender'] = clone $user;
$values['sender']->name = $values['name'];
$values['sender']->mail = $values['mail'];

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = contextual.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -7,8 +7,8 @@ files[] = dashboard.test
dependencies[] = block
configure = admin/dashboard/customize
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -32,13 +32,13 @@ Drupal.behaviors.dashboard = {
empty_text = Drupal.settings.dashboard.emptyRegionTextInactive;
}
// We need a placeholder.
if ($('.placeholder', this).length == 0) {
$(this).append('<div class="placeholder"></div>');
if ($('.dashboard-placeholder', this).length == 0) {
$(this).append('<div class="dashboard-placeholder"></div>');
}
$('.placeholder', this).html(empty_text);
$('.dashboard-placeholder', this).html(empty_text);
}
else {
$('.placeholder', this).remove();
$('.dashboard-placeholder', this).remove();
}
});
},

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = dblog.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -1328,10 +1328,27 @@ function hook_field_attach_load($entity_type, $entities, $age, $options) {
* @param $entity
* The entity with fields to validate.
* @param array $errors
* An associative array of errors keyed by field_name, language, delta.
* The array of errors (keyed by field name, language code, and delta) that
* have already been reported for the entity. The function should add its
* errors to this array. Each error is an associative array with the following
* keys and values:
* - error: An error code (should be a string prefixed with the module name).
* - message: The human readable message to be displayed.
*/
function hook_field_attach_validate($entity_type, $entity, &$errors) {
// @todo Needs function body.
// Make sure any images in article nodes have an alt text.
if ($entity_type == 'node' && $entity->type == 'article' && !empty($entity->field_image)) {
foreach ($entity->field_image as $langcode => $items) {
foreach ($items as $delta => $item) {
if (!empty($item['fid']) && empty($item['alt'])) {
$errors['field_image'][$langcode][$delta][] = array(
'error' => 'field_example_invalid',
'message' => t('All images in articles need to have an alternative text set.'),
);
}
}
}
}
}
/**
@@ -1880,7 +1897,7 @@ function hook_field_storage_write($entity_type, $entity, $op, $fields) {
$items = (array) $entity->{$field_name}[$langcode];
$delta_count = 0;
foreach ($items as $delta => $item) {
// We now know we have someting to insert.
// We now know we have something to insert.
$do_insert = TRUE;
$record = array(
'entity_type' => $entity_type,

View File

@@ -318,7 +318,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
// Unless a language suggestion is provided we iterate on all the
// available languages.
$available_languages = field_available_languages($entity_type, $field);
$language = !empty($options['language'][$id]) ? $options['language'][$id] : $options['language'];
$language = is_array($options['language']) && !empty($options['language'][$id]) ? $options['language'][$id] : $options['language'];
$languages = _field_language_suggestion($available_languages, $language, $field_name);
foreach ($languages as $langcode) {
$grouped_items[$field_id][$langcode][$id] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();

View File

@@ -60,11 +60,11 @@ function field_create_field($field) {
}
// Field type is required.
if (empty($field['type'])) {
throw new FieldException('Attempt to create a field with no type.');
throw new FieldException(format_string('Attempt to create field @field_name with no type.', array('@field_name' => $field['field_name'])));
}
// Field name cannot contain invalid characters.
if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $field['field_name'])) {
throw new FieldException('Attempt to create a field with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character');
throw new FieldException(format_string('Attempt to create a field @field_name with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character', array('@field_name' => $field['field_name'])));
}
// Field name cannot be longer than 32 characters. We use drupal_strlen()
@@ -540,9 +540,9 @@ function field_create_instance($instance) {
* // Fetch an instance info array.
* $instance_info = field_info_instance($entity_type, $field_name, $bundle_name);
* // Change a single property in the instance definition.
* $instance_info['definition']['required'] = TRUE;
* $instance_info['required'] = TRUE;
* // Write the changed definition back.
* field_update_instance($instance_info['definition']);
* field_update_instance($instance_info);
* @endcode
*
* @throws FieldException

View File

@@ -11,8 +11,8 @@ dependencies[] = field_sql_storage
required = TRUE
stylesheets[all][] = theme/field.css
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -146,7 +146,10 @@ class FieldInfo {
// Save in "static" and persistent caches.
$this->fieldMap = $map;
cache_set('field_info:field_map', $map, 'cache_field');
if (lock_acquire('field_info:field_map')) {
cache_set('field_info:field_map', $map, 'cache_field');
lock_release('field_info:field_map');
}
return $map;
}
@@ -174,7 +177,10 @@ class FieldInfo {
}
// Store in persistent cache.
cache_set('field_info:fields', $this->fieldsById, 'cache_field');
if (lock_acquire('field_info:fields')) {
cache_set('field_info:fields', $this->fieldsById, 'cache_field');
lock_release('field_info:fields');
}
}
// Fill the name/ID map.
@@ -231,7 +237,10 @@ class FieldInfo {
}
// Store in persistent cache.
cache_set('field_info:instances', $this->bundleInstances, 'cache_field');
if (lock_acquire('field_info:instances')) {
cache_set('field_info:instances', $this->bundleInstances, 'cache_field');
lock_release('field_info:instances');
}
}
$this->loadedAllInstances = TRUE;
@@ -419,7 +428,11 @@ class FieldInfo {
foreach ($instances as $instance) {
$cache['fields'][] = $this->fieldsById[$instance['field_id']];
}
cache_set("field_info:bundle:$entity_type:$bundle", $cache, 'cache_field');
if (lock_acquire("field_info:bundle:$entity_type:$bundle")) {
cache_set("field_info:bundle:$entity_type:$bundle", $cache, 'cache_field');
lock_release("field_info:bundle:$entity_type:$bundle");
}
return $instances;
}
@@ -460,7 +473,10 @@ class FieldInfo {
// Store in the 'static' and persistent caches.
$this->bundleExtraFields[$entity_type][$bundle] = $info;
cache_set("field_info:bundle_extra:$entity_type:$bundle", $info, 'cache_field');
if (lock_acquire("field_info:bundle_extra:$entity_type:$bundle")) {
cache_set("field_info:bundle_extra:$entity_type:$bundle", $info, 'cache_field');
lock_release("field_info:bundle_extra:$entity_type:$bundle");
}
return $this->bundleExtraFields[$entity_type][$bundle];
}

View File

@@ -223,7 +223,11 @@ function _field_info_collate_types($reset = FALSE) {
}
drupal_alter('field_storage_info', $info['storage types']);
cache_set("field_info_types:$langcode", $info, 'cache_field');
// Set the cache if we can acquire a lock.
if (lock_acquire("field_info_types:$langcode")) {
cache_set("field_info_types:$langcode", $info, 'cache_field');
lock_release("field_info_types:$langcode");
}
}
}

View File

@@ -162,6 +162,7 @@ function field_schema() {
),
);
$schema['cache_field'] = drupal_get_schema_unprocessed('system', 'cache');
$schema['cache_field']['description'] = 'Cache table for the Field module to store already built field information.';
return $schema;
}

View File

@@ -342,17 +342,6 @@ function field_cron() {
field_purge_batch($limit);
}
/**
* Implements hook_modules_uninstalled().
*/
function field_modules_uninstalled($modules) {
module_load_include('inc', 'field', 'field.crud');
foreach ($modules as $module) {
// TODO D7: field_module_delete is not yet implemented
// field_module_delete($module);
}
}
/**
* Implements hook_system_info_alter().
*
@@ -905,6 +894,7 @@ function field_view_field($entity_type, $entity, $field_name, $display = array()
'entity' => $entity,
'view_mode' => '_custom',
'display' => $display,
'language' => $langcode,
);
drupal_alter('field_attach_view', $result, $context);
@@ -947,20 +937,30 @@ function field_get_items($entity_type, $entity, $field_name, $langcode = NULL) {
*/
function field_has_data($field) {
$query = new EntityFieldQuery();
return (bool) $query
->fieldCondition($field)
$query = $query->fieldCondition($field)
->range(0, 1)
->count()
// Neutralize the 'entity_field_access' query tag added by
// field_sql_storage_field_storage_query(). The result cannot depend on the
// access grants of the current user.
->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');
return (bool) $query
->execute() || (bool) $query
->age(FIELD_LOAD_REVISION)
->execute();
}
/**
* Determine whether the user has access to a given field.
*
* This function does not determine whether access is granted to the entity
* itself, only the specific field. Callers are responsible for ensuring that
* entity access is also respected. For example, when checking field access for
* nodes, check node_access() before checking field_access(), and when checking
* field access for entities using the Entity API contributed module,
* check entity_access() before checking field_access().
*
* @param $op
* The operation to be performed. Possible values:
* - 'edit'

View File

@@ -7,8 +7,8 @@ dependencies[] = field
files[] = field_sql_storage.test
required = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -64,6 +64,49 @@ function _field_sql_storage_revision_tablename($field) {
}
}
/**
* Generates a table alias for a field data table.
*
* The table alias is unique for each unique combination of field name
* (represented by $tablename), delta_group and language_group.
*
* @param $tablename
* The name of the data table for this field.
* @param $field_key
* The numeric key of this field in this query.
* @param $query
* The EntityFieldQuery that is executed.
*
* @return
* A string containing the generated table alias.
*/
function _field_sql_storage_tablealias($tablename, $field_key, EntityFieldQuery $query) {
// No conditions present: use a unique alias.
if (empty($query->fieldConditions[$field_key])) {
return $tablename . $field_key;
}
// Find the delta and language condition values and append them to the alias.
$condition = $query->fieldConditions[$field_key];
$alias = $tablename;
$has_group_conditions = FALSE;
foreach (array('delta', 'language') as $column) {
if (isset($condition[$column . '_group'])) {
$alias .= '_' . $column . '_' . $condition[$column . '_group'];
$has_group_conditions = TRUE;
}
}
// Return the alias when it has delta/language group conditions.
if ($has_group_conditions) {
return $alias;
}
// Return a unique alias in other cases.
return $tablename . $field_key;
}
/**
* Generate a column name for a field data table.
*
@@ -422,7 +465,7 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel
$items = (array) $entity->{$field_name}[$langcode];
$delta_count = 0;
foreach ($items as $delta => $item) {
// We now know we have someting to insert.
// We now know we have something to insert.
$do_insert = TRUE;
$record = array(
'entity_type' => $entity_type,
@@ -504,17 +547,21 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) {
$id_key = 'revision_id';
}
$table_aliases = array();
$query_tables = NULL;
// Add tables for the fields used.
foreach ($query->fields as $key => $field) {
$tablename = $tablename_function($field);
// Every field needs a new table.
$table_alias = $tablename . $key;
$table_alias = _field_sql_storage_tablealias($tablename, $key, $query);
$table_aliases[$key] = $table_alias;
if ($key) {
$select_query->join($tablename, $table_alias, "$table_alias.entity_type = $field_base_table.entity_type AND $table_alias.$id_key = $field_base_table.$id_key");
if (!isset($query_tables[$table_alias])) {
$select_query->join($tablename, $table_alias, "$table_alias.entity_type = $field_base_table.entity_type AND $table_alias.$id_key = $field_base_table.$id_key");
}
}
else {
$select_query = db_select($tablename, $table_alias);
// Store a reference to the list of joined tables.
$query_tables =& $select_query->getTables();
// Allow queries internal to the Field API to opt out of the access
// check, for situations where the query's results should not depend on
// the access grants for the current user.

View File

@@ -438,4 +438,149 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
$this->assertEqual($foreign_key['table'], $foreign_key_name, 'Foreign key table name preserved in the schema');
$this->assertEqual($foreign_key['columns'][$foreign_key_column], 'id', 'Foreign key column name preserved in the schema');
}
/**
* Test handling multiple conditions on one column of a field.
*
* Tests both the result and the complexity of the query.
*/
function testFieldSqlStorageMultipleConditionsSameColumn() {
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$this->field_name}[LANGUAGE_NONE][0] = array('value' => 1);
field_test_entity_save($entity);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$this->field_name}[LANGUAGE_NONE][0] = array('value' => 2);
field_test_entity_save($entity);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$this->field_name}[LANGUAGE_NONE][0] = array('value' => 3);
field_test_entity_save($entity);
$query = new EntityFieldQuery();
// This tag causes field_test_query_store_global_test_query_alter() to be
// invoked so that the query can be tested.
$query->addTag('store_global_test_query');
$query->entityCondition('entity_type', 'test_entity');
$query->entityCondition('bundle', 'test_bundle');
$query->fieldCondition($this->field_name, 'value', 1, '<>', 0, LANGUAGE_NONE);
$query->fieldCondition($this->field_name, 'value', 2, '<>', 0, LANGUAGE_NONE);
$result = field_sql_storage_field_storage_query($query);
// Test the results.
$this->assertEqual(1, count($result), format_string('One result should be returned, got @count', array('@count' => count($result))));
// Test the complexity of the query.
$query = $GLOBALS['test_query'];
$this->assertNotNull($query, 'Precondition: the query should be available');
$tables = $query->getTables();
$this->assertEqual(1, count($tables), 'The query contains just one table.');
// Clean up.
unset($GLOBALS['test_query']);
}
/**
* Test handling multiple conditions on multiple columns of one field.
*
* Tests both the result and the complexity of the query.
*/
function testFieldSqlStorageMultipleConditionsDifferentColumns() {
// Create the multi-column shape field
$field_name = strtolower($this->randomName());
$field = array('field_name' => $field_name, 'type' => 'shape', 'cardinality' => 4);
$field = field_create_field($field);
$instance = array(
'field_name' => $field_name,
'entity_type' => 'test_entity',
'bundle' => 'test_bundle'
);
$instance = field_create_instance($instance);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$field_name}[LANGUAGE_NONE][0] = array('shape' => 'A', 'color' => 'X');
field_test_entity_save($entity);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$field_name}[LANGUAGE_NONE][0] = array('shape' => 'B', 'color' => 'X');
field_test_entity_save($entity);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$field_name}[LANGUAGE_NONE][0] = array('shape' => 'A', 'color' => 'Y');
field_test_entity_save($entity);
$query = new EntityFieldQuery();
// This tag causes field_test_query_store_global_test_query_alter() to be
// invoked so that the query can be tested.
$query->addTag('store_global_test_query');
$query->entityCondition('entity_type', 'test_entity');
$query->entityCondition('bundle', 'test_bundle');
$query->fieldCondition($field_name, 'shape', 'B', '=', 'something', LANGUAGE_NONE);
$query->fieldCondition($field_name, 'color', 'X', '=', 'something', LANGUAGE_NONE);
$result = field_sql_storage_field_storage_query($query);
// Test the results.
$this->assertEqual(1, count($result), format_string('One result should be returned, got @count', array('@count' => count($result))));
// Test the complexity of the query.
$query = $GLOBALS['test_query'];
$this->assertNotNull($query, 'Precondition: the query should be available');
$tables = $query->getTables();
$this->assertEqual(1, count($tables), 'The query contains just one table.');
// Clean up.
unset($GLOBALS['test_query']);
}
/**
* Test handling multiple conditions on multiple columns of one field for multiple languages.
*
* Tests both the result and the complexity of the query.
*/
function testFieldSqlStorageMultipleConditionsDifferentColumnsMultipleLanguages() {
field_test_entity_info_translatable('test_entity', TRUE);
// Create the multi-column shape field
$field_name = strtolower($this->randomName());
$field = array('field_name' => $field_name, 'type' => 'shape', 'cardinality' => 4, 'translatable' => TRUE);
$field = field_create_field($field);
$instance = array(
'field_name' => $field_name,
'entity_type' => 'test_entity',
'bundle' => 'test_bundle',
'settings' => array(
// Prevent warning from field_test_field_load().
'test_hook_field_load' => FALSE,
),
);
$instance = field_create_instance($instance);
$entity = field_test_create_stub_entity(NULL, NULL);
$entity->{$field_name}[LANGUAGE_NONE][0] = array('shape' => 'A', 'color' => 'X');
$entity->{$field_name}['en'][0] = array('shape' => 'B', 'color' => 'Y');
field_test_entity_save($entity);
$entity = field_test_entity_test_load($entity->ftid);
$query = new EntityFieldQuery();
// This tag causes field_test_query_store_global_test_query_alter() to be
// invoked so that the query can be tested.
$query->addTag('store_global_test_query');
$query->entityCondition('entity_type', 'test_entity');
$query->entityCondition('bundle', 'test_bundle');
$query->fieldCondition($field_name, 'color', 'X', '=', NULL, LANGUAGE_NONE);
$query->fieldCondition($field_name, 'shape', 'B', '=', NULL, 'en');
$result = field_sql_storage_field_storage_query($query);
// Test the results.
$this->assertEqual(1, count($result), format_string('One result should be returned, got @count', array('@count' => count($result))));
// Test the complexity of the query.
$query = $GLOBALS['test_query'];
$this->assertNotNull($query, 'Precondition: the query should be available');
$tables = $query->getTables();
$this->assertEqual(2, count($tables), 'The query contains two tables.');
// Clean up.
unset($GLOBALS['test_query']);
}
}

View File

@@ -7,8 +7,8 @@ dependencies[] = field
dependencies[] = options
files[] = tests/list.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -5,8 +5,8 @@ package = Testing
version = VERSION
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -6,8 +6,8 @@ core = 7.x
dependencies[] = field
files[] = number.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -6,8 +6,8 @@ core = 7.x
dependencies[] = field
files[] = options.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -7,8 +7,8 @@ dependencies[] = field
files[] = text.test
required = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -12,9 +12,9 @@ Drupal.behaviors.textSummary = {
$summaries.once('text-summary-wrapper').each(function(index) {
var $summary = $(this);
var $summaryLabel = $summary.find('label');
var $summaryLabel = $summary.find('label').first();
var $full = $widget.find('.text-full').eq(index).closest('.form-item');
var $fullLabel = $full.find('label');
var $fullLabel = $full.find('label').first();
// Create a placeholder label when the field cardinality is
// unlimited or greater than 1.
@@ -23,24 +23,28 @@ Drupal.behaviors.textSummary = {
}
// Setup the edit/hide summary link.
var $link = $('<span class="field-edit-link">(<a class="link-edit-summary" href="#">' + Drupal.t('Hide summary') + '</a>)</span>').toggle(
function () {
var $link = $('<span class="field-edit-link">(<a class="link-edit-summary" href="#">' + Drupal.t('Hide summary') + '</a>)</span>');
var $a = $link.find('a');
var toggleClick = true;
$link.bind('click', function (e) {
if (toggleClick) {
$summary.hide();
$(this).find('a').html(Drupal.t('Edit summary')).end().appendTo($fullLabel);
return false;
},
function () {
$summary.show();
$(this).find('a').html(Drupal.t('Hide summary')).end().appendTo($summaryLabel);
return false;
$a.html(Drupal.t('Edit summary'));
$link.appendTo($fullLabel);
}
).appendTo($summaryLabel);
else {
$summary.show();
$a.html(Drupal.t('Hide summary'));
$link.appendTo($summaryLabel);
}
toggleClick = !toggleClick;
return false;
}).appendTo($summaryLabel);
// If no summary is set, hide the summary field.
if ($(this).find('.text-summary').val() == '') {
$link.click();
}
return;
});
});
}

View File

@@ -245,7 +245,7 @@ function text_field_formatter_settings_summary($field, $instance, $view_mode) {
$summary = '';
if (strpos($display['type'], '_trimmed') !== FALSE) {
$summary = t('Trim length') . ': ' . $settings['trim_length'];
$summary = t('Trim length') . ': ' . check_plain($settings['trim_length']);
}
return $summary;

View File

@@ -484,6 +484,66 @@ class FieldAttachStorageTestCase extends FieldAttachTestCase {
$this->assertEqual($entity->{$this->field_name}[$langcode], $values, 'Insert: missing field results in default value saved');
}
/**
* Test field_has_data().
*/
function testFieldHasData() {
$entity_type = 'test_entity';
$langcode = LANGUAGE_NONE;
$field_name = 'field_1';
$field = array('field_name' => $field_name, 'type' => 'test_field');
$field = field_create_field($field);
$this->assertFalse(field_has_data($field), "No data should be detected.");
$instance = array(
'field_name' => $field_name,
'entity_type' => 'test_entity',
'bundle' => 'test_bundle'
);
$instance = field_create_instance($instance);
$table = _field_sql_storage_tablename($field);
$revision_table = _field_sql_storage_revision_tablename($field);
$columns = array('entity_type', 'entity_id', 'revision_id', 'delta', 'language', $field_name . '_value');
$eid = 0;
// Insert values into the field revision table.
$query = db_insert($revision_table)->fields($columns);
$query->values(array($entity_type, $eid, 0, 0, $langcode, 1));
$query->execute();
$this->assertTrue(field_has_data($field), "Revision data only should be detected.");
$field_name = 'field_2';
$field = array('field_name' => $field_name, 'type' => 'test_field');
$field = field_create_field($field);
$this->assertFalse(field_has_data($field), "No data should be detected.");
$instance = array(
'field_name' => $field_name,
'entity_type' => 'test_entity',
'bundle' => 'test_bundle'
);
$instance = field_create_instance($instance);
$table = _field_sql_storage_tablename($field);
$revision_table = _field_sql_storage_revision_tablename($field);
$columns = array('entity_type', 'entity_id', 'revision_id', 'delta', 'language', $field_name . '_value');
$eid = 1;
// Insert values into the field table.
$query = db_insert($table)->fields($columns);
$query->values(array($entity_type, $eid, 0, 0, $langcode, 1));
$query->execute();
$this->assertTrue(field_has_data($field), "Values only in field table should be detected.");
}
/**
* Test field_attach_delete().
*/
@@ -2146,11 +2206,12 @@ class FieldDisplayAPITestCase extends FieldTestCase {
'alter' => TRUE,
),
);
$output = field_view_field('test_entity', $this->entity, $this->field_name, $display);
$output = field_view_field('test_entity', $this->entity, $this->field_name, $display, LANGUAGE_NONE);
$this->drupalSetContent(drupal_render($output));
$setting = $display['settings']['test_formatter_setting_multiple'];
$this->assertNoText($this->label, 'Label was not displayed.');
$this->assertText('field_test_field_attach_view_alter', 'Alter fired, display passed.');
$this->assertText('field language is ' . LANGUAGE_NONE, 'Language is placed onto the context.');
$array = array();
foreach ($this->values as $delta => $value) {
$array[] = $delta . ':' . $value['value'];

View File

@@ -6,8 +6,8 @@ files[] = field_test.entity.inc
version = VERSION
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -220,6 +220,10 @@ function field_test_field_attach_view_alter(&$output, $context) {
if (!empty($context['display']['settings']['alter'])) {
$output['test_field'][] = array('#markup' => 'field_test_field_attach_view_alter');
}
if (isset($output['test_field'])) {
$output['test_field'][] = array('#markup' => 'field language is ' . $context['language']);
}
}
/**
@@ -267,3 +271,14 @@ function field_test_query_efq_table_prefixing_test_alter(&$query) {
// exception if the EFQ does not properly prefix the base table.
$query->join('test_entity','te2','%alias.ftid = test_entity.ftid');
}
/**
* Implements hook_query_TAG_alter() for tag 'store_global_test_query'.
*/
function field_test_query_store_global_test_query_alter($query) {
// Save the query in a global variable so that it can be examined by tests.
// This can be used by any test which needs to check a query, but see
// FieldSqlStorageTestCase::testFieldSqlStorageMultipleConditionsSameColumn()
// for an example.
$GLOBALS['test_query'] = $query;
}

View File

@@ -134,6 +134,9 @@ function hook_field_widget_settings_form($field, $instance) {
/**
* Specify the form elements for a formatter's settings.
*
* This hook is only invoked if hook_field_formatter_settings_summary()
* returns a non-empty value.
*
* @param $field
* The field structure being configured.
* @param $instance

View File

@@ -6,8 +6,8 @@ core = 7.x
dependencies[] = field
files[] = field_ui.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -168,7 +168,7 @@ Drupal.fieldUIOverview = {
var dragObject = this;
var row = dragObject.rowObject.element;
var rowHandler = $(row).data('fieldUIRowHandler');
if (rowHandler !== undefined) {
if (typeof rowHandler !== 'undefined') {
var regionRow = $(row).prevAll('tr.region-message').get(0);
var region = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
@@ -319,7 +319,7 @@ Drupal.fieldUIDisplayOverview.field.prototype = {
if (currentValue == 'hidden') {
// Restore the formatter back to the default formatter. Pseudo-fields do
// not have default formatters, we just return to 'visible' for those.
var value = (this.defaultFormatter != undefined) ? this.defaultFormatter : 'visible';
var value = (typeof this.defaultFormatter !== 'undefined') ? this.defaultFormatter : this.$formatSelect.find('option').val();
}
break;

View File

@@ -92,6 +92,7 @@ function file_field_instance_settings_form($field, $instance) {
'#description' => t('Separate extensions with a space or comma and do not include the leading dot.'),
'#element_validate' => array('_file_generic_settings_extensions'),
'#weight' => 1,
'#maxlength' => 256,
// By making this field required, we prevent a potential security issue
// that would allow files of any type to be uploaded.
'#required' => TRUE,
@@ -251,6 +252,12 @@ function file_field_insert($entity_type, $entity, $field, $instance, $langcode,
* Checks for files that have been removed from the object.
*/
function file_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
// Check whether the field is defined on the object.
if (!isset($entity->{$field['field_name']})) {
// We cannot check for removed files if the field is not defined.
return;
}
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
// On new revisions, all files are considered to be a new usage and no

View File

@@ -6,8 +6,8 @@ core = 7.x
dependencies[] = field
files[] = tests/file.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -357,6 +357,10 @@ function file_file_delete($file) {
* support for a default value.
*/
function file_managed_file_process($element, &$form_state, $form) {
// Append the '-upload' to the #id so the field label's 'for' attribute
// corresponds with the file element.
$original_id = $element['#id'];
$element['#id'] .= '-upload';
$fid = isset($element['#value']['fid']) ? $element['#value']['fid'] : 0;
// Set some default element properties.
@@ -366,7 +370,7 @@ function file_managed_file_process($element, &$form_state, $form) {
$ajax_settings = array(
'path' => 'file/ajax/' . implode('/', $element['#array_parents']) . '/' . $form['form_build_id']['#value'],
'wrapper' => $element['#id'] . '-ajax-wrapper',
'wrapper' => $original_id . '-ajax-wrapper',
'effect' => 'fade',
'progress' => array(
'type' => $element['#progress_indicator'],
@@ -461,13 +465,13 @@ function file_managed_file_process($element, &$form_state, $form) {
$element['upload']['#attached']['js'] = array(
array(
'type' => 'setting',
'data' => array('file' => array('elements' => array('#' . $element['#id'] . '-upload' => $extension_list)))
'data' => array('file' => array('elements' => array('#' . $element['#id'] => $extension_list)))
)
);
}
// Prefix and suffix used for Ajax replacement.
$element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
$element['#prefix'] = '<div id="' . $original_id . '-ajax-wrapper">';
$element['#suffix'] = '</div>';
return $element;
@@ -478,6 +482,7 @@ function file_managed_file_process($element, &$form_state, $form) {
*/
function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL) {
$fid = 0;
$force_default = FALSE;
// Find the current value of this field from the form state.
$form_state_fid = $form_state['values'];
@@ -510,15 +515,35 @@ function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL)
$callback($element, $input, $form_state);
}
}
// Load file if the FID has changed to confirm it exists.
if (isset($input['fid']) && $file = file_load($input['fid'])) {
$fid = $file->fid;
// If a FID was submitted, load the file (and check access if it's not a
// public file) to confirm it exists and that the current user has access
// to it.
if (isset($input['fid']) && ($file = file_load($input['fid']))) {
// By default the public:// file scheme provided by Drupal core is the
// only one that allows files to be publicly accessible to everyone, so
// it is the only one for which the file access checks are bypassed.
// Other modules which provide publicly accessible streams of their own
// in hook_stream_wrappers() can add the corresponding scheme to the
// 'file_public_schema' variable to bypass file access checks for those
// as well. This should only be done for schemes that are completely
// publicly accessible, with no download restrictions; for security
// reasons all other schemes must go through the file_download_access()
// check.
if (in_array(file_uri_scheme($file->uri), variable_get('file_public_schema', array('public'))) || file_download_access($file->uri)) {
$fid = $file->fid;
}
// If the current user doesn't have access, don't let the file be
// changed.
else {
$force_default = TRUE;
}
}
}
}
// If there is no input, set the default value.
else {
// If there is no input or if the default value was requested above, use the
// default value.
if ($input === FALSE || $force_default) {
if ($element['#extended']) {
$default_fid = isset($element['#default_value']['fid']) ? $element['#default_value']['fid'] : 0;
$return = isset($element['#default_value']) ? $element['#default_value'] : array('fid' => 0);

View File

@@ -220,6 +220,128 @@ class FileFieldTestCase extends DrupalWebTestCase {
}
}
/**
* Tests adding a file to a non-node entity.
*/
class FileTaxonomyTermTestCase extends DrupalWebTestCase {
protected $admin_user;
public static function getInfo() {
return array(
'name' => 'Taxonomy term file test',
'description' => 'Tests adding a file to a non-node entity.',
'group' => 'File',
);
}
public function setUp() {
$modules[] = 'file';
$modules[] = 'taxonomy';
parent::setUp($modules);
$this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer taxonomy'));
$this->drupalLogin($this->admin_user);
}
/**
* Creates a file field and attaches it to the "Tags" taxonomy vocabulary.
*
* @param $name
* The field name of the file field to create.
* @param $uri_scheme
* The URI scheme to use for the file field (for example, "private" to
* create a field that stores private files or "public" to create a field
* that stores public files).
*/
protected function createAttachFileField($name, $uri_scheme) {
$field = array(
'field_name' => $name,
'type' => 'file',
'settings' => array(
'uri_scheme' => $uri_scheme,
),
'cardinality' => 1,
);
field_create_field($field);
// Attach an instance of it.
$instance = array(
'field_name' => $name,
'label' => 'File',
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'required' => FALSE,
'settings' => array(),
'widget' => array(
'type' => 'file_generic',
'settings' => array(),
),
);
field_create_instance($instance);
}
/**
* Tests that a public file can be attached to a taxonomy term.
*
* This is a regression test for https://www.drupal.org/node/2305017.
*/
public function testTermFilePublic() {
$this->_testTermFile('public');
}
/**
* Tests that a private file can be attached to a taxonomy term.
*
* This is a regression test for https://www.drupal.org/node/2305017.
*/
public function testTermFilePrivate() {
$this->_testTermFile('private');
}
/**
* Runs tests for attaching a file field to a taxonomy term.
*
* @param $uri_scheme
* The URI scheme to use for the file field, either "public" or "private".
*/
protected function _testTermFile($uri_scheme) {
$field_name = strtolower($this->randomName());
$this->createAttachFileField($field_name, $uri_scheme);
// Get a file to upload.
$file = current($this->drupalGetTestFiles('text'));
// Add a filesize property to files as would be read by file_load().
$file->filesize = filesize($file->uri);
$langcode = LANGUAGE_NONE;
$edit = array(
"name" => $this->randomName(),
);
// Attach a file to the term.
$edit['files[' . $field_name . '_' . $langcode . '_0]'] = drupal_realpath($file->uri);
$this->drupalPost("admin/structure/taxonomy/tags/add", $edit, t('Save'));
// Find the term ID we just created.
$tid = db_query_range('SELECT tid FROM {taxonomy_term_data} ORDER BY tid DESC', 0, 1)->fetchField();
$terms = entity_load('taxonomy_term', array($tid));
$term = $terms[$tid];
$fid = $term->{$field_name}[LANGUAGE_NONE][0]['fid'];
// Check that the uploaded file is present on the edit form.
$this->drupalGet("taxonomy/term/$tid/edit");
$file_input_name = $field_name . '[' . LANGUAGE_NONE . '][0][fid]';
$this->assertFieldByXpath('//input[@type="hidden" and @name="' . $file_input_name . '"]', $fid, 'File is attached on edit form.');
// Edit the term and change name without changing the file.
$edit = array(
"name" => $this->randomName(),
);
$this->drupalPost("taxonomy/term/$tid/edit", $edit, t('Save'));
// Check that the uploaded file is still present on the edit form.
$this->drupalGet("taxonomy/term/$tid/edit");
$file_input_name = $field_name . '[' . LANGUAGE_NONE . '][0][fid]';
$this->assertFieldByXpath('//input[@type="hidden" and @name="' . $file_input_name . '"]', $fid, 'File is attached on edit form.');
// Load term while resetting the cache.
$terms = entity_load('taxonomy_term', array($tid), array(), TRUE);
$term = $terms[$tid];
$this->assertTrue(!empty($term->{$field_name}[LANGUAGE_NONE]), 'Term has attached files.');
$this->assertEqual($term->{$field_name}[LANGUAGE_NONE][0]['fid'], $fid, 'Same File ID is attached to the term.');
}
}
/**
* Tests the 'managed_file' element type.
*
@@ -352,6 +474,15 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
$node_file = (object) $node->{$field_name}[LANGUAGE_NONE][0];
$this->assertFileExists($node_file, 'New file saved to disk on node creation.');
// Test that running field_attach_update() leaves the file intact.
$field = new stdClass();
$field->type = $type_name;
$field->nid = $nid;
field_attach_update('node', $field);
$node = node_load($nid);
$node_file = (object) $node->{$field_name}[LANGUAGE_NONE][0];
$this->assertFileExists($node_file, 'New file still saved to disk on field update.');
// Ensure the file can be downloaded.
$this->drupalGet(file_create_url($node_file->uri));
$this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
@@ -755,6 +886,7 @@ class FileFieldDisplayTestCase extends FileFieldTestCase {
$field_settings = array(
'display_field' => '1',
'display_default' => '1',
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
);
$instance_settings = array(
'description_field' => '1',
@@ -795,6 +927,17 @@ class FileFieldDisplayTestCase extends FileFieldTestCase {
$this->assertNoRaw($default_output, 'Field is hidden when "display" option is unchecked.');
// Test that fields appear as expected during the preview.
// Add a second file.
$name = 'files[' . $field_name . '_' . LANGUAGE_NONE . '_1]';
$edit[$name] = drupal_realpath($test_file->uri);
// Uncheck the display checkboxes and go to the preview.
$edit[$field_name . '[' . LANGUAGE_NONE . '][0][display]'] = FALSE;
$edit[$field_name . '[' . LANGUAGE_NONE . '][1][display]'] = FALSE;
$this->drupalPost('node/' . $nid . '/edit', $edit, t('Preview'));
$this->assertRaw($field_name . '[' . LANGUAGE_NONE . '][0][display]', 'First file appears as expected.');
$this->assertRaw($field_name . '[' . LANGUAGE_NONE . '][1][display]', 'Second file appears as expected.');
}
}
@@ -1167,5 +1310,18 @@ class FilePrivateTestCase extends FileFieldTestCase {
// Ensure the file cannot be downloaded.
$this->drupalGet(file_create_url($node_file->uri));
$this->assertResponse(403, 'Confirmed that access is denied for the file without view field access permission.');
// Attempt to reuse the existing file when creating a new node, and confirm
// that access is still denied.
$edit = array();
$edit['title'] = $this->randomName(8);
$edit[$field_name . '[' . LANGUAGE_NONE . '][0][fid]'] = $node_file->fid;
$this->drupalPost('node/add/page', $edit, t('Save'));
$new_node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertTrue(!empty($new_node), 'Node was created.');
$this->assertUrl('node/' . $new_node->nid);
$this->assertNoRaw($node_file->filename, 'File without view field access permission does not appear after attempting to attach it to a new node.');
$this->drupalGet(file_create_url($node_file->uri));
$this->assertResponse(403, 'Confirmed that access is denied for the file without view field access permission after attempting to attach it to a new node.');
}
}

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -7,8 +7,8 @@ files[] = filter.test
required = TRUE
configure = admin/config/content/formats
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -348,9 +348,7 @@ function filter_permission() {
foreach (filter_formats() as $format) {
$permission = filter_permission_name($format);
if (!empty($permission)) {
// Only link to the text format configuration page if the user who is
// viewing this will have access to that page.
$format_name_replacement = user_access('administer filters') ? l($format->name, 'admin/config/content/formats/' . $format->format) : drupal_placeholder($format->name);
$format_name_replacement = l($format->name, 'admin/config/content/formats/' . $format->format);
$perms[$permission] = array(
'title' => t("Use the !text_format text format", array('!text_format' => $format_name_replacement,)),
'description' => drupal_placeholder(t('Warning: This permission may have security implications depending on how the text format is configured.')),

View File

@@ -68,7 +68,7 @@ function theme_filter_tips($variables) {
foreach ($tips as $name => $tiplist) {
if ($multiple) {
$output .= '<div class="filter-type filter-' . drupal_html_class($name) . '">';
$output .= '<h3>' . $name . '</h3>';
$output .= '<h3>' . check_plain($name) . '</h3>';
}
if (count($tiplist) > 0) {

View File

@@ -70,6 +70,15 @@ class FilterCRUDTestCase extends DrupalWebTestCase {
$this->assertFalse($db_format->status, 'Database: Disabled text format is marked as disabled.');
$formats = filter_formats();
$this->assertTrue(!isset($formats[$format->format]), 'filter_formats: Disabled text format no longer exists.');
// Add a new format to check for Xss in format name.
$format = new stdClass();
$format->format = 'xss_format';
$format->name = '<script>alert(123)</script>';
filter_format_save($format);
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(filter_permission_name($format) => 1));
$this->drupalGet('filter/tips');
$this->assertNoRaw($format->name, 'Text format name contains no xss.');
}
/**

View File

@@ -9,8 +9,8 @@ files[] = forum.test
configure = admin/structure/forum
stylesheets[all][] = forum.css
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -263,10 +263,10 @@ function _forum_node_check_node_type($node) {
* Implements hook_node_view().
*/
function forum_node_view($node, $view_mode) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node)) {
if ($view_mode == 'full' && node_is_page($node)) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
// Breadcrumb navigation
$breadcrumb[] = l(t('Home'), NULL);
$breadcrumb[] = l($vocabulary->name, 'forum');

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = help.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -7,8 +7,8 @@ dependencies[] = file
files[] = image.test
configure = admin/config/media/image-styles
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -845,6 +845,12 @@ function image_style_deliver($style, $scheme) {
}
}
// Confirm that the original source image exists before trying to process it.
if (!is_file($image_uri)) {
watchdog('image', 'Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', array('%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri));
return MENU_NOT_FOUND;
}
// Don't start generating the image if the derivative already exists or if
// generation is in progress in another thread.
$lock_name = 'image_style_deliver:' . $style['name'] . ':' . drupal_hash_base64($image_uri);
@@ -854,6 +860,7 @@ function image_style_deliver($style, $scheme) {
// Tell client to retry again in 3 seconds. Currently no browsers are known
// to support Retry-After.
drupal_add_http_header('Status', '503 Service Unavailable');
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
drupal_add_http_header('Retry-After', 3);
print t('Image generation in progress. Try again shortly.');
drupal_exit();
@@ -875,6 +882,7 @@ function image_style_deliver($style, $scheme) {
else {
watchdog('image', 'Unable to generate the derived image located at %path.', array('%path' => $derivative_uri));
drupal_add_http_header('Status', '500 Internal Server Error');
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
print t('Error generating image.');
drupal_exit();
}
@@ -1019,7 +1027,15 @@ function image_style_url($style_name, $path) {
// The token query is added even if the 'image_allow_insecure_derivatives'
// variable is TRUE, so that the emitted links remain valid if it is changed
// back to the default FALSE.
$token_query = array(IMAGE_DERIVATIVE_TOKEN => image_style_path_token($style_name, $original_uri));
// However, sites which need to prevent the token query from being emitted at
// all can additionally set the 'image_suppress_itok_output' variable to TRUE
// to achieve that (if both are set, the security token will neither be
// emitted in the image derivative URL nor checked for in
// image_style_deliver()).
$token_query = array();
if (!variable_get('image_suppress_itok_output', FALSE)) {
$token_query = array(IMAGE_DERIVATIVE_TOKEN => image_style_path_token($style_name, $original_uri));
}
// If not using clean URLs, the image derivative callback is only available
// with the query string. If the file does not exist, use url() to ensure
@@ -1031,8 +1047,12 @@ function image_style_url($style_name, $path) {
}
$file_url = file_create_url($uri);
// Append the query string with the token.
return $file_url . (strpos($file_url, '?') !== FALSE ? '&' : '?') . drupal_http_build_query($token_query);
// Append the query string with the token, if necessary.
if ($token_query) {
$file_url .= (strpos($file_url, '?') !== FALSE ? '&' : '?') . drupal_http_build_query($token_query);
}
return $file_url;
}
/**

View File

@@ -173,6 +173,16 @@ class ImageStylesPathAndUrlTestCase extends DrupalWebTestCase {
$this->_testImageStyleUrlAndPath('public', TRUE, TRUE);
}
/**
* Test that an invalid source image returns a 404.
*/
function testImageStyleUrlForMissingSourceImage() {
$non_existent_uri = 'public://foo.png';
$generated_url = image_style_url($this->style_name, $non_existent_uri);
$this->drupalGet($generated_url);
$this->assertResponse(404, 'Accessing an image style URL with a source image that does not exist provides a 404 error response.');
}
/**
* Test image_style_url().
*/
@@ -320,6 +330,15 @@ class ImageStylesPathAndUrlTestCase extends DrupalWebTestCase {
$this->drupalGet($nested_url);
$this->assertResponse(200, 'Image was accessible when a correct token was provided in the URL.');
// Suppress the security token in the URL, then get the URL of a file. Check
// that the security token is not present in the URL but that the image is
// still accessible.
variable_set('image_suppress_itok_output', TRUE);
$generate_url = image_style_url($this->style_name, $original_uri);
$this->assertIdentical(strpos($generate_url, IMAGE_DERIVATIVE_TOKEN . '='), FALSE, 'The security token does not appear in the image style URL.');
$this->drupalGet($generate_url);
$this->assertResponse(200, 'Image was accessible at the URL with a missing token.');
// Check that requesting a nonexistent image does not create any new
// directories in the file system.
$directory = $scheme . '://styles/' . $this->style_name . '/' . $scheme . '/' . $this->randomName();

View File

@@ -6,8 +6,8 @@ core = 7.x
files[] = image_module_test.module
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -1139,11 +1139,11 @@ function locale_translate_edit_form($form, &$form_state, $lid) {
'#value' => $source->location
);
// Include default form controls with empty values for all languages.
// This ensures that the languages are always in the same order in forms.
// Include both translated and not yet translated target languages in the
// list. The source language is English for built-in strings and the default
// language for other strings.
$languages = language_list();
$default = language_default();
// We don't need the default language value, that value is in $source.
$omit = $source->textgroup == 'default' ? 'en' : $default->language;
unset($languages[($omit)]);
$form['translations'] = array('#tree' => TRUE);

View File

@@ -6,8 +6,8 @@ core = 7.x
files[] = locale.test
configure = admin/config/regional/language
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -1202,7 +1202,7 @@ EOF;
* Helper function that returns a .po file with context.
*/
function getPoFileWithContext() {
// Croatian (code hr) is one the the languages that have a different
// Croatian (code hr) is one of the languages that have a different
// form for the full name and the abbreviated name for the month May.
return <<< EOF
msgid ""

View File

@@ -5,8 +5,8 @@ package = Testing
version = VERSION
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -6,8 +6,8 @@ core = 7.x
files[] = menu.test
configure = admin/structure/menu
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -69,7 +69,7 @@ function menu_menu() {
'title' => 'Parent menu items',
'page callback' => 'menu_parent_options_js',
'type' => MENU_CALLBACK,
'access arguments' => array(TRUE),
'access arguments' => array('administer menu'),
);
$items['admin/structure/menu/list'] = array(
'title' => 'List menus',

View File

@@ -513,6 +513,23 @@ class MenuTestCase extends DrupalWebTestCase {
}
}
/**
* Test administrative users other than user 1 can access the menu parents AJAX callback.
*/
public function testMenuParentsJsAccess() {
$admin = $this->drupalCreateUser(array('administer menu'));
$this->drupalLogin($admin);
// Just check access to the callback overall, the POST data is irrelevant.
$this->drupalGetAJAX('admin/structure/menu/parents');
$this->assertResponse(200);
// Do standard user tests.
// Login the user.
$this->drupalLogin($this->std_user);
$this->drupalGetAJAX('admin/structure/menu/parents');
$this->assertResponse(403);
}
/**
* Get standard menu link.
*/

View File

@@ -17,11 +17,14 @@
* During node operations (create, update, view, delete, etc.), there are
* several sets of hooks that get invoked to allow modules to modify the base
* node operation:
* - Node-type-specific hooks: These hooks are only invoked on the primary
* module, using the "base" return component of hook_node_info() as the
* function prefix. For example, poll.module defines the base for the Poll
* content type as "poll", so during creation of a poll node, hook_insert() is
* only invoked by calling poll_insert().
* - Node-type-specific hooks: When defining a node type, hook_node_info()
* returns a 'base' component. Node-type-specific hooks are named
* base_hookname() instead of mymodule_hookname() (in a module called
* 'mymodule' for example). Only the node type's corresponding implementation
* is invoked. For example, poll_node_info() in poll.module defines the base
* for the 'poll' node type as 'poll'. So when a poll node is created,
* hook_insert() is invoked on poll_insert() only.
* Hooks that are node-type-specific are noted below.
* - All-module hooks: This set of hooks is invoked on all implementing modules,
* to allow other modules to modify what the primary node module is doing. For
* example, hook_node_insert() is invoked on all modules when creating a poll
@@ -195,7 +198,7 @@ function hook_node_grants($account, $op) {
if (user_access('access private content', $account)) {
$grants['example'] = array(1);
}
$grants['example_owner'] = array($account->uid);
$grants['example_author'] = array($account->uid);
return $grants;
}
@@ -885,11 +888,10 @@ function hook_node_view_alter(&$build) {
* name as the key. Each sub-array has up to 10 attributes. Possible
* attributes:
* - name: (required) The human-readable name of the node type.
* - base: (required) The base string used to construct callbacks
* corresponding to this node type (for example, if base is defined as
* example_foo, then example_foo_insert will be called when inserting a node
* of that type). This string is usually the name of the module, but not
* always.
* - base: (required) The base name for implementations of node-type-specific
* hooks that respond to this node type. Base is usually the name of the
* module or 'node_content', but not always. See
* @link node_api_hooks Node API hooks @endlink for more information.
* - description: (required) A brief description of the node type.
* - help: (optional) Help information shown to the user when creating a node
* of this type.
@@ -1030,8 +1032,11 @@ function hook_node_type_delete($info) {
/**
* Respond to node deletion.
*
* This hook is invoked only on the module that defines the node's content type
* (use hook_node_delete() to respond to all node deletions).
* This is a node-type-specific hook, which is invoked only for the node type
* being affected. See
* @link node_api_hooks Node API hooks @endlink for more information.
*
* Use hook_node_delete() to respond to node deletion of all node types.
*
* This hook is invoked from node_delete_multiple() before hook_node_delete()
* is invoked and before field_attach_delete() is called.
@@ -1059,8 +1064,11 @@ function hook_delete($node) {
/**
* Act on a node object about to be shown on the add/edit form.
*
* This hook is invoked only on the module that defines the node's content type
* (use hook_node_prepare() to act on all node preparations).
* This is a node-type-specific hook, which is invoked only for the node type
* being affected. See
* @link node_api_hooks Node API hooks @endlink for more information.
*
* Use hook_node_prepare() to respond to node preparation of all node types.
*
* This hook is invoked from node_object_prepare() before the general
* hook_node_prepare() is invoked.
@@ -1089,6 +1097,13 @@ function hook_prepare($node) {
/**
* Display a node editing form.
*
* This is a node-type-specific hook, which is invoked only for the node type
* being affected. See
* @link node_api_hooks Node API hooks @endlink for more information.
*
* Use hook_form_BASE_FORM_ID_alter(), with base form ID 'node_form', to alter
* node forms for all node types.
*
* This hook, implemented by node modules, is called to retrieve the form
* that is displayed to create or edit a node. This form is displayed at path
* node/add/[node type] or node/[node ID]/edit.
@@ -1144,8 +1159,11 @@ function hook_form($node, &$form_state) {
/**
* Respond to creation of a new node.
*
* This hook is invoked only on the module that defines the node's content type
* (use hook_node_insert() to act on all node insertions).
* This is a node-type-specific hook, which is invoked only for the node type
* being affected. See
* @link node_api_hooks Node API hooks @endlink for more information.
*
* Use hook_node_insert() to respond to node insertion of all node types.
*
* This hook is invoked from node_save() after the node is inserted into the
* node table in the database, before field_attach_insert() is called, and
@@ -1168,8 +1186,11 @@ function hook_insert($node) {
/**
* Act on nodes being loaded from the database.
*
* This hook is invoked only on the module that defines the node's content type
* (use hook_node_load() to respond to all node loads).
* This is a node-type-specific hook, which is invoked only for the node type
* being affected. See
* @link node_api_hooks Node API hooks @endlink for more information.
*
* Use hook_node_load() to respond to node load of all node types.
*
* This hook is invoked during node loading, which is handled by entity_load(),
* via classes NodeController and DrupalDefaultEntityController. After the node
@@ -1202,8 +1223,11 @@ function hook_load($nodes) {
/**
* Respond to updates to a node.
*
* This hook is invoked only on the module that defines the node's content type
* (use hook_node_update() to act on all node updates).
* This is a node-type-specific hook, which is invoked only for the node type
* being affected. See
* @link node_api_hooks Node API hooks @endlink for more information.
*
* Use hook_node_update() to respond to node update of all node types.
*
* This hook is invoked from node_save() after the node is updated in the
* node table in the database, before field_attach_update() is called, and
@@ -1224,8 +1248,11 @@ function hook_update($node) {
/**
* Perform node validation before a node is created or updated.
*
* This hook is invoked only on the module that defines the node's content type
* (use hook_node_validate() to act on all node validations).
* This is a node-type-specific hook, which is invoked only for the node type
* being affected. See
* @link node_api_hooks Node API hooks @endlink for more information.
*
* Use hook_node_validate() to respond to node validation of all node types.
*
* This hook is invoked from node_validate(), after a user has finished
* editing the node and is previewing or submitting it. It is invoked at the end
@@ -1258,8 +1285,11 @@ function hook_validate($node, $form, &$form_state) {
/**
* Display a node.
*
* This hook is invoked only on the module that defines the node's content type
* (use hook_node_view() to act on all node views).
* This is a node-type-specific hook, which is invoked only for the node type
* being affected. See
* @link node_api_hooks Node API hooks @endlink for more information.
*
* Use hook_node_view() to respond to node view of all node types.
*
* This hook is invoked during node viewing after the node is fully loaded, so
* that the node type module can define a custom method for display, or add to
@@ -1269,6 +1299,10 @@ function hook_validate($node, $form, &$form_state) {
* The node to be displayed, as returned by node_load().
* @param $view_mode
* View mode, e.g. 'full', 'teaser', ...
* @param $langcode
* (optional) A language code to use for rendering. Defaults to the global
* content language of the current request.
*
* @return
* The passed $node parameter should be modified as necessary and returned so
* it can be properly presented. Nodes are prepared for display by assembling
@@ -1282,7 +1316,7 @@ function hook_validate($node, $form, &$form_state) {
*
* @ingroup node_api_hooks
*/
function hook_view($node, $view_mode) {
function hook_view($node, $view_mode, $langcode = NULL) {
if ($view_mode == 'full' && node_is_page($node)) {
$breadcrumb = array();
$breadcrumb[] = l(t('Home'), NULL);

View File

@@ -9,8 +9,8 @@ required = TRUE
configure = admin/structure/types
stylesheets[all][] = node.css
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -210,7 +210,7 @@ function node_entity_info() {
'custom settings' => FALSE,
),
'search_result' => array(
'label' => t('Search result'),
'label' => t('Search result highlighting input'),
'custom settings' => FALSE,
),
);
@@ -506,7 +506,8 @@ function node_type_load($name) {
* - custom: TRUE or FALSE indicating whether this type is defined by a module
* (FALSE) or by a user (TRUE) via Add Content Type.
* - modified: TRUE or FALSE indicating whether this type has been modified by
* an administrator. Currently not used in any way.
* an administrator. When modifying an existing node type, set to TRUE, or
* the change will be ignored on node_types_rebuild().
* - locked: TRUE or FALSE indicating whether the administrator can change the
* machine name of this type.
* - disabled: TRUE or FALSE indicating whether this type has been disabled.
@@ -739,11 +740,9 @@ function _node_types_build($rebuild = FALSE) {
$type_db = $type_object->type;
// Original disabled value.
$disabled = $type_object->disabled;
// Check for node types from disabled modules and mark their types for removal.
// Types defined by the node module in the database (rather than by a separate
// module using hook_node_info) have a base value of 'node_content'. The isset()
// check prevents errors on old (pre-Drupal 7) databases.
if (isset($type_object->base) && $type_object->base != 'node_content' && empty($_node_types->types[$type_db])) {
// Check for node types either from disabled modules or otherwise not defined
// and mark as disabled.
if (empty($type_object->custom) && empty($_node_types->types[$type_db])) {
$type_object->disabled = TRUE;
}
if (isset($_node_types->types[$type_db])) {
@@ -1397,12 +1396,7 @@ function node_build_content($node, $view_mode = 'full', $langcode = NULL) {
$node->content = array();
// Allow modules to change the view mode.
$context = array(
'entity_type' => 'node',
'entity' => $node,
'langcode' => $langcode,
);
drupal_alter('entity_view_mode', $view_mode, $context);
$view_mode = key(entity_view_mode_prepare('node', array($node->nid => $node), $view_mode, $langcode));
// The 'view' hook can be implemented to overwrite the default function
// to display nodes.
@@ -1585,9 +1579,7 @@ function node_permission() {
),
'access content overview' => array(
'title' => t('Access the content overview page'),
'description' => user_access('access content overview')
? t('Get an overview of <a href="@url">all content</a>.', array('@url' => url('admin/content')))
: t('Get an overview of all content.'),
'description' => t('Get an overview of <a href="@url">all content</a>.', array('@url' => url('admin/content'))),
),
'access content' => array(
'title' => t('View published content'),
@@ -1615,7 +1607,7 @@ function node_permission() {
}
/**
* Gathers the rankings from the the hook_ranking() implementations.
* Gathers the rankings from the hook_ranking() implementations.
*
* @param $query
* A query object that has been extended with the Search DB Extender.
@@ -2604,9 +2596,10 @@ function node_feed($nids = FALSE, $channel = array()) {
$node->link = url("node/$node->nid", array('absolute' => TRUE));
$node->rss_namespaces = array();
$account = user_load($node->uid);
$node->rss_elements = array(
array('key' => 'pubDate', 'value' => gmdate('r', $node->created)),
array('key' => 'dc:creator', 'value' => $node->name),
array('key' => 'dc:creator', 'value' => format_username($account)),
array('key' => 'guid', 'value' => $node->nid . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))
);
@@ -2664,15 +2657,26 @@ function node_feed($nids = FALSE, $channel = array()) {
* An array in the format expected by drupal_render().
*/
function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0, $langcode = NULL) {
field_attach_prepare_view('node', $nodes, $view_mode, $langcode);
entity_prepare_view('node', $nodes, $langcode);
$build = array();
$entities_by_view_mode = entity_view_mode_prepare('node', $nodes, $view_mode, $langcode);
foreach ($entities_by_view_mode as $entity_view_mode => $entities) {
field_attach_prepare_view('node', $entities, $entity_view_mode, $langcode);
entity_prepare_view('node', $entities, $langcode);
foreach ($entities as $entity) {
$build['nodes'][$entity->nid] = node_view($entity, $entity_view_mode, $langcode);
}
}
foreach ($nodes as $node) {
$build['nodes'][$node->nid] = node_view($node, $view_mode, $langcode);
$build['nodes'][$node->nid]['#weight'] = $weight;
$weight++;
}
// Sort here, to preserve the input order of the entities that were passed to
// this function.
uasort($build['nodes'], 'element_sort');
$build['nodes']['#sorted'] = TRUE;
return $build;
}
@@ -3629,7 +3633,8 @@ function node_access_rebuild($batch_mode = FALSE) {
// Try to allocate enough time to rebuild node grants
drupal_set_time_limit(240);
$nids = db_query("SELECT nid FROM {node}")->fetchCol();
// Rebuild newest nodes first so that recent content becomes available quickly.
$nids = db_query("SELECT nid FROM {node} ORDER BY nid DESC")->fetchCol();
foreach ($nids as $nid) {
$node = node_load($nid, NULL, TRUE);
// To preserve database integrity, only acquire grants if the node

View File

@@ -371,35 +371,38 @@ function node_form_build_preview($form, &$form_state) {
* @see node_form_build_preview()
*/
function node_preview($node) {
if (node_access('create', $node) || node_access('update', $node)) {
_field_invoke_multiple('load', 'node', array($node->nid => $node));
// Clone the node before previewing it to prevent the node itself from being
// modified.
$cloned_node = clone $node;
if (node_access('create', $cloned_node) || node_access('update', $cloned_node)) {
_field_invoke_multiple('load', 'node', array($cloned_node->nid => $cloned_node));
// Load the user's name when needed.
if (isset($node->name)) {
if (isset($cloned_node->name)) {
// The use of isset() is mandatory in the context of user IDs, because
// user ID 0 denotes the anonymous user.
if ($user = user_load_by_name($node->name)) {
$node->uid = $user->uid;
$node->picture = $user->picture;
if ($user = user_load_by_name($cloned_node->name)) {
$cloned_node->uid = $user->uid;
$cloned_node->picture = $user->picture;
}
else {
$node->uid = 0; // anonymous user
$cloned_node->uid = 0; // anonymous user
}
}
elseif ($node->uid) {
$user = user_load($node->uid);
$node->name = $user->name;
$node->picture = $user->picture;
elseif ($cloned_node->uid) {
$user = user_load($cloned_node->uid);
$cloned_node->name = $user->name;
$cloned_node->picture = $user->picture;
}
$node->changed = REQUEST_TIME;
$nodes = array($node->nid => $node);
$cloned_node->changed = REQUEST_TIME;
$nodes = array($cloned_node->nid => $cloned_node);
field_attach_prepare_view('node', $nodes, 'full');
// Display a preview of the node.
if (!form_get_errors()) {
$node->in_preview = TRUE;
$output = theme('node_preview', array('node' => $node));
unset($node->in_preview);
$cloned_node->in_preview = TRUE;
$output = theme('node_preview', array('node' => $cloned_node));
unset($cloned_node->in_preview);
}
drupal_set_title(t('Preview'), PASS_THROUGH);

View File

@@ -2782,8 +2782,8 @@ class NodeEntityViewModeAlterTest extends NodeWebTestCase {
$edit = array();
$langcode = LANGUAGE_NONE;
$edit["title"] = $this->randomName(8);
$edit["body[$langcode][0][value]"] = t('Data that should appear only in the body for the node.');
$edit["body[$langcode][0][summary]"] = t('Extra data that should appear only in the teaser for the node.');
$edit["body[$langcode][0][value]"] = 'Data that should appear only in the body for the node.';
$edit["body[$langcode][0][summary]"] = 'Extra data that should appear only in the teaser for the node.';
$this->drupalPost('node/add/page', $edit, t('Save'));
$node = $this->drupalGetNodeByTitle($edit["title"]);
@@ -2801,6 +2801,45 @@ class NodeEntityViewModeAlterTest extends NodeWebTestCase {
$build = node_view($node);
$this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
}
/**
* Tests fields that were previously hidden when the view mode is changed.
*/
function testNodeViewModeChangeHiddenField() {
// Hide the tags field on the default display
$instance = field_info_instance('node', 'field_tags', 'article');
$instance['display']['default']['type'] = 'hidden';
field_update_instance($instance);
$web_user = $this->drupalCreateUser(array('create article content', 'edit own article content'));
$this->drupalLogin($web_user);
// Create a node.
$edit = array();
$langcode = LANGUAGE_NONE;
$edit["title"] = $this->randomName(8);
$edit["body[$langcode][0][value]"] = 'Data that should appear only in the body for the node.';
$edit["body[$langcode][0][summary]"] = 'Extra data that should appear only in the teaser for the node.';
$edit["field_tags[$langcode]"] = 'Extra tag';
$this->drupalPost('node/add/article', $edit, t('Save'));
$node = $this->drupalGetNodeByTitle($edit["title"]);
// Set the flag to alter the view mode and view the node.
variable_set('node_test_change_view_mode', 'teaser');
$this->drupalGet('node/' . $node->nid);
// Check that teaser mode is viewed.
$this->assertText('Extra data that should appear only in the teaser for the node.', 'Teaser text present');
// Make sure body text is not present.
$this->assertNoText('Data that should appear only in the body for the node.', 'Body text not present');
// Make sure tags are present.
$this->assertText('Extra tag', 'Taxonomy term present');
// Test that the correct build mode has been set.
$build = node_view($node);
$this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
}
}
/**

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -211,7 +211,7 @@ function node_access_test_node_insert($node) {
}
/**
* Implements hook_nodeapi_update().
* Implements hook_node_update().
*/
function node_access_test_node_update($node) {
_node_access_test_node_write($node);

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -158,6 +158,11 @@ function _openid_xrds_parse($raw_xml) {
return array();
}
// Also stop parsing if there is an unreasonably large number of tags.
if ($dom->getElementsByTagName('*')->length > variable_get('openid_xrds_maximum_tag_count', 30000)) {
return array();
}
// Parse the DOM document for the information we need.
if ($xml = simplexml_import_dom($dom)) {
foreach ($xml->children(OPENID_NS_XRD)->XRD as $xrd) {

View File

@@ -5,8 +5,8 @@ package = Core
core = 7.x
files[] = openid.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -6,8 +6,8 @@ core = 7.x
dependencies[] = openid
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -4,8 +4,8 @@ package = Core
version = VERSION
core = 7.x
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -6,8 +6,8 @@ core = 7.x
files[] = path.test
configure = admin/config/search/path
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = php.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -6,8 +6,8 @@ core = 7.x
files[] = poll.test
stylesheets[all][] = poll.css
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -249,6 +249,7 @@ function poll_form($node, &$form_state) {
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
'#maxlength' => 255,
'#weight' => -5,
);
@@ -720,7 +721,6 @@ function poll_view_voting($form, &$form_state, $node, $block = FALSE) {
'#type' => 'radios',
'#title' => t('Choices'),
'#title_display' => 'invisible',
'#default_value' => -1,
'#options' => $list,
);
}
@@ -748,7 +748,7 @@ function poll_view_voting($form, &$form_state, $node, $block = FALSE) {
* Validation function for processing votes
*/
function poll_view_voting_validate($form, &$form_state) {
if ($form_state['values']['choice'] == -1) {
if (empty($form_state['values']['choice'])) {
form_set_error( 'choice', t('Your vote could not be recorded because you did not select any of the choices.'));
}
}
@@ -925,7 +925,6 @@ function template_preprocess_poll_results(&$variables) {
*
* @see poll-bar.tpl.php
* @see poll-bar--block.tpl.php
* @see theme_poll_bar()
*/
function template_preprocess_poll_bar(&$variables) {
if ($variables['block']) {

View File

@@ -315,6 +315,11 @@ class PollVoteTestCase extends PollTestCase {
$this->drupalLogin($vote_user);
// Record a vote without selecting any choice.
$edit = array();
$this->drupalPost('node/' . $poll_nid, $edit, t('Vote'));
$this->assertText(t('Your vote could not be recorded because you did not select any of the choices.'), 'Found the empty poll submission error message.');
// Record a vote for the first choice.
$edit = array(
'choice' => '1',

View File

@@ -11,8 +11,8 @@ configure = admin/config/people/profile
; See user_system_info_alter().
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = rdf.test
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -190,17 +190,33 @@ function _rdf_get_default_mapping($type) {
* An RDF mapping structure or an empty array if no record was found.
*/
function _rdf_mapping_load($type, $bundle) {
$mapping = db_select('rdf_mapping')
->fields(NULL, array('mapping'))
->condition('type', $type)
->condition('bundle', $bundle)
->execute()
->fetchField();
$mappings = _rdf_mapping_load_multiple($type, array($bundle));
return $mappings ? reset($mappings) : array();
}
if (!$mapping) {
return array();
/**
* Helper function to retrieve a set of RDF mappings from the database.
*
* @param $type
* The entity type of the mappings.
* @param $bundles
* The bundles the mappings refer to.
*
* @return
* An array of RDF mapping structures, or an empty array.
*/
function _rdf_mapping_load_multiple($type, array $bundles) {
$mappings = db_select('rdf_mapping')
->fields(NULL, array('bundle', 'mapping'))
->condition('type', $type)
->condition('bundle', $bundles)
->execute()
->fetchAllKeyed();
foreach ($mappings as $bundle => $mapping) {
$mappings[$bundle] = unserialize($mapping);
}
return unserialize($mapping);
return $mappings;
}
/**
@@ -368,10 +384,13 @@ function rdf_modules_uninstalled($modules) {
function rdf_entity_info_alter(&$entity_info) {
// Loop through each entity type and its bundles.
foreach ($entity_info as $entity_type => $entity_type_info) {
if (isset($entity_type_info['bundles'])) {
foreach ($entity_type_info['bundles'] as $bundle => $bundle_info) {
if ($mapping = _rdf_mapping_load($entity_type, $bundle)) {
$entity_info[$entity_type]['bundles'][$bundle]['rdf_mapping'] = $mapping;
if (!empty($entity_type_info['bundles'])) {
$bundles = array_keys($entity_type_info['bundles']);
$mappings = _rdf_mapping_load_multiple($entity_type, $bundles);
foreach ($bundles as $bundle) {
if (isset($mappings[$bundle])) {
$entity_info[$entity_type]['bundles'][$bundle]['rdf_mapping'] = $mappings[$bundle];
}
else {
// If no mapping was found in the database, assign the default RDF
@@ -471,27 +490,17 @@ function rdf_preprocess_node(&$variables) {
$variables['attributes_array']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
$variables['attributes_array']['typeof'] = empty($variables['node']->rdf_mapping['rdftype']) ? NULL : $variables['node']->rdf_mapping['rdftype'];
// Adds RDFa markup to the title of the node. Because the RDFa markup is
// added to the <h2> tag which might contain HTML code, we specify an empty
// datatype to ensure the value of the title read by the RDFa parsers is a
// literal.
$variables['title_attributes_array']['property'] = empty($variables['node']->rdf_mapping['title']['predicates']) ? NULL : $variables['node']->rdf_mapping['title']['predicates'];
$variables['title_attributes_array']['datatype'] = '';
// In full node mode, the title is not displayed by node.tpl.php so it is
// added in the <head> tag of the HTML page.
if ($variables['page']) {
$element = array(
'#tag' => 'meta',
'#attributes' => array(
'content' => $variables['node']->title,
'about' => $variables['node_url'],
// Adds RDFa markup about the title of the node to the title_suffix.
if (!empty($variables['node']->rdf_mapping['title']['predicates'])) {
$variables['title_suffix']['rdf_meta_title'] = array(
'#theme' => 'rdf_metadata',
'#metadata' => array(
array(
'property' => $variables['node']->rdf_mapping['title']['predicates'],
'content' => $variables['node']->title,
),
),
);
if (!empty($variables['node']->rdf_mapping['title']['predicates'])) {
$element['#attributes']['property'] = $variables['node']->rdf_mapping['title']['predicates'];
}
drupal_add_html_head($element, 'rdf_node_title');
}
// Adds RDFa markup for the date.
@@ -511,35 +520,20 @@ function rdf_preprocess_node(&$variables) {
}
// Adds RDFa markup annotating the number of comments a node has.
if (isset($variables['node']->comment_count) && !empty($variables['node']->rdf_mapping['comment_count']['predicates'])) {
// Annotates the 'x comments' link in teaser view.
if (isset($variables['content']['links']['comment']['#links']['comment-comments'])) {
$comment_count_attributes['property'] = $variables['node']->rdf_mapping['comment_count']['predicates'];
$comment_count_attributes['content'] = $variables['node']->comment_count;
$comment_count_attributes['datatype'] = $variables['node']->rdf_mapping['comment_count']['datatype'];
// According to RDFa parsing rule number 4, a new subject URI is created
// from the href attribute if no rel/rev attribute is present. To get the
// original node URL from the about attribute of the parent container we
// set an empty rel attribute which triggers rule number 5. See
// http://www.w3.org/TR/rdfa-syntax/#sec_5.5.
$comment_count_attributes['rel'] = '';
$variables['content']['links']['comment']['#links']['comment-comments']['attributes'] += $comment_count_attributes;
}
// In full node view, the number of comments is not displayed by
// node.tpl.php so it is expressed in RDFa in the <head> tag of the HTML
// page.
if ($variables['page'] && user_access('access comments')) {
$element = array(
'#tag' => 'meta',
'#attributes' => array(
'about' => $variables['node_url'],
if (isset($variables['node']->comment_count) &&
!empty($variables['node']->rdf_mapping['comment_count']['predicates']) &&
user_access('access comments')) {
// Adds RDFa markup for the comment count near the node title as metadata.
$variables['title_suffix']['rdf_meta_comment_count'] = array(
'#theme' => 'rdf_metadata',
'#metadata' => array(
array(
'property' => $variables['node']->rdf_mapping['comment_count']['predicates'],
'content' => $variables['node']->comment_count,
'datatype' => $variables['node']->rdf_mapping['comment_count']['datatype'],
),
);
drupal_add_html_head($element, 'rdf_node_comment_count');
}
),
);
}
}
@@ -865,9 +859,9 @@ function theme_rdf_metadata($variables) {
$output = '';
foreach ($variables['metadata'] as $attributes) {
// Add a class so that developers viewing the HTML source can see why there
// are empty <span> tags in the document. The class can also be used to set
// a CSS display:none rule in a theme where empty spans affect display.
// are empty <span> tags in the document.
$attributes['class'][] = 'rdf-meta';
$attributes['class'][] = 'element-hidden';
// The XHTML+RDFa doctype allows either <span></span> or <span /> syntax to
// be used, but for maximum browser compatibility, W3C recommends the
// former when serving pages using the text/html media type, see

View File

@@ -301,7 +301,7 @@ class RdfMappingDefinitionTestCase extends TaxonomyWebTestCase {
// Ensure the default bundle mapping for node is used. These attributes come
// from the node default bundle definition.
$blog_title = $this->xpath("//meta[@property='dc:title' and @content='$node->title']");
$blog_title = $this->xpath("//div[@about='$url']/span[@property='dc:title' and @content='$node->title']");
$blog_meta = $this->xpath("//div[(@about='$url') and (@typeof='sioct:Weblog')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']");
$this->assertTrue(!empty($blog_title), 'Property dc:title is present in meta tag.');
$this->assertTrue(!empty($blog_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.');
@@ -324,7 +324,7 @@ class RdfMappingDefinitionTestCase extends TaxonomyWebTestCase {
$this->drupalGet('node/' . $node->nid);
// Ensure the mapping defined in rdf_module.test is used.
$test_bundle_title = $this->xpath('//meta[@property="dc:title" and @content="' . $node->title . '"]');
$test_bundle_title = $this->xpath("//div[@about='$url']/span[@property='dc:title' and @content=\"$node->title\"]");
$test_bundle_meta = $this->xpath("//div[(@about='$url') and contains(@typeof, 'foo:mapping_install1') and contains(@typeof, 'bar:mapping_install2')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']");
$this->assertTrue(!empty($test_bundle_title), 'Property dc:title is present in meta tag.');
$this->assertTrue(!empty($test_bundle_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.');
@@ -343,7 +343,7 @@ class RdfMappingDefinitionTestCase extends TaxonomyWebTestCase {
// Ensure the default bundle mapping for node is used. These attributes come
// from the node default bundle definition.
$random_bundle_title = $this->xpath("//meta[@property='dc:title' and @content='$node->title']");
$random_bundle_title = $this->xpath("//div[@about='$url']/span[@property='dc:title' and @content='$node->title']");
$random_bundle_meta = $this->xpath("//div[(@about='$url') and contains(@typeof, 'sioc:Item') and contains(@typeof, 'foaf:Document')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']");
$this->assertTrue(!empty($random_bundle_title), 'Property dc:title is present in meta tag.');
$this->assertTrue(!empty($random_bundle_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.');
@@ -461,15 +461,13 @@ class RdfCommentAttributesTestCase extends CommentHelperCase {
// Tests number of comments in teaser view.
$this->drupalGet('node');
$comment_count_teaser = $this->xpath('//div[contains(@typeof, "sioc:Item")]//li[contains(@class, "comment-comments")]/a[contains(@property, "sioc:num_replies") and contains(@content, "2") and @datatype="xsd:integer"]');
$node_url = url('node/' . $this->node1->nid);
$comment_count_teaser = $this->xpath('//div[@about=:node-url]/span[@property="sioc:num_replies" and @content="2" and @datatype="xsd:integer"]', array(':node-url' => $node_url));
$this->assertTrue(!empty($comment_count_teaser), 'RDFa markup for the number of comments found on teaser view.');
$comment_count_link = $this->xpath('//div[@about=:url]//a[contains(@property, "sioc:num_replies") and @rel=""]', array(':url' => url("node/{$this->node1->nid}")));
$this->assertTrue(!empty($comment_count_link), 'Empty rel attribute found in comment count link.');
// Tests number of comments in full node view.
$this->drupalGet('node/' . $this->node1->nid);
$node_url = url('node/' . $this->node1->nid);
$comment_count_teaser = $this->xpath('/html/head/meta[@about=:node-url and @property="sioc:num_replies" and @content="2" and @datatype="xsd:integer"]', array(':node-url' => $node_url));
$comment_count_teaser = $this->xpath('//div[@about=:node-url]/span[@property="sioc:num_replies" and @content="2" and @datatype="xsd:integer"]', array(':node-url' => $node_url));
$this->assertTrue(!empty($comment_count_teaser), 'RDFa markup for the number of comments found on full node view.');
}

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -149,6 +149,17 @@ class SearchQuery extends SelectQueryExtender {
$this->searchExpression = $expression;
$this->type = $module;
// Add a search_* tag. This needs to be added before any preExecute methods
// for decorated queries are called, as $this->prepared will be set to TRUE
// and tags added in the execute method will never get used. For example,
// if $query is extended by 'SearchQuery' then 'PagerDefault', the
// search-specific tag will be added too late (when preExecute() has
// already been called from the PagerDefault extender), and as a
// consequence will not be available to hook_query_alter() implementations,
// nor will the correct hook_query_TAG_alter() implementations get invoked.
// See node_search_execute().
$this->addTag('search_' . $module);
return $this;
}
@@ -494,9 +505,8 @@ class SearchQuery extends SelectQueryExtender {
$this->orderBy('calculated_score', 'DESC');
}
// Add tag and useful metadata.
// Add useful metadata.
$this
->addTag('search_' . $this->type)
->addMetaData('normalize', $this->normalize)
->fields('i', array('type', 'sid'));

View File

@@ -8,8 +8,8 @@ files[] = search.test
configure = admin/config/search/settings
stylesheets[all][] = search.css
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -2048,6 +2048,47 @@ class SearchNodeAccessTest extends DrupalWebTestCase {
}
}
/**
* Tests node search with query tags.
*/
class SearchNodeTagTest extends DrupalWebTestCase {
public $test_user;
public static function getInfo() {
return array(
'name' => 'Node search query tags',
'description' => 'Tests Node search tags functionality.',
'group' => 'Search',
);
}
function setUp() {
parent::setUp('search', 'search_node_tags');
node_access_rebuild();
// Create a test user and log in.
$this->test_user = $this->drupalCreateUser(array('search content'));
$this->drupalLogin($this->test_user);
}
/**
* Tests that the correct tags are available and hooks invoked.
*/
function testNodeSearchQueryTags() {
$this->drupalCreateNode(array('body' => array(LANGUAGE_NONE => array(array('value' => 'testing testing testing.')))));
// Update the search index.
module_invoke_all('update_index');
search_update_totals();
$edit = array('keys' => 'testing');
$this->drupalPost('search/node', $edit, t('Search'));
$this->assertTrue(variable_get('search_node_tags_test_query_tag', FALSE), 'hook_query_alter() was invoked and the query contained the "search_node" tag.');
$this->assertTrue(variable_get('search_node_tags_test_query_tag_hook', FALSE), 'hook_query_search_node_alter() was invoked.');
}
}
/**
* Tests searching with locale values set.
*/

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-05-08
version = "7.28"
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1399522731"
datestamp = "1427943826"

View File

@@ -0,0 +1,12 @@
name = "Test search node tags"
description = "Support module for Node search tags testing."
package = Testing
version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2015-04-02
version = "7.36"
project = "drupal"
datestamp = "1427943826"

View File

@@ -0,0 +1,23 @@
<?php
/**
* @file
* Dummy module implementing a node search hooks for search module testing.
*/
/**
* Implements hook_query_alter().
*/
function search_node_tags_query_alter(QueryAlterableInterface $query) {
if ($query->hasTag('search_node')) {
variable_set('search_node_tags_test_query_tag', TRUE);
}
}
/**
* Implements hook_query_TAG_alter().
*/
function search_node_tags_query_search_node_alter(QueryAlterableInterface $query) {
variable_set('search_node_tags_test_query_tag_hook', TRUE);
}

Some files were not shown because too many files have changed in this diff Show More