update core to 7.36
This commit is contained in:
@@ -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.
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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' => '<none>')),
|
||||
'#default_value' => isset($block->title) ? $block->title : '',
|
||||
'#weight' => -19,
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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".
|
||||
*/
|
||||
|
@@ -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'),
|
||||
|
@@ -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) {
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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.
|
||||
*
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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'];
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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];
|
||||
}
|
||||
|
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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'
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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']);
|
||||
}
|
||||
}
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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'];
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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.');
|
||||
}
|
||||
}
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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.')),
|
||||
|
@@ -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) {
|
||||
|
@@ -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.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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');
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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();
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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 ""
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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',
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
@@ -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);
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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']) {
|
||||
|
@@ -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',
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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.');
|
||||
}
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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'));
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
12
modules/search/tests/search_node_tags.info
Normal file
12
modules/search/tests/search_node_tags.info
Normal 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"
|
||||
|
23
modules/search/tests/search_node_tags.module
Normal file
23
modules/search/tests/search_node_tags.module
Normal 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
Reference in New Issue
Block a user