Commit 3b1aa6c1 authored by Riccardo Padovani's avatar Riccardo Padovani

Updated Drupal core to 7.30

parent 0e2475ef
Drupal 7.30, 2014-07-24
-----------------------
- Fixed a regression introduced in Drupal 7.29 that caused files or images
attached to taxonomy terms to be deleted when the taxonomy term was edited
and resaved (and other related bugs with contributed and custom modules).
- Added a warning on the permissions page to recommend restricting access to
the "View site reports" permission to trusted administrators. See
DRUPAL-PSA-2014-002.
- Numerous API documentation improvements.
- Additional automated test coverage.
Drupal 7.29, 2014-07-16
----------------------
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2014-003.
......
......@@ -139,9 +139,6 @@ Accessibility
Documentation
- Jennifer Hodgdon 'jhodgdon' http://drupal.org/user/155601
Security
- Greg Knaddison 'greggles' http://drupal.org/user/36762
Translations
- Gerhard Killesreiter 'killes' http://drupal.org/user/83
......@@ -154,6 +151,20 @@ Node Access
- Ken Rickard 'agentrickard' http://drupal.org/user/20975
- Jess Myrbo 'xjm' http://drupal.org/user/65776
Security team
-----------------
To report a security issue, see: https://drupal.org/security-team/report-issue
The Drupal security team provides Security Advisories for vulnerabilities,
assists developers in resolving security issues, and provides security
documentation. See http://drupal.org/security-team for more information. The
security team lead is:
- Michael Hess 'mlhess' https://drupal.org/user/102818
Module maintainers
------------------
......
......@@ -8,7 +8,7 @@
/**
* The current system version.
*/
define('VERSION', '7.29');
define('VERSION', '7.30');
/**
* Core API compatibility.
......
......@@ -544,37 +544,32 @@ function drupal_get_destination() {
}
/**
* Parses a system URL string into an associative array suitable for url().
* Parses a URL string into its path, query, and fragment components.
*
* This function should only be used for URLs that have been generated by the
* system, such as via url(). It should not be used for URLs that come from
* external sources, or URLs that link to external resources.
* This function splits both internal paths like @code node?b=c#d @endcode and
* external URLs like @code https://example.com/a?b=c#d @endcode into their
* component parts. See
* @link http://tools.ietf.org/html/rfc3986#section-3 RFC 3986 @endlink for an
* explanation of what the component parts are.
*
* The returned array contains a 'path' that may be passed separately to url().
* For example:
* @code
* $options = drupal_parse_url($_GET['destination']);
* $my_url = url($options['path'], $options);
* $my_link = l('Example link', $options['path'], $options);
* @endcode
* Note that, unlike the RFC, when passed an external URL, this function
* groups the scheme, authority, and path together into the path component.
*
* This is required, because url() does not support relative URLs containing a
* query string or fragment in its $path argument. Instead, any query string
* needs to be parsed into an associative query parameter array in
* $options['query'] and the fragment into $options['fragment'].
*
* @param $url
* The URL string to parse, f.e. $_GET['destination'].
* @param string $url
* The internal path or external URL string to parse.
*
* @return
* An associative array containing the keys:
* - 'path': The path of the URL. If the given $url is external, this includes
* the scheme and host.
* - 'query': An array of query parameters of $url, if existent.
* - 'fragment': The fragment of $url, if existent.
* @return array
* An associative array containing:
* - path: The path component of $url. If $url is an external URL, this
* includes the scheme, authority, and path.
* - query: An array of query parameters from $url, if they exist.
* - fragment: The fragment component from $url, if it exists.
*
* @see url()
* @see drupal_goto()
* @see l()
* @see url()
* @see http://tools.ietf.org/html/rfc3986
*
* @ingroup php_wrappers
*/
function drupal_parse_url($url) {
......
......@@ -2832,7 +2832,7 @@ function db_drop_table($table) {
* will be set to the value of the key in all rows. This is most useful for
* creating NOT NULL columns with no default value in existing tables.
* @param $keys_new
* Optional keys and indexes specification to be created on the table along
* (optional) Keys and indexes specification to be created on the table along
* with adding the field. The format is the same as a table specification, but
* without the 'fields' element. If you are adding a type 'serial' field, you
* MUST specify at least one key or index including it in this array. See
......@@ -3012,7 +3012,7 @@ function db_drop_index($table, $name) {
* @param $spec
* The field specification for the new field.
* @param $keys_new
* Optional keys and indexes specification to be created on the table along
* (optional) Keys and indexes specification to be created on the table along
* with changing the field. The format is the same as a table specification
* but without the 'fields' element.
*/
......
......@@ -416,7 +416,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
* This is most useful for creating NOT NULL columns with no default
* value in existing tables.
* @param $keys_new
* Optional keys and indexes specification to be created on the
* (optional) Keys and indexes specification to be created on the
* table along with adding the field. The format is the same as a
* table specification but without the 'fields' element. If you are
* adding a type 'serial' field, you MUST specify at least one key
......@@ -630,7 +630,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
* @param $spec
* The field specification for the new field.
* @param $keys_new
* Optional keys and indexes specification to be created on the
* (optional) Keys and indexes specification to be created on the
* table along with changing the field. The format is the same as a
* table specification but without the 'fields' element.
*
......
......@@ -46,7 +46,7 @@ interface DrupalEntityControllerInterface {
class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
/**
* Static cache of entities.
* Static cache of entities, keyed by entity ID.
*
* @var array
*/
......
......@@ -9,7 +9,9 @@
* Invokes XML-RPC methods on this server.
*
* @param array $callbacks
* Array of external XML-RPC method names with the callbacks they map to.
* Either an associative array of external XML-RPC method names as keys with
* the callbacks they map to as values, or a more complex structure
* describing XML-RPC callbacks as returned from hook_xmlrpc().
*/
function xmlrpc_server($callbacks) {
$xmlrpc_server = new stdClass();
......
......@@ -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-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -6,8 +6,8 @@ core = 7.x
files[] = block.test
configure = admin/structure/block
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -13,8 +13,8 @@ regions[footer] = Footer
regions[highlighted] = Highlighted
regions[help] = Help
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = blog.test
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -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-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = color.test
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -9,8 +9,8 @@ files[] = comment.test
configure = admin/content/comment
stylesheets[all][] = comment.css
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -6,8 +6,8 @@ core = 7.x
files[] = contact.test
configure = admin/structure/contact
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = contextual.test
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -7,8 +7,8 @@ files[] = dashboard.test
dependencies[] = block
configure = admin/dashboard/customize
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
files[] = dblog.test
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -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-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -961,6 +961,13 @@ function field_has_data($field) {
/**
* 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-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -7,8 +7,8 @@ dependencies[] = field
dependencies[] = options
files[] = tests/list.test
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -5,8 +5,8 @@ package = Testing
version = VERSION
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -6,8 +6,8 @@ core = 7.x
dependencies[] = field
files[] = number.test
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -6,8 +6,8 @@ core = 7.x
dependencies[] = field
files[] = options.test
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -7,8 +7,8 @@ dependencies[] = field
files[] = text.test
required = TRUE
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -6,8 +6,8 @@ files[] = field_test.entity.inc
version = VERSION
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -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-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -6,8 +6,8 @@ core = 7.x
dependencies[] = field
files[] = tests/file.test
; Information added by Drupal.org packaging script on 2014-07-16
version = "7.29"
; Information added by Drupal.org packaging script on 2014-07-24
version = "7.30"
project = "drupal"
datestamp = "1405543132"
datestamp = "1406239730"
......@@ -478,6 +478,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,16 +511,25 @@ function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL)
$callback($element, $input, $form_state);
}
}
// Load file and check access if the FID has changed, to confirm it
// exists and that the current user has access to it.
if (isset($input['fid']) && ($file = file_load($input['fid'])) && file_download_access($file->uri)) {
$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']))) {
if (file_uri_scheme($file->uri) == '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.
*
......
......@@ -5,8 +5,8 @@ version = VERSION
core = 7.x
hidden = TRUE