|
@@ -688,6 +688,13 @@ function drupal_goto($path = '', array $options = array(), $http_response_code =
|
|
$options['fragment'] = $destination['fragment'];
|
|
$options['fragment'] = $destination['fragment'];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // In some cases modules call drupal_goto(current_path()). We need to ensure
|
|
|
|
+ // that such a redirect is not to an external URL.
|
|
|
|
+ if ($path === current_path() && empty($options['external']) && url_is_external($path)) {
|
|
|
|
+ // Force url() to generate a non-external URL.
|
|
|
|
+ $options['external'] = FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
drupal_alter('drupal_goto', $path, $options, $http_response_code);
|
|
drupal_alter('drupal_goto', $path, $options, $http_response_code);
|
|
|
|
|
|
// The 'Location' HTTP header must be absolute.
|
|
// The 'Location' HTTP header must be absolute.
|
|
@@ -753,7 +760,8 @@ function drupal_access_denied() {
|
|
* - headers: An array containing request headers to send as name/value pairs.
|
|
* - headers: An array containing request headers to send as name/value pairs.
|
|
* - method: A string containing the request method. Defaults to 'GET'.
|
|
* - method: A string containing the request method. Defaults to 'GET'.
|
|
* - data: A string containing the request body, formatted as
|
|
* - data: A string containing the request body, formatted as
|
|
- * 'param=value¶m=value&...'. Defaults to NULL.
|
|
|
|
|
|
+ * 'param=value¶m=value&...'; to generate this, use http_build_query().
|
|
|
|
+ * Defaults to NULL.
|
|
* - max_redirects: An integer representing how many times a redirect
|
|
* - max_redirects: An integer representing how many times a redirect
|
|
* may be followed. Defaults to 3.
|
|
* may be followed. Defaults to 3.
|
|
* - timeout: A float representing the maximum number of seconds the function
|
|
* - timeout: A float representing the maximum number of seconds the function
|
|
@@ -778,6 +786,8 @@ function drupal_access_denied() {
|
|
* HTTP header names are case-insensitive (RFC 2616, section 4.2), so for
|
|
* HTTP header names are case-insensitive (RFC 2616, section 4.2), so for
|
|
* easy access the array keys are returned in lower case.
|
|
* easy access the array keys are returned in lower case.
|
|
* - data: A string containing the response body that was received.
|
|
* - data: A string containing the response body that was received.
|
|
|
|
+ *
|
|
|
|
+ * @see http_build_query()
|
|
*/
|
|
*/
|
|
function drupal_http_request($url, array $options = array()) {
|
|
function drupal_http_request($url, array $options = array()) {
|
|
// Allow an alternate HTTP client library to replace Drupal's default
|
|
// Allow an alternate HTTP client library to replace Drupal's default
|
|
@@ -1057,6 +1067,12 @@ function drupal_http_request($url, array $options = array()) {
|
|
|
|
|
|
switch ($code) {
|
|
switch ($code) {
|
|
case 200: // OK
|
|
case 200: // OK
|
|
|
|
+ case 201: // Created
|
|
|
|
+ case 202: // Accepted
|
|
|
|
+ case 203: // Non-Authoritative Information
|
|
|
|
+ case 204: // No Content
|
|
|
|
+ case 205: // Reset Content
|
|
|
|
+ case 206: // Partial Content
|
|
case 304: // Not modified
|
|
case 304: // Not modified
|
|
break;
|
|
break;
|
|
case 301: // Moved permanently
|
|
case 301: // Moved permanently
|
|
@@ -1522,7 +1538,7 @@ function _filter_xss_split($m, $store = FALSE) {
|
|
return '<';
|
|
return '<';
|
|
}
|
|
}
|
|
|
|
|
|
- if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?|(<!--.*?-->)$%', $string, $matches)) {
|
|
|
|
|
|
+ if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9\-]+)([^>]*)>?|(<!--.*?-->)$%', $string, $matches)) {
|
|
// Seriously malformed.
|
|
// Seriously malformed.
|
|
return '';
|
|
return '';
|
|
}
|
|
}
|
|
@@ -1754,9 +1770,15 @@ function format_rss_item($title, $link, $description, $args = array()) {
|
|
* - 'key': element name
|
|
* - 'key': element name
|
|
* - 'value': element contents
|
|
* - 'value': element contents
|
|
* - 'attributes': associative array of element attributes
|
|
* - 'attributes': associative array of element attributes
|
|
|
|
+ * - 'encoded': TRUE if 'value' is already encoded
|
|
*
|
|
*
|
|
* In both cases, 'value' can be a simple string, or it can be another array
|
|
* In both cases, 'value' can be a simple string, or it can be another array
|
|
* with the same format as $array itself for nesting.
|
|
* with the same format as $array itself for nesting.
|
|
|
|
+ *
|
|
|
|
+ * If 'encoded' is TRUE it is up to the caller to ensure that 'value' is either
|
|
|
|
+ * entity-encoded or CDATA-escaped. Using this option is not recommended when
|
|
|
|
+ * working with untrusted user input, since failing to escape the data
|
|
|
|
+ * correctly has security implications.
|
|
*/
|
|
*/
|
|
function format_xml_elements($array) {
|
|
function format_xml_elements($array) {
|
|
$output = '';
|
|
$output = '';
|
|
@@ -1769,7 +1791,7 @@ function format_xml_elements($array) {
|
|
}
|
|
}
|
|
|
|
|
|
if (isset($value['value']) && $value['value'] != '') {
|
|
if (isset($value['value']) && $value['value'] != '') {
|
|
- $output .= '>' . (is_array($value['value']) ? format_xml_elements($value['value']) : check_plain($value['value'])) . '</' . $value['key'] . ">\n";
|
|
|
|
|
|
+ $output .= '>' . (is_array($value['value']) ? format_xml_elements($value['value']) : (!empty($value['encoded']) ? $value['value'] : check_plain($value['value']))) . '</' . $value['key'] . ">\n";
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
$output .= " />\n";
|
|
$output .= " />\n";
|
|
@@ -2214,20 +2236,8 @@ function url($path = NULL, array $options = array()) {
|
|
'prefix' => ''
|
|
'prefix' => ''
|
|
);
|
|
);
|
|
|
|
|
|
- // A duplicate of the code from url_is_external() to avoid needing another
|
|
|
|
- // function call, since performance inside url() is critical.
|
|
|
|
if (!isset($options['external'])) {
|
|
if (!isset($options['external'])) {
|
|
- // Return an external link if $path contains an allowed absolute URL. Avoid
|
|
|
|
- // calling drupal_strip_dangerous_protocols() if there is any slash (/),
|
|
|
|
- // hash (#) or question_mark (?) before the colon (:) occurrence - if any -
|
|
|
|
- // as this would clearly mean it is not a URL. If the path starts with 2
|
|
|
|
- // slashes then it is always considered an external URL without an explicit
|
|
|
|
- // protocol part.
|
|
|
|
- $colonpos = strpos($path, ':');
|
|
|
|
- $options['external'] = (strpos($path, '//') === 0)
|
|
|
|
- || ($colonpos !== FALSE
|
|
|
|
- && !preg_match('![/?#]!', substr($path, 0, $colonpos))
|
|
|
|
- && drupal_strip_dangerous_protocols($path) == $path);
|
|
|
|
|
|
+ $options['external'] = url_is_external($path);
|
|
}
|
|
}
|
|
|
|
|
|
// Preserve the original path before altering or aliasing.
|
|
// Preserve the original path before altering or aliasing.
|
|
@@ -2347,12 +2357,18 @@ function url($path = NULL, array $options = array()) {
|
|
*/
|
|
*/
|
|
function url_is_external($path) {
|
|
function url_is_external($path) {
|
|
$colonpos = strpos($path, ':');
|
|
$colonpos = strpos($path, ':');
|
|
- // Avoid calling drupal_strip_dangerous_protocols() if there is any slash (/),
|
|
|
|
- // hash (#) or question_mark (?) before the colon (:) occurrence - if any - as
|
|
|
|
- // this would clearly mean it is not a URL. If the path starts with 2 slashes
|
|
|
|
- // then it is always considered an external URL without an explicit protocol
|
|
|
|
- // part.
|
|
|
|
|
|
+ // Some browsers treat \ as / so normalize to forward slashes.
|
|
|
|
+ $path = str_replace('\\', '/', $path);
|
|
|
|
+ // If the path starts with 2 slashes then it is always considered an external
|
|
|
|
+ // URL without an explicit protocol part.
|
|
return (strpos($path, '//') === 0)
|
|
return (strpos($path, '//') === 0)
|
|
|
|
+ // Leading control characters may be ignored or mishandled by browsers, so
|
|
|
|
+ // assume such a path may lead to an external location. The \p{C} character
|
|
|
|
+ // class matches all UTF-8 control, unassigned, and private characters.
|
|
|
|
+ || (preg_match('/^\p{C}/u', $path) !== 0)
|
|
|
|
+ // Avoid calling drupal_strip_dangerous_protocols() if there is any slash
|
|
|
|
+ // (/), hash (#) or question_mark (?) before the colon (:) occurrence - if
|
|
|
|
+ // any - as this would clearly mean it is not a URL.
|
|
|| ($colonpos !== FALSE
|
|
|| ($colonpos !== FALSE
|
|
&& !preg_match('![/?#]!', substr($path, 0, $colonpos))
|
|
&& !preg_match('![/?#]!', substr($path, 0, $colonpos))
|
|
&& drupal_strip_dangerous_protocols($path) == $path);
|
|
&& drupal_strip_dangerous_protocols($path) == $path);
|
|
@@ -2637,6 +2653,15 @@ function drupal_deliver_html_page($page_callback_result) {
|
|
global $language;
|
|
global $language;
|
|
drupal_add_http_header('Content-Language', $language->language);
|
|
drupal_add_http_header('Content-Language', $language->language);
|
|
|
|
|
|
|
|
+ // By default, do not allow the site to be rendered in an iframe on another
|
|
|
|
+ // domain, but provide a variable to override this. If the code running for
|
|
|
|
+ // this page request already set the X-Frame-Options header earlier, don't
|
|
|
|
+ // overwrite it here.
|
|
|
|
+ $frame_options = variable_get('x_frame_options', 'SAMEORIGIN');
|
|
|
|
+ if ($frame_options && is_null(drupal_get_http_header('X-Frame-Options'))) {
|
|
|
|
+ drupal_add_http_header('X-Frame-Options', $frame_options);
|
|
|
|
+ }
|
|
|
|
+
|
|
// Menu status constants are integers; page content is a string or array.
|
|
// Menu status constants are integers; page content is a string or array.
|
|
if (is_int($page_callback_result)) {
|
|
if (is_int($page_callback_result)) {
|
|
// @todo: Break these up into separate functions?
|
|
// @todo: Break these up into separate functions?
|
|
@@ -2751,6 +2776,7 @@ function drupal_page_footer() {
|
|
_registry_check_code(REGISTRY_WRITE_LOOKUP_CACHE);
|
|
_registry_check_code(REGISTRY_WRITE_LOOKUP_CACHE);
|
|
drupal_cache_system_paths();
|
|
drupal_cache_system_paths();
|
|
module_implements_write_cache();
|
|
module_implements_write_cache();
|
|
|
|
+ drupal_file_scan_write_cache();
|
|
system_run_automated_cron();
|
|
system_run_automated_cron();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2812,11 +2838,11 @@ function drupal_map_assoc($array, $function = NULL) {
|
|
* into script execution a call such as set_time_limit(20) is made, the
|
|
* into script execution a call such as set_time_limit(20) is made, the
|
|
* script will run for a total of 45 seconds before timing out.
|
|
* script will run for a total of 45 seconds before timing out.
|
|
*
|
|
*
|
|
- * It also means that it is possible to decrease the total time limit if
|
|
|
|
- * the sum of the new time limit and the current time spent running the
|
|
|
|
- * script is inferior to the original time limit. It is inherent to the way
|
|
|
|
- * set_time_limit() works, it should rather be called with an appropriate
|
|
|
|
- * value every time you need to allocate a certain amount of time
|
|
|
|
|
|
+ * If the current time limit is not unlimited it is possible to decrease the
|
|
|
|
+ * total time limit if the sum of the new time limit and the current time spent
|
|
|
|
+ * running the script is inferior to the original time limit. It is inherent to
|
|
|
|
+ * the way set_time_limit() works, it should rather be called with an
|
|
|
|
+ * appropriate value every time you need to allocate a certain amount of time
|
|
* to execute a task than only once at the beginning of the script.
|
|
* to execute a task than only once at the beginning of the script.
|
|
*
|
|
*
|
|
* Before calling set_time_limit(), we check if this function is available
|
|
* Before calling set_time_limit(), we check if this function is available
|
|
@@ -2833,7 +2859,11 @@ function drupal_map_assoc($array, $function = NULL) {
|
|
*/
|
|
*/
|
|
function drupal_set_time_limit($time_limit) {
|
|
function drupal_set_time_limit($time_limit) {
|
|
if (function_exists('set_time_limit')) {
|
|
if (function_exists('set_time_limit')) {
|
|
- @set_time_limit($time_limit);
|
|
|
|
|
|
+ $current = ini_get('max_execution_time');
|
|
|
|
+ // Do not set time limit if it is currently unlimited.
|
|
|
|
+ if ($current != 0) {
|
|
|
|
+ @set_time_limit($time_limit);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3014,6 +3044,13 @@ function drupal_add_html_head_link($attributes, $header = FALSE) {
|
|
*/
|
|
*/
|
|
function drupal_add_css($data = NULL, $options = NULL) {
|
|
function drupal_add_css($data = NULL, $options = NULL) {
|
|
$css = &drupal_static(__FUNCTION__, array());
|
|
$css = &drupal_static(__FUNCTION__, array());
|
|
|
|
+ $count = &drupal_static(__FUNCTION__ . '_count', 0);
|
|
|
|
+
|
|
|
|
+ // If the $css variable has been reset with drupal_static_reset(), there is
|
|
|
|
+ // no longer any CSS being tracked, so set the counter back to 0 also.
|
|
|
|
+ if (count($css) === 0) {
|
|
|
|
+ $count = 0;
|
|
|
|
+ }
|
|
|
|
|
|
// Construct the options, taking the defaults into consideration.
|
|
// Construct the options, taking the defaults into consideration.
|
|
if (isset($options)) {
|
|
if (isset($options)) {
|
|
@@ -3049,7 +3086,8 @@ function drupal_add_css($data = NULL, $options = NULL) {
|
|
}
|
|
}
|
|
|
|
|
|
// Always add a tiny value to the weight, to conserve the insertion order.
|
|
// Always add a tiny value to the weight, to conserve the insertion order.
|
|
- $options['weight'] += count($css) / 1000;
|
|
|
|
|
|
+ $options['weight'] += $count / 1000;
|
|
|
|
+ $count++;
|
|
|
|
|
|
// Add the data to the CSS array depending on the type.
|
|
// Add the data to the CSS array depending on the type.
|
|
switch ($options['type']) {
|
|
switch ($options['type']) {
|
|
@@ -3802,7 +3840,7 @@ function drupal_load_stylesheet_content($contents, $optimize = FALSE) {
|
|
|
|
|
|
// Replaces @import commands with the actual stylesheet content.
|
|
// Replaces @import commands with the actual stylesheet content.
|
|
// This happens recursively but omits external files.
|
|
// This happens recursively but omits external files.
|
|
- $contents = preg_replace_callback('/@import\s*(?:url\(\s*)?[\'"]?(?![a-z]+:)([^\'"\()]+)[\'"]?\s*\)?\s*;/', '_drupal_load_stylesheet', $contents);
|
|
|
|
|
|
+ $contents = preg_replace_callback('/@import\s*(?:url\(\s*)?[\'"]?(?![a-z]+:)(?!\/\/)([^\'"\()]+)[\'"]?\s*\)?\s*;/', '_drupal_load_stylesheet', $contents);
|
|
return $contents;
|
|
return $contents;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3862,6 +3900,21 @@ function drupal_delete_file_if_stale($uri) {
|
|
* The cleaned identifier.
|
|
* The cleaned identifier.
|
|
*/
|
|
*/
|
|
function drupal_clean_css_identifier($identifier, $filter = array(' ' => '-', '_' => '-', '/' => '-', '[' => '-', ']' => '')) {
|
|
function drupal_clean_css_identifier($identifier, $filter = array(' ' => '-', '_' => '-', '/' => '-', '[' => '-', ']' => '')) {
|
|
|
|
+ // Use the advanced drupal_static() pattern, since this is called very often.
|
|
|
|
+ static $drupal_static_fast;
|
|
|
|
+ if (!isset($drupal_static_fast)) {
|
|
|
|
+ $drupal_static_fast['allow_css_double_underscores'] = &drupal_static(__FUNCTION__ . ':allow_css_double_underscores');
|
|
|
|
+ }
|
|
|
|
+ $allow_css_double_underscores = &$drupal_static_fast['allow_css_double_underscores'];
|
|
|
|
+ if (!isset($allow_css_double_underscores)) {
|
|
|
|
+ $allow_css_double_underscores = variable_get('allow_css_double_underscores', FALSE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Preserve BEM-style double-underscores depending on custom setting.
|
|
|
|
+ if ($allow_css_double_underscores) {
|
|
|
|
+ $filter['__'] = '__';
|
|
|
|
+ }
|
|
|
|
+
|
|
// By default, we filter using Drupal's coding standards.
|
|
// By default, we filter using Drupal's coding standards.
|
|
$identifier = strtr($identifier, $filter);
|
|
$identifier = strtr($identifier, $filter);
|
|
|
|
|
|
@@ -5212,6 +5265,11 @@ function _drupal_bootstrap_full() {
|
|
fix_gpc_magic();
|
|
fix_gpc_magic();
|
|
// Load all enabled modules
|
|
// Load all enabled modules
|
|
module_load_all();
|
|
module_load_all();
|
|
|
|
+ // Reset drupal_alter() and module_implements() static caches as these
|
|
|
|
+ // include implementations for vital modules only when called early on
|
|
|
|
+ // in the bootstrap.
|
|
|
|
+ drupal_static_reset('drupal_alter');
|
|
|
|
+ drupal_static_reset('module_implements');
|
|
// Make sure all stream wrappers are registered.
|
|
// Make sure all stream wrappers are registered.
|
|
file_get_stream_wrappers();
|
|
file_get_stream_wrappers();
|
|
// Ensure mt_rand is reseeded, to prevent random values from one page load
|
|
// Ensure mt_rand is reseeded, to prevent random values from one page load
|
|
@@ -5308,8 +5366,8 @@ function drupal_page_set_cache() {
|
|
*
|
|
*
|
|
* Do not call this function from a test. Use $this->cronRun() instead.
|
|
* Do not call this function from a test. Use $this->cronRun() instead.
|
|
*
|
|
*
|
|
- * @return
|
|
|
|
- * TRUE if cron ran successfully.
|
|
|
|
|
|
+ * @return bool
|
|
|
|
+ * TRUE if cron ran successfully and FALSE if cron is already running.
|
|
*/
|
|
*/
|
|
function drupal_cron_run() {
|
|
function drupal_cron_run() {
|
|
// Allow execution to continue even if the request gets canceled.
|
|
// Allow execution to continue even if the request gets canceled.
|
|
@@ -5371,12 +5429,12 @@ function drupal_cron_run() {
|
|
// Do not run if queue wants to skip.
|
|
// Do not run if queue wants to skip.
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- $function = $info['worker callback'];
|
|
|
|
|
|
+ $callback = $info['worker callback'];
|
|
$end = time() + (isset($info['time']) ? $info['time'] : 15);
|
|
$end = time() + (isset($info['time']) ? $info['time'] : 15);
|
|
$queue = DrupalQueue::get($queue_name);
|
|
$queue = DrupalQueue::get($queue_name);
|
|
while (time() < $end && ($item = $queue->claimItem())) {
|
|
while (time() < $end && ($item = $queue->claimItem())) {
|
|
try {
|
|
try {
|
|
- $function($item->data);
|
|
|
|
|
|
+ call_user_func($callback, $item->data);
|
|
$queue->deleteItem($item);
|
|
$queue->deleteItem($item);
|
|
}
|
|
}
|
|
catch (Exception $e) {
|
|
catch (Exception $e) {
|
|
@@ -6329,13 +6387,21 @@ function drupal_render_cid_parts($granularity = NULL) {
|
|
}
|
|
}
|
|
|
|
|
|
if (!empty($granularity)) {
|
|
if (!empty($granularity)) {
|
|
|
|
+ $cache_per_role = $granularity & DRUPAL_CACHE_PER_ROLE;
|
|
|
|
+ $cache_per_user = $granularity & DRUPAL_CACHE_PER_USER;
|
|
|
|
+ // User 1 has special permissions outside of the role system, so when
|
|
|
|
+ // caching per role is requested, it should cache per user instead.
|
|
|
|
+ if ($user->uid == 1 && $cache_per_role) {
|
|
|
|
+ $cache_per_user = TRUE;
|
|
|
|
+ $cache_per_role = FALSE;
|
|
|
|
+ }
|
|
// 'PER_ROLE' and 'PER_USER' are mutually exclusive. 'PER_USER' can be a
|
|
// 'PER_ROLE' and 'PER_USER' are mutually exclusive. 'PER_USER' can be a
|
|
// resource drag for sites with many users, so when a module is being
|
|
// resource drag for sites with many users, so when a module is being
|
|
// equivocal, we favor the less expensive 'PER_ROLE' pattern.
|
|
// equivocal, we favor the less expensive 'PER_ROLE' pattern.
|
|
- if ($granularity & DRUPAL_CACHE_PER_ROLE) {
|
|
|
|
|
|
+ if ($cache_per_role) {
|
|
$cid_parts[] = 'r.' . implode(',', array_keys($user->roles));
|
|
$cid_parts[] = 'r.' . implode(',', array_keys($user->roles));
|
|
}
|
|
}
|
|
- elseif ($granularity & DRUPAL_CACHE_PER_USER) {
|
|
|
|
|
|
+ elseif ($cache_per_user) {
|
|
$cid_parts[] = "u.$user->uid";
|
|
$cid_parts[] = "u.$user->uid";
|
|
}
|
|
}
|
|
|
|
|
|
@@ -7075,7 +7141,8 @@ function drupal_uninstall_schema($module) {
|
|
* specification of a schema, as it was defined in a module's
|
|
* specification of a schema, as it was defined in a module's
|
|
* hook_schema(). No additional default values will be set,
|
|
* hook_schema(). No additional default values will be set,
|
|
* hook_schema_alter() is not invoked and these unprocessed
|
|
* hook_schema_alter() is not invoked and these unprocessed
|
|
- * definitions won't be cached.
|
|
|
|
|
|
+ * definitions won't be cached. To retrieve the schema after
|
|
|
|
+ * hook_schema_alter() has been invoked use drupal_get_schema().
|
|
*
|
|
*
|
|
* This function can be used to retrieve a schema specification in
|
|
* This function can be used to retrieve a schema specification in
|
|
* hook_schema(), so it allows you to derive your tables from existing
|
|
* hook_schema(), so it allows you to derive your tables from existing
|
|
@@ -7137,6 +7204,24 @@ function _drupal_schema_initialize(&$schema, $module, $remove_descriptions = TRU
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Retrieves the type for every field in a table schema.
|
|
|
|
+ *
|
|
|
|
+ * @param $table
|
|
|
|
+ * The name of the table from which to retrieve type information.
|
|
|
|
+ *
|
|
|
|
+ * @return
|
|
|
|
+ * An array of types, keyed by field name.
|
|
|
|
+ */
|
|
|
|
+function drupal_schema_field_types($table) {
|
|
|
|
+ $table_schema = drupal_get_schema($table);
|
|
|
|
+ $field_types = array();
|
|
|
|
+ foreach ($table_schema['fields'] as $field_name => $field_info) {
|
|
|
|
+ $field_types[$field_name] = isset($field_info['type']) ? $field_info['type'] : NULL;
|
|
|
|
+ }
|
|
|
|
+ return $field_types;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Retrieves a list of fields from a table schema.
|
|
* Retrieves a list of fields from a table schema.
|
|
*
|
|
*
|
|
@@ -7338,7 +7423,16 @@ function drupal_write_record($table, &$record, $primary_keys = array()) {
|
|
* Information stored in a module .info file:
|
|
* Information stored in a module .info file:
|
|
* - name: The real name of the module for display purposes.
|
|
* - name: The real name of the module for display purposes.
|
|
* - description: A brief description of the module.
|
|
* - description: A brief description of the module.
|
|
- * - dependencies: An array of shortnames of other modules this module requires.
|
|
|
|
|
|
+ * - dependencies: An array of dependency strings. Each is in the form
|
|
|
|
+ * 'project:module (versions)'; with the following meanings:
|
|
|
|
+ * - project: (optional) Project shortname, recommended to ensure uniqueness,
|
|
|
|
+ * if the module is part of a project hosted on drupal.org. If omitted,
|
|
|
|
+ * also omit the : that follows. The project name is currently ignored by
|
|
|
|
+ * Drupal core but is used for automated testing.
|
|
|
|
+ * - module: (required) Module shortname within the project.
|
|
|
|
+ * - (versions): Optional version information, consisting of one or more
|
|
|
|
+ * comma-separated operator/value pairs or simply version numbers, which
|
|
|
|
+ * can contain "x" as a wildcard. Examples: (>=7.22, <7.28), (7.x-3.x).
|
|
* - package: The name of the package of modules this module belongs to.
|
|
* - package: The name of the package of modules this module belongs to.
|
|
*
|
|
*
|
|
* See forum.info for an example of a module .info file.
|
|
* See forum.info for an example of a module .info file.
|
|
@@ -7418,7 +7512,6 @@ function drupal_parse_info_file($filename) {
|
|
*/
|
|
*/
|
|
function drupal_parse_info_format($data) {
|
|
function drupal_parse_info_format($data) {
|
|
$info = array();
|
|
$info = array();
|
|
- $constants = get_defined_constants();
|
|
|
|
|
|
|
|
if (preg_match_all('
|
|
if (preg_match_all('
|
|
@^\s* # Start at the beginning of a line, ignoring leading whitespace
|
|
@^\s* # Start at the beginning of a line, ignoring leading whitespace
|
|
@@ -7458,8 +7551,8 @@ function drupal_parse_info_format($data) {
|
|
}
|
|
}
|
|
|
|
|
|
// Handle PHP constants.
|
|
// Handle PHP constants.
|
|
- if (isset($constants[$value])) {
|
|
|
|
- $value = $constants[$value];
|
|
|
|
|
|
+ if (preg_match('/^\w+$/i', $value) && defined($value)) {
|
|
|
|
+ $value = constant($value);
|
|
}
|
|
}
|
|
|
|
|
|
// Insert actual value.
|
|
// Insert actual value.
|
|
@@ -7623,7 +7716,12 @@ function debug($data, $label = NULL, $print_r = FALSE) {
|
|
* Parses a dependency for comparison by drupal_check_incompatibility().
|
|
* Parses a dependency for comparison by drupal_check_incompatibility().
|
|
*
|
|
*
|
|
* @param $dependency
|
|
* @param $dependency
|
|
- * A dependency string, for example 'foo (>=7.x-4.5-beta5, 3.x)'.
|
|
|
|
|
|
+ * A dependency string, which specifies a module dependency, and optionally
|
|
|
|
+ * the project it comes from and versions that are supported. Supported
|
|
|
|
+ * formats include:
|
|
|
|
+ * - 'module'
|
|
|
|
+ * - 'project:module'
|
|
|
|
+ * - 'project:module (>=version, version)'
|
|
*
|
|
*
|
|
* @return
|
|
* @return
|
|
* An associative array with three keys:
|
|
* An associative array with three keys:
|
|
@@ -7638,6 +7736,12 @@ function debug($data, $label = NULL, $print_r = FALSE) {
|
|
* @see drupal_check_incompatibility()
|
|
* @see drupal_check_incompatibility()
|
|
*/
|
|
*/
|
|
function drupal_parse_dependency($dependency) {
|
|
function drupal_parse_dependency($dependency) {
|
|
|
|
+ $value = array();
|
|
|
|
+ // Split out the optional project name.
|
|
|
|
+ if (strpos($dependency, ':')) {
|
|
|
|
+ list($project_name, $dependency) = explode(':', $dependency);
|
|
|
|
+ $value['project'] = $project_name;
|
|
|
|
+ }
|
|
// We use named subpatterns and support every op that version_compare
|
|
// We use named subpatterns and support every op that version_compare
|
|
// supports. Also, op is optional and defaults to equals.
|
|
// supports. Also, op is optional and defaults to equals.
|
|
$p_op = '(?P<operation>!=|==|=|<|<=|>|>=|<>)?';
|
|
$p_op = '(?P<operation>!=|==|=|<|<=|>|>=|<>)?';
|
|
@@ -7646,7 +7750,6 @@ function drupal_parse_dependency($dependency) {
|
|
$p_major = '(?P<major>\d+)';
|
|
$p_major = '(?P<major>\d+)';
|
|
// By setting the minor version to x, branches can be matched.
|
|
// By setting the minor version to x, branches can be matched.
|
|
$p_minor = '(?P<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
|
|
$p_minor = '(?P<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
|
|
- $value = array();
|
|
|
|
$parts = explode('(', $dependency, 2);
|
|
$parts = explode('(', $dependency, 2);
|
|
$value['name'] = trim($parts[0]);
|
|
$value['name'] = trim($parts[0]);
|
|
if (isset($parts[1])) {
|
|
if (isset($parts[1])) {
|
|
@@ -7761,6 +7864,7 @@ function entity_get_info($entity_type = NULL) {
|
|
// Prepare entity schema fields SQL info for
|
|
// Prepare entity schema fields SQL info for
|
|
// DrupalEntityControllerInterface::buildQuery().
|
|
// DrupalEntityControllerInterface::buildQuery().
|
|
if (isset($entity_info[$name]['base table'])) {
|
|
if (isset($entity_info[$name]['base table'])) {
|
|
|
|
+ $entity_info[$name]['base table field types'] = drupal_schema_field_types($entity_info[$name]['base table']);
|
|
$entity_info[$name]['schema_fields_sql']['base table'] = drupal_schema_fields_sql($entity_info[$name]['base table']);
|
|
$entity_info[$name]['schema_fields_sql']['base table'] = drupal_schema_fields_sql($entity_info[$name]['base table']);
|
|
if (isset($entity_info[$name]['revision table'])) {
|
|
if (isset($entity_info[$name]['revision table'])) {
|
|
$entity_info[$name]['schema_fields_sql']['revision table'] = drupal_schema_fields_sql($entity_info[$name]['revision table']);
|
|
$entity_info[$name]['schema_fields_sql']['revision table'] = drupal_schema_fields_sql($entity_info[$name]['revision table']);
|