Compare commits
394
Commits
+12
@@ -6,6 +6,7 @@ sites/*/drushrc*
|
||||
#sites/*
|
||||
sites/*/files
|
||||
sites/*/private
|
||||
sites/all/translations/*
|
||||
|
||||
_base_d7.tmproj
|
||||
/_materio.sublime-project
|
||||
@@ -15,3 +16,14 @@ _base_d7.tmproj
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
*.sublime-project*
|
||||
|
||||
node_modules
|
||||
|
||||
.sass-cache
|
||||
typescript
|
||||
.directory
|
||||
|
||||
*.old_patched
|
||||
|
||||
sync_uploads
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
# Protect files and directories from prying eyes.
|
||||
<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$">
|
||||
<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig\.save)$">
|
||||
Order allow,deny
|
||||
</FilesMatch>
|
||||
|
||||
@@ -20,7 +20,7 @@ ErrorDocument 404 /index.php
|
||||
DirectoryIndex index.php index.html index.htm
|
||||
|
||||
# Override PHP settings that cannot be changed at runtime. See
|
||||
# sites/default/default.settings.php and drupal_initialize_variables() in
|
||||
# sites/default/default.settings.php and drupal_environment_initialize() in
|
||||
# includes/bootstrap.inc for settings that can be changed at runtime.
|
||||
|
||||
# PHP 5, Apache 1 and 2.
|
||||
@@ -56,6 +56,17 @@ DirectoryIndex index.php index.html index.htm
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
|
||||
# Set "protossl" to "s" if we were accessed via https://. This is used later
|
||||
# if you enable "www." stripping or enforcement, in order to ensure that
|
||||
# you don't bounce between http and https.
|
||||
RewriteRule ^ - [E=protossl]
|
||||
RewriteCond %{HTTPS} on
|
||||
RewriteRule ^ - [E=protossl:s]
|
||||
|
||||
# Make sure Authorization HTTP header is available to PHP
|
||||
# even when running as CGI or FastCGI.
|
||||
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
# Block access to "hidden" directories whose names begin with a period. This
|
||||
# includes directories used by version control systems such as Subversion or
|
||||
# Git to store control files. Files whose names begin with a period, as well
|
||||
@@ -71,18 +82,6 @@ DirectoryIndex index.php index.html index.htm
|
||||
# downloaded.
|
||||
RewriteRule "(^|/)\." - [F]
|
||||
|
||||
# custom
|
||||
RewriteCond %{HTTP_HOST} ^basebeta\.materio\.com [OR]
|
||||
RewriteCond %{HTTP_HOST} ^materio\.com [OR]
|
||||
RewriteCond %{HTTP_HOST} ^www\.materio\.fr [OR]
|
||||
RewriteCond %{HTTP_HOST} ^materio\.fr [OR]
|
||||
RewriteCond %{HTTP_HOST} ^www\.materio\.net [OR]
|
||||
RewriteCond %{HTTP_HOST} ^materio\.net [OR]
|
||||
RewriteCond %{HTTP_HOST} ^www\.materio\.eu [OR]
|
||||
RewriteCond %{HTTP_HOST} ^materio\.eu [NC]
|
||||
RewriteRule ^ http://www.materio.com%{REQUEST_URI} [L,R=301]
|
||||
|
||||
|
||||
# If your site can be accessed both with and without the 'www.' prefix, you
|
||||
# can use one of the following settings to redirect users to your preferred
|
||||
# URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option:
|
||||
@@ -90,14 +89,32 @@ DirectoryIndex index.php index.html index.htm
|
||||
# To redirect all users to access the site WITH the 'www.' prefix,
|
||||
# (http://example.com/... will be redirected to http://www.example.com/...)
|
||||
# uncomment the following:
|
||||
# RewriteCond %{HTTP_HOST} .
|
||||
# RewriteCond %{HTTP_HOST} !^www\. [NC]
|
||||
# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
#
|
||||
# RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# To redirect all users to access the site WITHOUT the 'www.' prefix,
|
||||
# (http://www.example.com/... will be redirected to http://example.com/...)
|
||||
# uncomment the following:
|
||||
# RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
|
||||
# RewriteRule ^ http://%1%{REQUEST_URI} [L,R=301]
|
||||
# RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# redirect all materiau domains to materio.com
|
||||
RewriteCond %{HTTP_HOST} ^basebeta\.materio\.com [OR]
|
||||
RewriteCond %{HTTP_HOST} ^www\.materio\.fr [OR]
|
||||
RewriteCond %{HTTP_HOST} ^materio\.fr [OR]
|
||||
RewriteCond %{HTTP_HOST} ^www\.materio\.net [OR]
|
||||
RewriteCond %{HTTP_HOST} ^materio\.net [OR]
|
||||
RewriteCond %{HTTP_HOST} ^www\.materio\.eu [OR]
|
||||
RewriteCond %{HTTP_HOST} ^materio\.eu [OR]
|
||||
RewriteCond %{HTTP_HOST} ^www\.materio\.com
|
||||
# RewriteRule ^ http%{ENV:protossl}://materio.com%{REQUEST_URI} [L,R=301]
|
||||
RewriteRule ^ https://materio.com%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Redirect to HTTPS
|
||||
# RewriteCond %{HTTPS} off
|
||||
# RewriteCond %{HTTP:X-Forwarded-Proto} !https
|
||||
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Modify the RewriteBase if you are using Drupal in a subdirectory or in a
|
||||
# VirtualDocumentRoot and the rewrite rules are not working properly.
|
||||
@@ -116,24 +133,6 @@ DirectoryIndex index.php index.html index.htm
|
||||
RewriteCond %{REQUEST_URI} !=/favicon.ico
|
||||
RewriteRule ^ index.php [L]
|
||||
|
||||
## local
|
||||
# RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1
|
||||
## maison quentin
|
||||
# RewriteCond %{REMOTE_ADDR} !^86\.68\.188\.175
|
||||
## materio
|
||||
# RewriteCond %{REMOTE_ADDR} !^212\.198\.136\.215
|
||||
## maison bach
|
||||
# RewriteCond %{REMOTE_ADDR} !^82\.230\.62\.145
|
||||
# RewriteRule !maintenance http://www.materio.com/maintenance [L,R=302,E=nocache:1]
|
||||
|
||||
## http://mark.koli.ch/2010/12/set-cache-control-and-expires-headers-on-a-redirect-with-mod-rewrite.html
|
||||
## Set the response header if the "nocache" environment variable is set
|
||||
## in the RewriteRule above.
|
||||
# Header always set Cache-Control "no-store, no-cache, must-revalidate" env=nocache
|
||||
## Set Expires too ...
|
||||
# Header always set Expires "Thu, 01 Jan 1970 00:00:00 GMT" env=nocache
|
||||
|
||||
|
||||
# Rules to correctly serve gzip compressed CSS and JS files.
|
||||
# Requires both mod_rewrite and mod_headers to be enabled.
|
||||
<IfModule mod_headers.c>
|
||||
@@ -160,94 +159,138 @@ DirectoryIndex index.php index.html index.htm
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# Add headers to all responses.
|
||||
<IfModule mod_headers.c>
|
||||
# Disable content sniffing, since it's an attack vector.
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
</IfModule>
|
||||
|
||||
# from boiler plate V5.02
|
||||
|
||||
# FROM Html5 BoilerPlate 4.0
|
||||
# ######################################################################
|
||||
# # MEDIA TYPES AND CHARACTER ENCODINGS #
|
||||
# ######################################################################
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Proper MIME type for all files
|
||||
# | Media types |
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# JavaScript
|
||||
# Normalize to standard type (it's sniffed in IE anyways)
|
||||
# tools.ietf.org/html/rfc4329#section-7.2
|
||||
AddType application/javascript js jsonp
|
||||
AddType application/json json
|
||||
# Serve resources with the proper media types (f.k.a. MIME types).
|
||||
#
|
||||
# https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||
# https://httpd.apache.org/docs/current/mod/mod_mime.html#addtype
|
||||
|
||||
# Audio
|
||||
AddType audio/ogg oga ogg
|
||||
AddType audio/mp4 m4a f4a f4b
|
||||
<IfModule mod_mime.c>
|
||||
|
||||
# Video
|
||||
AddType video/ogg ogv
|
||||
AddType video/mp4 mp4 m4v f4v f4p
|
||||
AddType video/webm webm
|
||||
AddType video/x-flv flv
|
||||
# Data interchange
|
||||
|
||||
# SVG
|
||||
# Required for svg webfonts on iPad
|
||||
# twitter.com/FontSquirrel/status/14855840545
|
||||
AddType image/svg+xml svg svgz
|
||||
AddEncoding gzip svgz
|
||||
|
||||
# Webfonts
|
||||
AddType application/vnd.ms-fontobject eot
|
||||
AddType application/x-font-ttf ttf ttc
|
||||
AddType font/opentype otf
|
||||
AddType application/x-font-woff woff
|
||||
|
||||
# Assorted types
|
||||
AddType image/x-icon ico
|
||||
AddType image/webp webp
|
||||
AddType text/cache-manifest appcache manifest
|
||||
AddType text/x-component htc
|
||||
AddType application/xml rss atom xml rdf
|
||||
AddType application/x-chrome-extension crx
|
||||
AddType application/x-opera-extension oex
|
||||
AddType application/x-xpinstall xpi
|
||||
AddType application/octet-stream safariextz
|
||||
AddType application/x-web-app-manifest+json webapp
|
||||
AddType text/x-vcard vcf
|
||||
AddType application/x-shockwave-flash swf
|
||||
AddType text/vtt vtt
|
||||
AddType application/atom+xml atom
|
||||
AddType application/json json map topojson
|
||||
AddType application/ld+json jsonld
|
||||
AddType application/rss+xml rss
|
||||
AddType application/vnd.geo+json geojson
|
||||
AddType application/xml rdf xml
|
||||
|
||||
|
||||
# JavaScript
|
||||
|
||||
# Normalize to standard type.
|
||||
# https://tools.ietf.org/html/rfc4329#section-7.2
|
||||
|
||||
AddType application/javascript js
|
||||
|
||||
|
||||
# Manifest files
|
||||
|
||||
AddType application/manifest+json webmanifest
|
||||
AddType application/x-web-app-manifest+json webapp
|
||||
AddType text/cache-manifest appcache
|
||||
|
||||
|
||||
# Media files
|
||||
|
||||
AddType audio/mp4 f4a f4b m4a
|
||||
AddType audio/ogg oga ogg opus
|
||||
AddType image/bmp bmp
|
||||
AddType image/svg+xml svg svgz
|
||||
AddType image/webp webp
|
||||
AddType video/mp4 f4v f4p m4v mp4
|
||||
AddType video/ogg ogv
|
||||
AddType video/webm webm
|
||||
AddType video/x-flv flv
|
||||
|
||||
# Serving `.ico` image files with a different media type
|
||||
# prevents Internet Explorer from displaying then as images:
|
||||
# https://github.com/h5bp/html5-boilerplate/commit/37b5fec090d00f38de64b591bcddcb205aadf8ee
|
||||
|
||||
AddType image/x-icon cur ico
|
||||
|
||||
|
||||
# Web fonts
|
||||
|
||||
AddType application/font-woff woff
|
||||
AddType application/font-woff2 woff2
|
||||
AddType application/vnd.ms-fontobject eot
|
||||
|
||||
# Browsers usually ignore the font media types and simply sniff
|
||||
# the bytes to figure out the font type.
|
||||
# https://mimesniff.spec.whatwg.org/#matching-a-font-type-pattern
|
||||
#
|
||||
# However, Blink and WebKit based browsers will show a warning
|
||||
# in the console if the following font types are served with any
|
||||
# other media types.
|
||||
|
||||
AddType application/x-font-ttf ttc ttf
|
||||
AddType font/opentype otf
|
||||
|
||||
|
||||
# Other
|
||||
|
||||
AddType application/octet-stream safariextz
|
||||
AddType application/x-bb-appworld bbaw
|
||||
AddType application/x-chrome-extension crx
|
||||
AddType application/x-opera-extension oex
|
||||
AddType application/x-xpinstall xpi
|
||||
AddType text/vcard vcard vcf
|
||||
AddType text/vnd.rim.location.xloc xloc
|
||||
AddType text/vtt vtt
|
||||
AddType text/x-component htc
|
||||
|
||||
</IfModule>
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# UTF-8 encoding
|
||||
# | Character encodings |
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# Use UTF-8 encoding for anything served text/plain or text/html
|
||||
# Serve all resources labeled as `text/html` or `text/plain`
|
||||
# with the media type `charset` parameter set to `UTF-8`.
|
||||
#
|
||||
# https://httpd.apache.org/docs/current/mod/core.html#adddefaultcharset
|
||||
|
||||
AddDefaultCharset utf-8
|
||||
|
||||
# Force UTF-8 for a number of file formats
|
||||
AddCharset utf-8 .atom .css .js .json .rss .vtt .xml
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
# Serve the following file types with the media type `charset`
|
||||
# parameter set to `UTF-8`.
|
||||
#
|
||||
# https://httpd.apache.org/docs/current/mod/mod_mime.html#addcharset
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# A little more security
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
|
||||
# Block access to "hidden" directories or files whose names begin with a
|
||||
# period. This includes directories used by version control systems such as
|
||||
# Subversion or Git.
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteCond %{SCRIPT_FILENAME} -d [OR]
|
||||
RewriteCond %{SCRIPT_FILENAME} -f
|
||||
RewriteRule "(^|/)\." - [F]
|
||||
</IfModule>
|
||||
|
||||
# Block access to backup and source files. These files may be left by some
|
||||
# text/html editors and pose a great security danger, when anyone can access
|
||||
# them.
|
||||
<FilesMatch "(\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy All
|
||||
</FilesMatch>
|
||||
|
||||
# Increase cookie security
|
||||
<IfModule php5_module>
|
||||
php_value session.cookie_httponly true
|
||||
<IfModule mod_mime.c>
|
||||
AddCharset utf-8 .atom \
|
||||
.bbaw \
|
||||
.css \
|
||||
.geojson \
|
||||
.js \
|
||||
.json \
|
||||
.jsonld \
|
||||
.manifest \
|
||||
.rdf \
|
||||
.rss \
|
||||
.topojson \
|
||||
.vtt \
|
||||
.webapp \
|
||||
.webmanifest \
|
||||
.xloc \
|
||||
.xml
|
||||
</IfModule>
|
||||
|
||||
+301
-30
@@ -1,4 +1,275 @@
|
||||
|
||||
Drupal 7.56, 2017-06-21
|
||||
-----------------------
|
||||
- Fixed security issues (access bypass). See SA-CORE-2017-003.
|
||||
|
||||
Drupal 7.55, 2017-06-07
|
||||
-----------------------
|
||||
- Fixed incompatibility with PHP versions 7.0.19 and 7.1.5 due to duplicate
|
||||
DATE_RFC7231 definition.
|
||||
- Made Drupal core pass all automated tests on PHP 7.1.
|
||||
- Allowed services such as Let's Encrypt to work with Drupal on Apache, by
|
||||
making Drupal's .htaccess file allow access to the .well-known directory
|
||||
defined by RFC 5785.
|
||||
- Made new Drupal sites work correctly on Apache 2.4 when the mod_access_compat
|
||||
Apache module is disabled.
|
||||
- Fixed Drupal's URL-generating functions to always encode '[' and ']' so that
|
||||
the URLs will pass HTML5 validation.
|
||||
- Various additional bug fixes.
|
||||
- Various API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.54, 2017-02-01
|
||||
-----------------------
|
||||
- Modules are now able to define theme engines (API addition:
|
||||
https://www.drupal.org/node/2826480).
|
||||
- Logging of searches can now be disabled (new option in the administrative
|
||||
interface).
|
||||
- Added menu tree render structure to (pre-)process hooks for theme_menu_tree()
|
||||
(API addition: https://www.drupal.org/node/2827134).
|
||||
- Added new function for determining whether an HTTPS request is being served
|
||||
(API addition: https://www.drupal.org/node/2824590).
|
||||
- Fixed incorrect default value for short and medium date formats on the date
|
||||
type configuration page.
|
||||
- File validation error message is now removed after subsequent upload of valid
|
||||
file.
|
||||
- Numerous bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- Additional performance improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.53, 2016-12-07
|
||||
-----------------------
|
||||
- Fixed drag and drop support on newer Chrome/IE 11+ versions after 7.51 update
|
||||
when jQuery is updated to 1.7-1.11.0.
|
||||
|
||||
Drupal 7.52, 2016-11-16
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2016-005.
|
||||
|
||||
Drupal 7.51, 2016-10-05
|
||||
-----------------------
|
||||
- The Update module now also checks for updates to a disabled theme that is
|
||||
used as an admin theme.
|
||||
- Exceptions thrown in dblog_watchdog() are now caught and ignored.
|
||||
- Clarified the warning that appears when modules are missing or have moved.
|
||||
- Log messages are now XSS filtered on display.
|
||||
- Draggable tables now work on touch screen devices.
|
||||
- Added a setting for allowing double underscores in CSS identifiers
|
||||
(https://www.drupal.org/node/2810369).
|
||||
- If a user navigates away from a page while an Ajax request is running they
|
||||
will no longer get an error message saying "An Ajax HTTP request terminated
|
||||
abnormally".
|
||||
- The system_region_list() API function now takes an optional third parameter
|
||||
which allows region name translations to be skipped when they are not needed
|
||||
(API addition: https://www.drupal.org/node/2810365).
|
||||
- Numerous performance improvements.
|
||||
- Numerous bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.50, 2016-07-07
|
||||
-----------------------
|
||||
- Added a new "administer fields" permission for trusted users, which is
|
||||
required in addition to other permissions to use the field UI
|
||||
(https://www.drupal.org/node/2483307).
|
||||
- Added clickjacking protection to Drupal core by setting the X-Frame-Options
|
||||
header to SAMEORIGIN by default (https://www.drupal.org/node/2735873).
|
||||
- Added support for full UTF-8 (emojis, Asian symbols, mathematical symbols) on
|
||||
MySQL and other database drivers when the site and database are configured to
|
||||
allow it (https://www.drupal.org/node/2761183).
|
||||
- Improved performance by avoiding a re-scan of directories when a file is
|
||||
missing; instead, trigger a PHP warning (minor API change:
|
||||
https://www.drupal.org/node/2581445).
|
||||
- Made it possible to use any PHP callable in Ajax form callbacks, form API
|
||||
form-building functions, and form API wrapper callbacks (API addition:
|
||||
https://www.drupal.org/node/2761169).
|
||||
- Fixed that following a password reset link while logged in leaves users unable
|
||||
to change their password (minor user interface change:
|
||||
https://www.drupal.org/node/2759023).
|
||||
- Implemented various fixes for automated test failures on PHP 5.4+ and PHP 7.
|
||||
Drupal core automated tests now pass in these environments.
|
||||
- Improved support for PHP 7 by fixing various problems.
|
||||
- Fixed various bugs with PHP 5.5+ imagerotate(), including when incorrect
|
||||
color indices are passed in.
|
||||
- Fixed a regression introduced in Drupal 7.43 that allowed files uploaded by
|
||||
anonymous users to be lost after form validation errors, and that also caused
|
||||
regressions with certain contributed modules.
|
||||
- Fixed a regression introduced in Drupal 7.36 which caused the default value
|
||||
of hidden textarea fields to be ignored.
|
||||
- Fixed robots.txt to allow search engines to access CSS, JavaScript and image
|
||||
files.
|
||||
- Changed wording on the Update Manager settings page to clarify that the
|
||||
option to check for disabled module updates also applies to uninstalled
|
||||
modules (administrative-facing translatable string change).
|
||||
- Changed the help text when editing menu links and configuring URL redirect
|
||||
actions so that it does not reference "Drupal" or the drupal.org website
|
||||
(administrative-facing translatable string change).
|
||||
- Fixed the locale safety check that is used to ensure that translations are
|
||||
safe to allow for tokens in the href/src attributes of translated strings.
|
||||
- Fixed that URL generation only works on port 80 when using domain based
|
||||
language negotation.
|
||||
- Made method="get" forms work inside the administrative overlay. The fix adds
|
||||
a new hidden field to these forms when they appear inside the overlay (minor
|
||||
data structure change).
|
||||
- Increased maxlength of menu link title input fields in the node form and
|
||||
menu link form from 128 to 255 characters.
|
||||
- Removed meaningless post-check=0 and pre-check=0 cache control headers from
|
||||
Drupal HTTP responses.
|
||||
- Added a .editorconfig file to auto-configure editors that support it.
|
||||
- Added --directory option to run-tests.sh for easier test discovery of all
|
||||
tests within a project.
|
||||
- Made run-tests.sh exit with a failure code when there are test fails or
|
||||
problems running the script.
|
||||
- Fixed that cookies from previous tests are still present when a new test
|
||||
starts in DrupalWebTestCase.
|
||||
- Improved performance of queries on the {authmap} database table.
|
||||
- Fixed handling of missing files and functions inside the registry.
|
||||
- Fixed Ajax handling for tableselect form elements that use checkboxes.
|
||||
- Fixed a bug which caused ip_address() to return nothing when the client IP
|
||||
address and proxy IP address are the same.
|
||||
- Added a new option to format_xml_elements() to allow for already encoded
|
||||
values.
|
||||
- Changed the {history} table's node ID field to be an unsigned integer, to
|
||||
match the same field in the {node} table and to prevent errors with very
|
||||
large node IDs.
|
||||
- Added an explicit page callback to the "admin/people/create" menu item in the
|
||||
User module (minor data structure change). Previously this automatically
|
||||
inherited the page callback from the parent "admin/people" menu item, which
|
||||
broke contributed modules that override the "admin/people" page.
|
||||
- Numerous small bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.44, 2016-06-15
|
||||
-----------------------
|
||||
- Fixed security issues (privilege escalation). See SA-CORE-2016-002.
|
||||
|
||||
Drupal 7.43, 2016-02-24
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2016-001.
|
||||
|
||||
Drupal 7.42, 2016-02-03
|
||||
-----------------------
|
||||
- Stopped invoking hook_flush_caches() on every cron run, since some modules
|
||||
use that hook for expensive operations that are only needed on cache clears.
|
||||
- Changed the default .htaccess and web.config to block Composer-related files.
|
||||
- Added static caching to module_load_include() to improve performance.
|
||||
- Fixed double-encoding bugs in select field widgets provided by the Options
|
||||
module. The fix deprecates the 'strip_tags' property on option widgets and
|
||||
replaces it with a new 'strip_tags_and_unescape' property (minor data
|
||||
structure change).
|
||||
- Improved MySQL 5.7 support by changing the MySQL database driver to stop
|
||||
using the ANSI SQL mode alias, which has different meanings for different
|
||||
MySQL versions.
|
||||
- Fixed a regression introduced in Drupal 7.39 which prevented autocomplete
|
||||
functionality from working on servers that are not configured to
|
||||
automatically recognize index.php.
|
||||
- Updated the Archive_Tar PEAR package to the latest 1.4.0 release, to fix bugs
|
||||
with tar file handling on various operating systems.
|
||||
- Fixed fatal errors on node preview when a field is displayed in the node
|
||||
teaser but hidden in the full node view. The fix removes a
|
||||
field_attach_prepare_view() call from the node_preview() function since it is
|
||||
redundant with one in the node preview theme layer.
|
||||
- Improved the description of the "Trimmed" format option on text fields
|
||||
(translatable string change, and minor UI and data structure change).
|
||||
- Numerous small bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.41, 2015-10-21
|
||||
-----------------------
|
||||
- Fixed security issues (open redirect). See SA-CORE-2015-004.
|
||||
|
||||
Drupal 7.40, 2015-10-14
|
||||
-----------------------
|
||||
- Made Drupal's code for parsing .info files run much faster and use much less
|
||||
memory.
|
||||
- Prevented drupal_http_request() from returning an error when it receives a
|
||||
201 through 206 HTTP status code.
|
||||
- Added support for autoloading traits via the registry on sites running PHP
|
||||
5.4 or higher.
|
||||
- Allowed the user-picture.tpl.php theme template to have HTML classes besides
|
||||
the default "user-picture" class printed in it (markup change).
|
||||
- Fixed the URL text filter to convert e-mail addresses with plus signs into
|
||||
mailto: links.
|
||||
- Added alternate text to file icons displayed by the File module, to improve
|
||||
accessibility (string change, and minor API addition to theme_file_icon()).
|
||||
- Changed one-time login link failure messages to be displayed as errors or
|
||||
warnings as appropriate, rather than as regular status messages (minor UI
|
||||
change and data structure change).
|
||||
- Changed the default settings.php configuration to exclude private files from
|
||||
the "404_fast_paths" behavior.
|
||||
- Changed the page that displays filter tips for a particular text format, for
|
||||
example filter/tips/full_html, to return "page not found" or "access denied"
|
||||
if the format does not exist or the user does not have access to it. This
|
||||
change adds a new menu item to the Filter module's hook_menu() entry (minor
|
||||
data structure change).
|
||||
- Added a new hook, hook_block_cid_parts_alter(), to allow modules to alter the
|
||||
cache keys used for caching a particular block.
|
||||
- Made drupal_set_message() display and return messages when "0" is passed in
|
||||
as the message to set.
|
||||
- Fixed non-functional "Files displayed by default" setting on file fields.
|
||||
- The "worker callback" provided in hook_cron_queue_info() and the "finished"
|
||||
callback specified during batch processing can now be any PHP callable
|
||||
instead of just functions.
|
||||
- Prevented drupal_set_time_limit() from decreasing the time limit in the case
|
||||
where the PHP maximum execution time is already unlimited.
|
||||
- Changed the default thousand marker for numeric fields from a space ("1 000")
|
||||
to nothing ("1000") (minor UI change: https://www.drupal.org/node/1388376).
|
||||
- Prevented malformed theme .info files (without a "name" key) from causing
|
||||
exceptions during menu rebuilds. If an .info file without a "name" key is
|
||||
found in a module or theme directory, Drupal will now use the module or
|
||||
theme's machine name as the display name instead.
|
||||
- Made the format column in the {date_format_locale} database table
|
||||
case-sensitive, to match the equivalent column in the {date_formats} table.
|
||||
- Fixed a bug in the Statistics module that caused JavaScript files attached to
|
||||
a node while it is being viewed to be omitted from the page.
|
||||
- Added an optional 'project:' prefix that can be added to dependencies in a
|
||||
module's .info file to indicate which project the dependency resides in (API
|
||||
addition: https://www.drupal.org/node/2299747).
|
||||
- Fixed various bugs that occurred after hooks were invoked early in the Drupal
|
||||
bootstrap and that caused module_implements() and drupal_alter() to cache an
|
||||
incomplete set of hook implementations for later use.
|
||||
- Set the X-Content-Type-Options header to "nosniff" when possible, to prevent
|
||||
certain web browsers from picking an unsafe MIME type.
|
||||
- Prevented the database API from executing multiple queries at once on MySQL,
|
||||
if the site's PHP version is new enough to do so. This is a secondary defense
|
||||
against SQL injection (API change: https://www.drupal.org/node/2463973).
|
||||
- Fixed a bug in the Drupal 6 to Drupal 7 upgrade path which caused the upgrade
|
||||
to fail when there were multiple file records pointing to the same file.
|
||||
- Numerous small bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.39, 2015-08-19
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2015-003.
|
||||
|
||||
Drupal 7.38, 2015-06-17
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2015-002.
|
||||
|
||||
Drupal 7.37, 2015-05-07
|
||||
-----------------------
|
||||
- Fixed a regression in Drupal 7.36 which caused certain kinds of content types
|
||||
to become disabled if they were defined by a no-longer-enabled module.
|
||||
- Removed a confusing description regarding automatic time zone detection from
|
||||
the user account form (minor UI and data structure change).
|
||||
- Allowed custom HTML tags with a dash in the name to pass through filter_xss()
|
||||
when specified in the list of allowed tags.
|
||||
- Allowed hook_field_schema() implementations to specify indexes for fields
|
||||
based on a fixed-length column prefix (rather than the entire column), as was
|
||||
already allowed in hook_schema() implementations.
|
||||
- Fixed PDO exceptions on PostgreSQL when accessing invalid entity URLs.
|
||||
- Added a sites/all/libraries folder to the codebase, with instructions for
|
||||
using it.
|
||||
- Added a description to the "Administer text formats and filters" permission
|
||||
on the Permissions page (string change).
|
||||
- Numerous small bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.36, 2015-04-01
|
||||
-----------------------
|
||||
- Added a 'file_public_schema' variable which allows modules that define
|
||||
@@ -58,11 +329,11 @@ Drupal 7.36, 2015-04-01
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.35, 2015-03-18
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2015-001.
|
||||
|
||||
Drupal 7.34, 2014-11-19
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2014-006.
|
||||
|
||||
Drupal 7.33, 2014-11-07
|
||||
@@ -131,11 +402,11 @@ Drupal 7.33, 2014-11-07
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.32, 2014-10-15
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (SQL injection). See SA-CORE-2014-005.
|
||||
|
||||
Drupal 7.31, 2014-08-06
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (denial of service). See SA-CORE-2014-004.
|
||||
|
||||
Drupal 7.30, 2014-07-24
|
||||
@@ -150,7 +421,7 @@ Drupal 7.30, 2014-07-24
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.29, 2014-07-16
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2014-003.
|
||||
|
||||
Drupal 7.28, 2014-05-08
|
||||
@@ -196,11 +467,11 @@ Drupal 7.28, 2014-05-08
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.27, 2014-04-16
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (information disclosure). See SA-CORE-2014-002.
|
||||
|
||||
Drupal 7.26, 2014-01-15
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities). See SA-CORE-2014-001.
|
||||
|
||||
Drupal 7.25, 2014-01-02
|
||||
@@ -266,7 +537,7 @@ Drupal 7.25, 2014-01-02
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.24, 2013-11-20
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (multiple vulnerabilities), see SA-CORE-2013-003.
|
||||
|
||||
Drupal 7.23, 2013-08-07
|
||||
@@ -520,8 +791,8 @@ Drupal 7.15, 2012-08-01
|
||||
- Numerous API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.14 2012-05-02
|
||||
----------------------
|
||||
Drupal 7.14, 2012-05-02
|
||||
-----------------------
|
||||
- Fixed "integrity constraint" fatal errors when rebuilding registry.
|
||||
- Fixed custom logo and favicon functionality referencing incorrect paths.
|
||||
- Fixed DB Case Sensitivity: Allow BINARY attribute in MySQL.
|
||||
@@ -569,12 +840,12 @@ Drupal 7.14 2012-05-02
|
||||
- system_update_7061() converts filepaths too aggressively.
|
||||
- Trigger upgrade path: Node triggers removed when upgrading to 7-x from 6.25.
|
||||
|
||||
Drupal 7.13 2012-05-02
|
||||
----------------------
|
||||
Drupal 7.13, 2012-05-02
|
||||
-----------------------
|
||||
- Fixed security issues (Multiple vulnerabilities), see SA-CORE-2012-002.
|
||||
|
||||
Drupal 7.12, 2012-02-01
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed bug preventing custom menus from receiving an active trail.
|
||||
- Fixed hook_field_delete() no longer invoked during field_purge_data().
|
||||
- Fixed bug causing entity info cache to not be cleared with the rest of caches.
|
||||
@@ -608,11 +879,11 @@ Drupal 7.12, 2012-02-01
|
||||
cache.
|
||||
|
||||
Drupal 7.11, 2012-02-01
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (Multiple vulnerabilities), see SA-CORE-2012-001.
|
||||
|
||||
Drupal 7.10, 2011-12-05
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed Content-Language HTTP header to not cause issues with Drush 5.x.
|
||||
- Reduce memory usage of theme registry (performance).
|
||||
- Fixed PECL upload progress bar for FileField
|
||||
@@ -965,7 +1236,7 @@ Drupal 7.0, 2011-01-05
|
||||
requests.
|
||||
|
||||
Drupal 6.23-dev, xxxx-xx-xx (development release)
|
||||
-----------------------
|
||||
---------------------------
|
||||
|
||||
Drupal 6.22, 2011-05-25
|
||||
-----------------------
|
||||
@@ -975,25 +1246,25 @@ Drupal 6.22, 2011-05-25
|
||||
- Fixed a variety of other bugs.
|
||||
|
||||
Drupal 6.21, 2011-05-25
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (Cross site scripting), see SA-CORE-2011-001.
|
||||
|
||||
Drupal 6.20, 2010-12-15
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed a variety of small bugs, improved code documentation.
|
||||
|
||||
Drupal 6.19, 2010-08-11
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed a variety of small bugs, improved code documentation.
|
||||
|
||||
Drupal 6.18, 2010-08-11
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (OpenID authentication bypass, File download access
|
||||
bypass, Comment unpublishing bypass, Actions cross site scripting),
|
||||
see SA-CORE-2010-002.
|
||||
|
||||
Drupal 6.17, 2010-06-02
|
||||
----------------------
|
||||
-----------------------
|
||||
- Improved PostgreSQL compatibility
|
||||
- Better PHP 5.3 and PHP 4 compatibility
|
||||
- Better browser compatibility of CSS and JS aggregation
|
||||
@@ -1002,7 +1273,7 @@ Drupal 6.17, 2010-06-02
|
||||
- Fixed a variety of other bugs.
|
||||
|
||||
Drupal 6.16, 2010-03-03
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (Installation cross site scripting, Open redirection,
|
||||
Locale module cross site scripting, Blocked user session regeneration),
|
||||
see SA-CORE-2010-001.
|
||||
@@ -1014,12 +1285,12 @@ Drupal 6.16, 2010-03-03
|
||||
- Fixed a variety of other bugs.
|
||||
|
||||
Drupal 6.15, 2009-12-16
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (Cross site scripting), see SA-CORE-2009-009.
|
||||
- Fixed a variety of other bugs.
|
||||
|
||||
Drupal 6.14, 2009-09-16
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (OpenID association cross site request forgeries,
|
||||
OpenID impersonation and File upload), see SA-CORE-2009-008.
|
||||
- Changed the system modules page to not run all cache rebuilds; use the
|
||||
@@ -1028,18 +1299,18 @@ Drupal 6.14, 2009-09-16
|
||||
- Fixed a variety of small bugs.
|
||||
|
||||
Drupal 6.13, 2009-07-01
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (Cross site scripting, Input format access bypass and
|
||||
Password leakage in URL), see SA-CORE-2009-007.
|
||||
- Fixed a variety of small bugs.
|
||||
|
||||
Drupal 6.12, 2009-05-13
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (Cross site scripting), see SA-CORE-2009-006.
|
||||
- Fixed a variety of small bugs.
|
||||
|
||||
Drupal 6.11, 2009-04-29
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed security issues (Cross site scripting and limited information
|
||||
disclosure), see SA-CORE-2009-005
|
||||
- Fixed performance issues with the menu router cache, the update
|
||||
@@ -1047,7 +1318,7 @@ Drupal 6.11, 2009-04-29
|
||||
- Fixed a variety of small bugs.
|
||||
|
||||
Drupal 6.10, 2009-02-25
|
||||
----------------------
|
||||
-----------------------
|
||||
- Fixed a security issue, (Local file inclusion on Windows),
|
||||
see SA-CORE-2009-003
|
||||
- Fixed node_feed() so custom fields can show up in RSS feeds.
|
||||
@@ -1443,7 +1714,7 @@ Drupal 4.7.9, 2007-12-05
|
||||
- fixed a security issue (SQL injection), see SA-2007-031
|
||||
|
||||
Drupal 4.7.8, 2007-10-17
|
||||
----------------------
|
||||
------------------------
|
||||
- fixed a security issue (HTTP response splitting), see SA-2007-024
|
||||
- fixed a security issue (Cross site scripting via uploads), see SA-2007-026
|
||||
- fixed a security issue (API handling of unpublished comment), see SA-2007-030
|
||||
@@ -1556,7 +1827,7 @@ Drupal 4.6.11, 2007-01-05
|
||||
- Fixed security issue (DoS), see SA-2007-002
|
||||
|
||||
Drupal 4.6.10, 2006-10-18
|
||||
------------------------
|
||||
-------------------------
|
||||
- Fixed security issue (XSS), see SA-2006-024
|
||||
- Fixed security issue (CSRF), see SA-2006-025
|
||||
- Fixed security issue (Form action attribute injection), see SA-2006-026
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
CREATE THE MySQL DATABASE
|
||||
--------------------------
|
||||
|
||||
This step is only necessary if you don't already have a database set up (e.g.,
|
||||
by your host). In the following examples, 'username' is an example MySQL user
|
||||
which has the CREATE and GRANT privileges. Use the appropriate user name for
|
||||
your system.
|
||||
|
||||
First, you must create a new database for your Drupal site (here, 'databasename'
|
||||
is the name of the new database):
|
||||
|
||||
mysqladmin -u username -p create databasename
|
||||
|
||||
MySQL will prompt for the 'username' database password and then create the
|
||||
initial database files. Next you must log in and set the access database rights:
|
||||
|
||||
mysql -u username -p
|
||||
|
||||
Again, you will be asked for the 'username' database password. At the MySQL
|
||||
prompt, enter the following command:
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER,
|
||||
CREATE TEMPORARY TABLES ON databasename.*
|
||||
TO 'username'@'localhost' IDENTIFIED BY 'password';
|
||||
|
||||
where:
|
||||
|
||||
'databasename' is the name of your database
|
||||
'username' is the username of your MySQL account
|
||||
'localhost' is the web server host where Drupal is installed
|
||||
'password' is the password required for that username
|
||||
|
||||
Note: Unless the database user/host combination for your Drupal installation
|
||||
has all of the privileges listed above (except possibly CREATE TEMPORARY TABLES,
|
||||
which is currently only used by Drupal core automated tests and some
|
||||
contributed modules), you will not be able to install or run Drupal.
|
||||
|
||||
If successful, MySQL will reply with:
|
||||
|
||||
Query OK, 0 rows affected
|
||||
|
||||
If the InnoDB storage engine is available, it will be used for all database
|
||||
tables. InnoDB provides features over MyISAM such as transaction support,
|
||||
row-level locks, and consistent non-locking reads.
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
CREATE THE PostgreSQL DATABASE
|
||||
------------------------------
|
||||
|
||||
Note that the database must be created with UTF-8 (Unicode) encoding.
|
||||
|
||||
1. CREATE DATABASE USER
|
||||
|
||||
This step is only necessary if you don't already have a user set up (e.g., by
|
||||
your host), or want to create a new user for use with Drupal only. The
|
||||
following command creates a new user named 'username' and asks for a password
|
||||
for that user:
|
||||
|
||||
createuser --pwprompt --encrypted --no-createrole --no-createdb username
|
||||
|
||||
If there are no errors, then the command was successful.
|
||||
|
||||
2. CREATE DRUPAL DATABASE
|
||||
|
||||
This step is only necessary if you don't already have a database set up
|
||||
(e.g., by your host) or want to create a new database for use with Drupal
|
||||
only. The following command creates a new database named 'databasename',
|
||||
which is owned by the previously created 'username':
|
||||
|
||||
createdb --encoding=UTF8 --owner=username databasename
|
||||
|
||||
If there are no errors, then the command was successful.
|
||||
|
||||
3. CREATE SCHEMA OR SCHEMAS (Optional advanced step)
|
||||
|
||||
Drupal will run across different schemas within your database if you so wish.
|
||||
By default, Drupal runs inside the 'public' schema but you can use $db_prefix
|
||||
inside settings.php to define a schema for Drupal to run inside of, or
|
||||
specify tables that are shared inside of a separate schema. Drupal will not
|
||||
create schemas for you. In fact, the user that Drupal runs as should not be
|
||||
allowed to do this. You'll need to execute the SQL below as a superuser,
|
||||
replace 'username' with the username that Drupal uses to connect to
|
||||
PostgreSQL, and replace 'schema_name' with a schema name you wish to use,
|
||||
such as 'shared':
|
||||
|
||||
CREATE SCHEMA schema_name AUTHORIZATION username;
|
||||
|
||||
Do this for as many schemas as you need. See default.settings.php for
|
||||
instructions on how to set which tables use which schemas.
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
SQLITE REQUIREMENTS
|
||||
-------------------
|
||||
|
||||
To use SQLite with your Drupal installation, the following requirements must be
|
||||
met: Server has PHP 5.2 or later with PDO, and the PDO SQLite driver must be
|
||||
enabled.
|
||||
|
||||
SQLITE DATABASE CREATION
|
||||
------------------------
|
||||
|
||||
The Drupal installer will create the SQLite database for you. The only
|
||||
requirement is that the installer must have write permissions to the directory
|
||||
where the database file resides. This directory (not just the database file) also
|
||||
has to remain writeable by the web server going forward for SQLite to continue to
|
||||
be able to operate.
|
||||
|
||||
On the "Database configuration" form in the "Database file" field, you must
|
||||
supply the exact path to where you wish your database file to reside. It is
|
||||
strongly suggested that you choose a path that is outside of the webroot, yet
|
||||
ensure that the directory is writeable by the web server.
|
||||
|
||||
If you must place your database file in your webroot, you could try using the
|
||||
following in your "Database file" field:
|
||||
|
||||
sites/default/files/.ht.sqlite
|
||||
|
||||
Note: The .ht in the name will tell Apache to prevent the database from being
|
||||
downloaded. Please check that the file is, indeed, protected by your webserver.
|
||||
If not, please consult the documentation of your webserver on how to protect a
|
||||
file from downloading.
|
||||
+400
@@ -0,0 +1,400 @@
|
||||
|
||||
CONTENTS OF THIS FILE
|
||||
---------------------
|
||||
|
||||
* Requirements and notes
|
||||
* Optional server requirements
|
||||
* Installation
|
||||
* Building and customizing your site
|
||||
* Multisite configuration
|
||||
* More information
|
||||
|
||||
REQUIREMENTS AND NOTES
|
||||
----------------------
|
||||
|
||||
Drupal requires:
|
||||
|
||||
- A web server. Apache (version 2.0 or greater) is recommended.
|
||||
- PHP 5.2.4 (or greater) (http://www.php.net/).
|
||||
- One of the following databases:
|
||||
- MySQL 5.0.15 (or greater) (http://www.mysql.com/).
|
||||
- MariaDB 5.1.44 (or greater) (http://mariadb.org/). MariaDB is a fully
|
||||
compatible drop-in replacement for MySQL.
|
||||
- Percona Server 5.1.70 (or greater) (http://www.percona.com/). Percona
|
||||
Server is a backwards-compatible replacement for MySQL.
|
||||
- PostgreSQL 8.3 (or greater) (http://www.postgresql.org/).
|
||||
- SQLite 3.3.7 (or greater) (http://www.sqlite.org/).
|
||||
|
||||
For more detailed information about Drupal requirements, including a list of
|
||||
PHP extensions and configurations that are required, see "System requirements"
|
||||
(http://drupal.org/requirements) in the Drupal.org online documentation.
|
||||
|
||||
For detailed information on how to configure a test server environment using a
|
||||
variety of operating systems and web servers, see "Local server setup"
|
||||
(http://drupal.org/node/157602) in the Drupal.org online documentation.
|
||||
|
||||
Note that all directories mentioned in this document are always relative to the
|
||||
directory of your Drupal installation, and commands are meant to be run from
|
||||
this directory (except for the initial commands that create that directory).
|
||||
|
||||
OPTIONAL SERVER REQUIREMENTS
|
||||
----------------------------
|
||||
|
||||
- If you want to use Drupal's "Clean URLs" feature on an Apache web server, you
|
||||
will need the mod_rewrite module and the ability to use local .htaccess
|
||||
files. For Clean URLs support on IIS, see "Clean URLs with IIS"
|
||||
(http://drupal.org/node/3854) in the Drupal.org online documentation.
|
||||
|
||||
- If you plan to use XML-based services such as RSS aggregation, you will need
|
||||
PHP's XML extension. This extension is enabled by default on most PHP
|
||||
installations.
|
||||
|
||||
- To serve gzip compressed CSS and JS files on an Apache web server, you will
|
||||
need the mod_headers module and the ability to use local .htaccess files.
|
||||
|
||||
- Some Drupal functionality (e.g., checking whether Drupal and contributed
|
||||
modules need updates, RSS aggregation, etc.) require that the web server be
|
||||
able to go out to the web and download information. If you want to use this
|
||||
functionality, you need to verify that your hosting provider or server
|
||||
configuration allows the web server to initiate outbound connections. Most web
|
||||
hosting setups allow this.
|
||||
|
||||
INSTALLATION
|
||||
------------
|
||||
|
||||
1. Download and extract Drupal.
|
||||
|
||||
You can obtain the latest Drupal release from http://drupal.org -- the files
|
||||
are available in .tar.gz and .zip formats and can be extracted using most
|
||||
compression tools.
|
||||
|
||||
To download and extract the files, on a typical Unix/Linux command line, use
|
||||
the following commands (assuming you want version x.y of Drupal in .tar.gz
|
||||
format):
|
||||
|
||||
wget http://drupal.org/files/projects/drupal-x.y.tar.gz
|
||||
tar -zxvf drupal-x.y.tar.gz
|
||||
|
||||
This will create a new directory drupal-x.y/ containing all Drupal files and
|
||||
directories. Then, to move the contents of that directory into a directory
|
||||
within your web server's document root or your public HTML directory,
|
||||
continue with this command:
|
||||
|
||||
mv drupal-x.y/* drupal-x.y/.htaccess /path/to/your/installation
|
||||
|
||||
2. Optionally, download a translation.
|
||||
|
||||
By default, Drupal is installed in English, and further languages may be
|
||||
installed later. If you prefer to install Drupal in another language
|
||||
initially:
|
||||
|
||||
- Download a translation file for the correct Drupal version and language
|
||||
from the translation server: http://localize.drupal.org/translate/downloads
|
||||
|
||||
- Place the file into your installation profile's translations directory.
|
||||
For instance, if you are using the Standard installation profile,
|
||||
move the .po file into the directory:
|
||||
|
||||
profiles/standard/translations/
|
||||
|
||||
For detailed instructions, visit http://drupal.org/localize
|
||||
|
||||
3. Create the Drupal database.
|
||||
|
||||
Because Drupal stores all site information in a database, you must create
|
||||
this database in order to install Drupal, and grant Drupal certain database
|
||||
privileges (such as the ability to create tables). For details, consult
|
||||
INSTALL.mysql.txt, INSTALL.pgsql.txt, or INSTALL.sqlite.txt. You may also
|
||||
need to consult your web hosting provider for instructions specific to your
|
||||
web host.
|
||||
|
||||
Take note of the username, password, database name, and hostname as you
|
||||
create the database. You will enter this information during the install.
|
||||
|
||||
4. Run the install script.
|
||||
|
||||
To run the install script, point your browser to the base URL of your
|
||||
website (e.g., http://www.example.com).
|
||||
|
||||
You will be guided through several screens to set up the database, add the
|
||||
site maintenance account (the first user, also known as user/1), and provide
|
||||
basic web site settings.
|
||||
|
||||
During installation, several files and directories need to be created, which
|
||||
the install script will try to do automatically. However, on some hosting
|
||||
environments, manual steps are required, and the install script will tell
|
||||
you that it cannot proceed until you fix certain issues. This is normal and
|
||||
does not indicate a problem with your server.
|
||||
|
||||
The most common steps you may need to perform are:
|
||||
|
||||
a. Missing files directory.
|
||||
|
||||
The install script will attempt to create a file storage directory in
|
||||
the default location at sites/default/files (the location of the files
|
||||
directory may be changed after Drupal is installed).
|
||||
|
||||
If auto-creation fails, you can make it work by changing permissions on
|
||||
the sites/default directory so that the web server can create the files
|
||||
directory within it for you. (If you are creating a multisite
|
||||
installation, substitute the correct sites directory for sites/default;
|
||||
see the Multisite Configuration section of this file, below.)
|
||||
|
||||
For example, on a Unix/Linux command line, you can grant everyone
|
||||
(including the web server) permission to write to the sites/default
|
||||
directory with this command:
|
||||
|
||||
chmod a+w sites/default
|
||||
|
||||
Be sure to set the permissions back after the installation is finished!
|
||||
Sample command:
|
||||
|
||||
chmod go-w sites/default
|
||||
|
||||
Alternatively, instead of allowing the web server to create the files
|
||||
directory for you as described above, you can create it yourself. Sample
|
||||
commands from a Unix/Linux command line:
|
||||
|
||||
mkdir sites/default/files
|
||||
chmod a+w sites/default/files
|
||||
|
||||
b. Missing settings file.
|
||||
|
||||
Drupal will try to automatically create a settings.php configuration file,
|
||||
which is normally in the directory sites/default (to avoid problems when
|
||||
upgrading, Drupal is not packaged with this file). If auto-creation fails,
|
||||
you will need to create this file yourself, using the file
|
||||
sites/default/default.settings.php as a template.
|
||||
|
||||
For example, on a Unix/Linux command line, you can make a copy of the
|
||||
default.settings.php file with the command:
|
||||
|
||||
cp sites/default/default.settings.php sites/default/settings.php
|
||||
|
||||
Next, grant write privileges to the file to everyone (including the web
|
||||
server) with the command:
|
||||
|
||||
chmod a+w sites/default/settings.php
|
||||
|
||||
Be sure to set the permissions back after the installation is finished!
|
||||
Sample command:
|
||||
|
||||
chmod go-w sites/default/settings.php
|
||||
|
||||
c. Write permissions after install.
|
||||
|
||||
The install script will attempt to write-protect the settings.php file and
|
||||
the sites/default directory after saving your configuration. If this
|
||||
fails, you will be notified, and you can do it manually. Sample commands
|
||||
from a Unix/Linux command line:
|
||||
|
||||
chmod go-w sites/default/settings.php
|
||||
chmod go-w sites/default
|
||||
|
||||
5. Verify that the site is working.
|
||||
|
||||
When the install script finishes, you will be logged in with the site
|
||||
maintenance account on a "Welcome" page. If the default Drupal theme is not
|
||||
displaying properly and links on the page result in "Page Not Found" errors,
|
||||
you may be experiencing problems with clean URLs. Visit
|
||||
http://drupal.org/getting-started/clean-urls to troubleshoot.
|
||||
|
||||
6. Change file system storage settings (optional).
|
||||
|
||||
The files directory created in step 4 is the default file system path used to
|
||||
store all uploaded files, as well as some temporary files created by
|
||||
Drupal. After installation, you can modify the file system path to store
|
||||
uploaded files in a different location.
|
||||
|
||||
It is not necessary to modify this path, but you may wish to change it if:
|
||||
|
||||
- Your site runs multiple Drupal installations from a single codebase (modify
|
||||
the file system path of each installation to a different directory so that
|
||||
uploads do not overlap between installations).
|
||||
|
||||
- Your site runs on a number of web servers behind a load balancer or reverse
|
||||
proxy (modify the file system path on each server to point to a shared file
|
||||
repository).
|
||||
|
||||
- You want to restrict access to uploaded files.
|
||||
|
||||
To modify the file system path:
|
||||
|
||||
a. Ensure that the new location for the path exists and is writable by the
|
||||
web server. For example, to create a new directory named uploads and grant
|
||||
write permissions, use the following commands on a Unix/Linux command
|
||||
line:
|
||||
|
||||
mkdir uploads
|
||||
chmod a+w uploads
|
||||
|
||||
b. Navigate to Administration > Configuration > Media > File system, and
|
||||
enter the desired path. Note that if you want to use private file storage,
|
||||
you need to first enter the path for private files and save the
|
||||
configuration, and then change the "Default download method" setting and
|
||||
save again.
|
||||
|
||||
Changing the file system path after files have been uploaded may cause
|
||||
unexpected problems on an existing site. If you modify the file system path
|
||||
on an existing site, remember to copy all files from the original location
|
||||
to the new location.
|
||||
|
||||
7. Revoke documentation file permissions (optional).
|
||||
|
||||
Some administrators suggest making the documentation files, especially
|
||||
CHANGELOG.txt, non-readable so that the exact version of Drupal you are
|
||||
running is slightly more difficult to determine. If you wish to implement
|
||||
this optional security measure, from a Unix/Linux command line you can use
|
||||
the following command:
|
||||
|
||||
chmod a-r CHANGELOG.txt
|
||||
|
||||
Note that the example only affects CHANGELOG.txt. To completely hide all
|
||||
documentation files from public view, repeat this command for each of the
|
||||
Drupal documentation files in the installation directory, substituting the
|
||||
name of each file for CHANGELOG.txt in the example.
|
||||
|
||||
For more information on setting file permissions, see "Modifying Linux,
|
||||
Unix, and Mac file permissions" (http://drupal.org/node/202483) or
|
||||
"Modifying Windows file permissions" (http://drupal.org/node/202491) in the
|
||||
Drupal.org online documentation.
|
||||
|
||||
8. Set up independent "cron" maintenance jobs.
|
||||
|
||||
Many Drupal modules have tasks that must be run periodically, including the
|
||||
Search module (building and updating the index used for keyword searching),
|
||||
the Aggregator module (retrieving feeds from other sites), and the System
|
||||
module (performing routine maintenance and pruning of database tables). These
|
||||
tasks are known as "cron maintenance tasks", named after the Unix/Linux
|
||||
"cron" utility.
|
||||
|
||||
When you install Drupal, its built-in cron feature is enabled, which
|
||||
automatically runs the cron tasks periodically, triggered by people visiting
|
||||
pages of your site. You can configure the built-in cron feature by navigating
|
||||
to Administration > Configuration > System > Cron.
|
||||
|
||||
It is also possible to run the cron tasks independent of site visits; this is
|
||||
recommended for most sites. To do this, you will need to set up an automated
|
||||
process to visit the page cron.php on your site, which executes the cron
|
||||
tasks.
|
||||
|
||||
The URL of the cron.php page requires a "cron key" to protect against
|
||||
unauthorized access. Your site's cron key is automatically generated during
|
||||
installation and is specific to your site. The full URL of the page, with the
|
||||
cron key, is available in the "Cron maintenance tasks" section of the Status
|
||||
report page at Administration > Reports > Status report.
|
||||
|
||||
As an example for how to set up this automated process, you can use the
|
||||
crontab utility on Unix/Linux systems. The following crontab line uses the
|
||||
wget command to visit the cron.php page, and runs each hour, on the hour:
|
||||
|
||||
0 * * * * wget -O - -q -t 1 http://example.com/cron.php?cron_key=YOURKEY
|
||||
|
||||
Replace the text "http://example.com/cron.php?cron_key=YOURKEY" in the
|
||||
example with the full URL displayed under "Cron maintenance tasks" on the
|
||||
"Status report" page.
|
||||
|
||||
More information about cron maintenance tasks is available at
|
||||
http://drupal.org/cron, and sample cron shell scripts can be found in the
|
||||
scripts/ directory. (Note that these scripts must be customized like the
|
||||
above example, to add your site-specific cron key and domain name.)
|
||||
|
||||
BUILDING AND CUSTOMIZING YOUR SITE
|
||||
----------------------------------
|
||||
|
||||
A new installation of Drupal defaults to a very basic configuration. To extend
|
||||
your site, you use "modules" and "themes". A module is a plugin that adds
|
||||
functionality to Drupal, while a theme changes the look of your site. The core
|
||||
of Drupal provides several optional modules and themes, and you can download
|
||||
more at http://drupal.org/project/modules and http://drupal.org/project/themes
|
||||
|
||||
Do not mix downloaded or custom modules and themes with Drupal's core modules
|
||||
and themes. Drupal's modules and themes are located in the top-level modules and
|
||||
themes directories, while the modules and themes you add to Drupal are normally
|
||||
placed in the sites/all/modules and sites/all/themes directories. If you run a
|
||||
multisite installation, you can also place modules and themes in the
|
||||
site-specific directories -- see the Multisite Configuration section, below.
|
||||
|
||||
Never edit Drupal's core modules and themes; instead, use the hooks available in
|
||||
the Drupal API. To modify the behavior of Drupal, develop a module as described
|
||||
at http://drupal.org/developing/modules. To modify the look of Drupal, create a
|
||||
subtheme as described at http://drupal.org/node/225125, or a completely new
|
||||
theme as described at http://drupal.org/documentation/theme
|
||||
|
||||
MULTISITE CONFIGURATION
|
||||
-----------------------
|
||||
|
||||
A single Drupal installation can host several Drupal-powered sites, each with
|
||||
its own individual configuration.
|
||||
|
||||
Additional site configurations are created in subdirectories within the 'sites'
|
||||
directory. Each subdirectory must have a 'settings.php' file, which specifies
|
||||
the configuration settings. The easiest way to create additional sites is to
|
||||
copy the 'default' directory and modify the 'settings.php' file as appropriate.
|
||||
The new directory name is constructed from the site's URL. The configuration for
|
||||
www.example.com could be in 'sites/example.com/settings.php' (note that 'www.'
|
||||
should be omitted if users can access your site at http://example.com/).
|
||||
|
||||
Sites do not have to have a different domain. You can also use subdomains and
|
||||
subdirectories for Drupal sites. For example, example.com, sub.example.com, and
|
||||
sub.example.com/site3 can all be defined as independent Drupal sites. The setup
|
||||
for a configuration such as this would look like the following:
|
||||
|
||||
sites/default/settings.php
|
||||
sites/example.com/settings.php
|
||||
sites/sub.example.com/settings.php
|
||||
sites/sub.example.com.site3/settings.php
|
||||
|
||||
When searching for a site configuration (for example www.sub.example.com/site3),
|
||||
Drupal will search for configuration files in the following order, using the
|
||||
first configuration it finds:
|
||||
|
||||
sites/www.sub.example.com.site3/settings.php
|
||||
sites/sub.example.com.site3/settings.php
|
||||
sites/example.com.site3/settings.php
|
||||
sites/www.sub.example.com/settings.php
|
||||
sites/sub.example.com/settings.php
|
||||
sites/example.com/settings.php
|
||||
sites/default/settings.php
|
||||
|
||||
If you are installing on a non-standard port, the port number is treated as the
|
||||
deepest subdomain. For example: http://www.example.com:8080/ could be loaded
|
||||
from sites/8080.www.example.com/. The port number will be removed according to
|
||||
the pattern above if no port-specific configuration is found, just like a real
|
||||
subdomain.
|
||||
|
||||
Each site configuration can have its own site-specific modules and themes in
|
||||
addition to those installed in the standard 'modules' and 'themes' directories.
|
||||
To use site-specific modules or themes, simply create a 'modules' or 'themes'
|
||||
directory within the site configuration directory. For example, if
|
||||
sub.example.com has a custom theme and a custom module that should not be
|
||||
accessible to other sites, the setup would look like this:
|
||||
|
||||
sites/sub.example.com/
|
||||
settings.php
|
||||
themes/custom_theme
|
||||
modules/custom_module
|
||||
|
||||
NOTE: for more information about multiple virtual hosts or the configuration
|
||||
settings, consult http://drupal.org/getting-started/6/install/multi-site
|
||||
|
||||
For more information on configuring Drupal's file system path in a multisite
|
||||
configuration, see step 6 above.
|
||||
|
||||
MORE INFORMATION
|
||||
----------------
|
||||
|
||||
- See the Drupal.org online documentation:
|
||||
http://drupal.org/documentation
|
||||
|
||||
- For a list of security announcements, see the "Security advisories" page at
|
||||
http://drupal.org/security (available as an RSS feed). This page also
|
||||
describes how to subscribe to these announcements via e-mail.
|
||||
|
||||
- For information about the Drupal security process, or to find out how to
|
||||
report a potential security issue to the Drupal security team, see the
|
||||
"Security team" page at http://drupal.org/security-team
|
||||
|
||||
- For information about the wide range of available support options, visit
|
||||
http://drupal.org and click on Community and Support in the top or bottom
|
||||
navigation.
|
||||
Executable → Regular
+106
-106
@@ -1,7 +1,8 @@
|
||||
|
||||
Drupal core is built and maintained by the Drupal project community. Everyone is
|
||||
encouraged to submit issues and changes (patches) to improve Drupal, and to
|
||||
contribute in other ways -- see http://drupal.org/contribute to find out how.
|
||||
contribute in other ways -- see https://www.drupal.org/contribute to find out
|
||||
how.
|
||||
|
||||
Branch maintainers
|
||||
------------------
|
||||
@@ -9,154 +10,154 @@ Branch maintainers
|
||||
The Drupal Core branch maintainers oversee the development of Drupal as a whole.
|
||||
The branch maintainers for Drupal 7 are:
|
||||
|
||||
- Dries Buytaert 'dries' http://drupal.org/user/1
|
||||
- Angela Byron 'webchick' http://drupal.org/user/24967
|
||||
- David Rothstein 'David_Rothstein' http://drupal.org/user/124982
|
||||
- Dries Buytaert 'dries' https://www.drupal.org/u/dries
|
||||
- Angela Byron 'webchick' https://www.drupal.org/u/webchick
|
||||
- Fabian Franz 'Fabianx' https://www.drupal.org/u/fabianx
|
||||
- David Rothstein 'David_Rothstein' https://www.drupal.org/u/david_rothstein
|
||||
- Stefan Ruijsenaars 'stefan.r' https://www.drupal.org/u/stefanr-0
|
||||
|
||||
|
||||
Component maintainers
|
||||
---------------------
|
||||
|
||||
The Drupal Core component maintainers oversee the development of Drupal
|
||||
subsystems. See http://drupal.org/contribute/core-maintainers for more
|
||||
subsystems. See https://www.drupal.org/contribute/core-maintainers for more
|
||||
information on their responsibilities, and to find out how to become a component
|
||||
maintainer. Current component maintainers for Drupal 7:
|
||||
|
||||
Ajax system
|
||||
- Alex Bronstein 'effulgentsia' http://drupal.org/user/78040
|
||||
- Earl Miles 'merlinofchaos' http://drupal.org/user/26979
|
||||
- Alex Bronstein 'effulgentsia' https://www.drupal.org/u/effulgentsia
|
||||
- Earl Miles 'merlinofchaos' https://www.drupal.org/u/merlinofchaos
|
||||
|
||||
Base system
|
||||
- Damien Tournoud 'DamZ' http://drupal.org/user/22211
|
||||
- Moshe Weitzman 'moshe weitzman' http://drupal.org/user/23
|
||||
- Damien Tournoud 'DamZ' https://www.drupal.org/u/damien-tournoud
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
|
||||
Batch system
|
||||
- Yves Chedemois 'yched' http://drupal.org/user/39567
|
||||
- Yves Chedemois 'yched' https://www.drupal.org/u/yched
|
||||
|
||||
Cache system
|
||||
- Damien Tournoud 'DamZ' http://drupal.org/user/22211
|
||||
- Nathaniel Catchpole 'catch' http://drupal.org/user/35733
|
||||
- Damien Tournoud 'DamZ' https://www.drupal.org/u/damien-tournoud
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
|
||||
Cron system
|
||||
- Derek Wright 'dww' http://drupal.org/user/46549
|
||||
- Derek Wright 'dww' https://www.drupal.org/u/dww
|
||||
|
||||
Database system
|
||||
- Larry Garfield 'Crell' http://drupal.org/user/26398
|
||||
- Larry Garfield 'Crell' https://www.drupal.org/u/crell
|
||||
|
||||
- MySQL driver
|
||||
- Larry Garfield 'Crell' http://drupal.org/user/26398
|
||||
- David Strauss 'David Strauss' http://drupal.org/user/93254
|
||||
- Larry Garfield 'Crell' https://www.drupal.org/u/crell
|
||||
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
|
||||
|
||||
- PostgreSQL driver
|
||||
- Damien Tournoud 'DamZ' http://drupal.org/user/22211
|
||||
- Josh Waihi 'fiasco' http://drupal.org/user/188162
|
||||
- Damien Tournoud 'DamZ' https://www.drupal.org/u/damien-tournoud
|
||||
- Josh Waihi 'fiasco' https://www.drupal.org/u/josh-waihi
|
||||
|
||||
- Sqlite driver
|
||||
- Damien Tournoud 'DamZ' http://drupal.org/user/22211
|
||||
- Damien Tournoud 'DamZ' https://www.drupal.org/u/damien-tournoud
|
||||
|
||||
Database update system
|
||||
- Ashok Modi 'BTMash' http://drupal.org/user/60422
|
||||
- Ashok Modi 'BTMash' https://www.drupal.org/u/btmash
|
||||
|
||||
Entity system
|
||||
- Wolfgang Ziegler 'fago' http://drupal.org/user/16747
|
||||
- Nathaniel Catchpole 'catch' http://drupal.org/user/35733
|
||||
- Franz Heinzmann 'Frando' http://drupal.org/user/21850
|
||||
- Wolfgang Ziegler 'fago' https://www.drupal.org/u/fago
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
- Franz Heinzmann 'Frando' https://www.drupal.org/u/frando
|
||||
|
||||
File system
|
||||
- Andrew Morton 'drewish' http://drupal.org/user/34869
|
||||
- Aaron Winborn 'aaron' http://drupal.org/user/33420
|
||||
- Andrew Morton 'drewish' https://www.drupal.org/u/drewish
|
||||
- Aaron Winborn 'aaron' https://www.drupal.org/u/aaron
|
||||
|
||||
Form system
|
||||
- Alex Bronstein 'effulgentsia' http://drupal.org/user/78040
|
||||
- Wolfgang Ziegler 'fago' http://drupal.org/user/16747
|
||||
- Daniel F. Kudwien 'sun' http://drupal.org/user/54136
|
||||
- Franz Heinzmann 'Frando' http://drupal.org/user/21850
|
||||
- Alex Bronstein 'effulgentsia' https://www.drupal.org/u/effulgentsia
|
||||
- Wolfgang Ziegler 'fago' https://www.drupal.org/u/fago
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
- Franz Heinzmann 'Frando' https://www.drupal.org/u/frando
|
||||
|
||||
Image system
|
||||
- Andrew Morton 'drewish' http://drupal.org/user/34869
|
||||
- Nathan Haug 'quicksketch' http://drupal.org/user/35821
|
||||
- Andrew Morton 'drewish' https://www.drupal.org/u/drewish
|
||||
- Nathan Haug 'quicksketch' https://www.drupal.org/u/quicksketch
|
||||
|
||||
Install system
|
||||
- David Rothstein 'David_Rothstein' http://drupal.org/user/124982
|
||||
- David Rothstein 'David_Rothstein' https://www.drupal.org/u/david_rothstein
|
||||
|
||||
JavaScript
|
||||
- Théodore Biadala 'nod_' http://drupal.org/user/598310
|
||||
- Steve De Jonghe 'seutje' http://drupal.org/user/264148
|
||||
- Jesse Renée Beach 'jessebeach' http://drupal.org/user/748566
|
||||
- Théodore Biadala 'nod_' https://www.drupal.org/u/nod_
|
||||
- Steve De Jonghe 'seutje' https://www.drupal.org/u/seutje
|
||||
|
||||
Language system
|
||||
- Francesco Placella 'plach' http://drupal.org/user/183211
|
||||
- Daniel F. Kudwien 'sun' http://drupal.org/user/54136
|
||||
- Francesco Placella 'plach' https://www.drupal.org/u/plach
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
|
||||
Lock system
|
||||
- Damien Tournoud 'DamZ' http://drupal.org/user/22211
|
||||
- Damien Tournoud 'DamZ' https://www.drupal.org/u/damien-tournoud
|
||||
|
||||
Mail system
|
||||
- ?
|
||||
|
||||
Markup
|
||||
- Jacine Luisi 'Jacine' http://drupal.org/user/88931
|
||||
- Daniel F. Kudwien 'sun' http://drupal.org/user/54136
|
||||
- Jacine Luisi 'Jacine' https://www.drupal.org/u/jacine
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
|
||||
Menu system
|
||||
- Peter Wolanin 'pwolanin' http://drupal.org/user/49851
|
||||
- Peter Wolanin 'pwolanin' https://www.drupal.org/u/pwolanin
|
||||
|
||||
Path system
|
||||
- Dave Reid 'davereid' http://drupal.org/user/53892
|
||||
- Nathaniel Catchpole 'catch' http://drupal.org/user/35733
|
||||
- Dave Reid 'davereid' https://www.drupal.org/u/dave-reid
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
|
||||
Render system
|
||||
- Moshe Weitzman 'moshe weitzman' http://drupal.org/user/23
|
||||
- Alex Bronstein 'effulgentsia' http://drupal.org/user/78040
|
||||
- Franz Heinzmann 'Frando' http://drupal.org/user/21850
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- Alex Bronstein 'effulgentsia' https://www.drupal.org/u/effulgentsia
|
||||
- Franz Heinzmann 'Frando' https://www.drupal.org/u/frando
|
||||
|
||||
Theme system
|
||||
- Earl Miles 'merlinofchaos' http://drupal.org/user/26979
|
||||
- Alex Bronstein 'effulgentsia' http://drupal.org/user/78040
|
||||
- Joon Park 'dvessel' http://drupal.org/user/56782
|
||||
- John Albin Wilkins 'JohnAlbin' http://drupal.org/user/32095
|
||||
- Earl Miles 'merlinofchaos' https://www.drupal.org/u/merlinofchaos
|
||||
- Alex Bronstein 'effulgentsia' https://www.drupal.org/u/effulgentsia
|
||||
- Joon Park 'dvessel' https://www.drupal.org/u/dvessel
|
||||
- John Albin Wilkins 'JohnAlbin' https://www.drupal.org/u/johnalbin
|
||||
|
||||
Token system
|
||||
- Dave Reid 'davereid' http://drupal.org/user/53892
|
||||
- Dave Reid 'davereid' https://www.drupal.org/u/dave-reid
|
||||
|
||||
XML-RPC system
|
||||
- Frederic G. Marand 'fgm' http://drupal.org/user/27985
|
||||
- Frederic G. Marand 'fgm' https://www.drupal.org/u/fgm
|
||||
|
||||
|
||||
Topic coordinators
|
||||
------------------
|
||||
|
||||
Accessibility
|
||||
- Everett Zufelt 'Everett Zufelt' http://drupal.org/user/406552
|
||||
- Brandon Bowersox-Johnson 'bowersox' http://drupal.org/user/186415
|
||||
- Everett Zufelt 'Everett Zufelt' https://www.drupal.org/u/everett-zufelt
|
||||
- Brandon Bowersox-Johnson 'bowersox' https://www.drupal.org/u/bowersox
|
||||
|
||||
Documentation
|
||||
- Jennifer Hodgdon 'jhodgdon' http://drupal.org/user/155601
|
||||
- Jennifer Hodgdon 'jhodgdon' https://www.drupal.org/u/jhodgdon
|
||||
|
||||
Translations
|
||||
- Gerhard Killesreiter 'killes' http://drupal.org/user/83
|
||||
- Gerhard Killesreiter 'killes' https://www.drupal.org/u/gerhard-killesreiter
|
||||
|
||||
User experience and usability
|
||||
- Roy Scholten 'yoroy' http://drupal.org/user/41502
|
||||
- Bojhan Somers 'Bojhan' http://drupal.org/user/87969
|
||||
- Roy Scholten 'yoroy' https://www.drupal.org/u/yoroy
|
||||
- Bojhan Somers 'Bojhan' https://www.drupal.org/u/bojhan
|
||||
|
||||
Node Access
|
||||
- Moshe Weitzman 'moshe weitzman' http://drupal.org/user/23
|
||||
- Ken Rickard 'agentrickard' http://drupal.org/user/20975
|
||||
- Jess Myrbo 'xjm' http://drupal.org/user/65776
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- Ken Rickard 'agentrickard' https://www.drupal.org/u/agentrickard
|
||||
|
||||
|
||||
Security team
|
||||
-----------------
|
||||
|
||||
To report a security issue, see: https://drupal.org/security-team/report-issue
|
||||
To report a security issue, see: https://www.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:
|
||||
documentation. See https://www.drupal.org/security-team for more information.
|
||||
The security team lead is:
|
||||
|
||||
- Michael Hess 'mlhess' https://drupal.org/user/102818
|
||||
- Michael Hess 'mlhess' https://www.drupal.org/u/mlhess
|
||||
|
||||
|
||||
Module maintainers
|
||||
@@ -166,142 +167,141 @@ Aggregator module
|
||||
- ?
|
||||
|
||||
Block module
|
||||
- John Albin Wilkins 'JohnAlbin' http://drupal.org/user/32095
|
||||
- John Albin Wilkins 'JohnAlbin' https://www.drupal.org/u/johnalbin
|
||||
|
||||
Blog module
|
||||
- ?
|
||||
|
||||
Book module
|
||||
- Peter Wolanin 'pwolanin' http://drupal.org/user/49851
|
||||
- Peter Wolanin 'pwolanin' https://www.drupal.org/u/pwolanin
|
||||
|
||||
Color module
|
||||
- ?
|
||||
|
||||
Comment module
|
||||
- Nathaniel Catchpole 'catch' http://drupal.org/user/35733
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
|
||||
Contact module
|
||||
- Dave Reid 'davereid' http://drupal.org/user/53892
|
||||
- Dave Reid 'davereid' https://www.drupal.org/u/dave-reid
|
||||
|
||||
Contextual module
|
||||
- Daniel F. Kudwien 'sun' http://drupal.org/user/54136
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
|
||||
Dashboard module
|
||||
- ?
|
||||
|
||||
Database logging module
|
||||
- Khalid Baheyeldin 'kbahey' http://drupal.org/user/4063
|
||||
- Khalid Baheyeldin 'kbahey' https://www.drupal.org/u/kbahey
|
||||
|
||||
Field module
|
||||
- Yves Chedemois 'yched' http://drupal.org/user/39567
|
||||
- Barry Jaspan 'bjaspan' http://drupal.org/user/46413
|
||||
- Yves Chedemois 'yched' https://www.drupal.org/u/yched
|
||||
- Barry Jaspan 'bjaspan' https://www.drupal.org/u/bjaspan
|
||||
|
||||
Field UI module
|
||||
- Yves Chedemois 'yched' http://drupal.org/user/39567
|
||||
- Yves Chedemois 'yched' https://www.drupal.org/u/yched
|
||||
|
||||
File module
|
||||
- Aaron Winborn 'aaron' http://drupal.org/user/33420
|
||||
- Aaron Winborn 'aaron' https://www.drupal.org/u/aaron
|
||||
|
||||
Filter module
|
||||
- Daniel F. Kudwien 'sun' http://drupal.org/user/54136
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
|
||||
Forum module
|
||||
- Lee Rowlands 'larowlan' http://drupal.org/user/395439
|
||||
- Lee Rowlands 'larowlan' https://www.drupal.org/u/larowlan
|
||||
|
||||
Help module
|
||||
- ?
|
||||
|
||||
Image module
|
||||
- Nathan Haug 'quicksketch' http://drupal.org/user/35821
|
||||
- Nathan Haug 'quicksketch' https://www.drupal.org/u/quicksketch
|
||||
|
||||
Locale module
|
||||
- Gábor Hojtsy 'Gábor Hojtsy' http://drupal.org/user/4166
|
||||
- Gábor Hojtsy 'Gábor Hojtsy' https://www.drupal.org/u/gábor-hojtsy
|
||||
|
||||
Menu module
|
||||
- ?
|
||||
|
||||
Node module
|
||||
- Moshe Weitzman 'moshe weitzman' http://drupal.org/user/23
|
||||
- David Strauss 'David Strauss' http://drupal.org/user/93254
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
|
||||
|
||||
OpenID module
|
||||
- Vojtech Kusy 'wojtha' http://drupal.org/user/56154
|
||||
- Christian Schmidt 'c960657' http://drupal.org/user/216078
|
||||
- Damien Tournoud 'DamZ' http://drupal.org/user/22211
|
||||
- Vojtech Kusy 'wojtha' https://www.drupal.org/u/wojtha
|
||||
- Christian Schmidt 'c960657' https://www.drupal.org/u/c960657
|
||||
- Damien Tournoud 'DamZ' https://www.drupal.org/u/damien-tournoud
|
||||
|
||||
Overlay module
|
||||
- Katherine Senzee 'ksenzee' http://drupal.org/user/139855
|
||||
- Katherine Senzee 'ksenzee' https://www.drupal.org/u/ksenzee
|
||||
|
||||
Path module
|
||||
- Dave Reid 'davereid' http://drupal.org/user/53892
|
||||
- Dave Reid 'davereid' https://www.drupal.org/u/dave-reid
|
||||
|
||||
PHP module
|
||||
- ?
|
||||
|
||||
Poll module
|
||||
- Andrei Mateescu 'amateescu' http://drupal.org/user/729614
|
||||
- Andrei Mateescu 'amateescu' https://www.drupal.org/u/amateescu
|
||||
|
||||
Profile module
|
||||
- ?
|
||||
|
||||
RDF module
|
||||
- Stéphane Corlosquet 'scor' http://drupal.org/user/52142
|
||||
- Stéphane Corlosquet 'scor' https://www.drupal.org/u/scor
|
||||
|
||||
Search module
|
||||
- Doug Green 'douggreen' http://drupal.org/user/29191
|
||||
- Doug Green 'douggreen' https://www.drupal.org/u/douggreen
|
||||
|
||||
Shortcut module
|
||||
- David Rothstein 'David_Rothstein' http://drupal.org/user/124982
|
||||
- David Rothstein 'David_Rothstein' https://www.drupal.org/u/david_rothstein
|
||||
|
||||
Simpletest module
|
||||
- Jimmy Berry 'boombatower' http://drupal.org/user/214218
|
||||
- Jimmy Berry 'boombatower' https://www.drupal.org/u/boombatower
|
||||
|
||||
Statistics module
|
||||
- Tim Millwood 'timmillwood' http://drupal.org/user/227849
|
||||
- Tim Millwood 'timmillwood' https://www.drupal.org/u/timmillwood
|
||||
|
||||
Syslog module
|
||||
- Khalid Baheyeldin 'kbahey' http://drupal.org/user/4063
|
||||
- Khalid Baheyeldin 'kbahey' https://www.drupal.org/u/kbahey
|
||||
|
||||
System module
|
||||
- ?
|
||||
|
||||
Taxonomy module
|
||||
- Jess Myrbo 'xjm' http://drupal.org/user/65776
|
||||
- Nathaniel Catchpole 'catch' http://drupal.org/user/35733
|
||||
- Benjamin Doherty 'bangpound' http://drupal.org/user/100456
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
- Benjamin Doherty 'bangpound' https://www.drupal.org/u/bangpound
|
||||
|
||||
Toolbar module
|
||||
- ?
|
||||
|
||||
Tracker module
|
||||
- David Strauss 'David Strauss' http://drupal.org/user/93254
|
||||
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
|
||||
|
||||
Translation module
|
||||
- Francesco Placella 'plach' http://drupal.org/user/183211
|
||||
- Francesco Placella 'plach' https://www.drupal.org/u/plach
|
||||
|
||||
Trigger module
|
||||
- ?
|
||||
|
||||
Update module
|
||||
- Derek Wright 'dww' http://drupal.org/user/46549
|
||||
- Derek Wright 'dww' https://www.drupal.org/u/dww
|
||||
|
||||
User module
|
||||
- Moshe Weitzman 'moshe weitzman' http://drupal.org/user/23
|
||||
- David Strauss 'David Strauss' http://drupal.org/user/93254
|
||||
- Moshe Weitzman 'moshe weitzman' https://www.drupal.org/u/moshe-weitzman
|
||||
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
|
||||
|
||||
|
||||
Theme maintainers
|
||||
-----------------
|
||||
|
||||
Bartik theme
|
||||
- Jen Simmons 'jensimmons' http://drupal.org/user/140882
|
||||
- Jeff Burns 'Jeff Burnz' http://drupal.org/user/61393
|
||||
- Jen Simmons 'jensimmons' https://www.drupal.org/u/jensimmons
|
||||
- Jeff Burns 'Jeff Burnz' https://www.drupal.org/u/jeff-burnz
|
||||
|
||||
Garland theme
|
||||
- John Albin Wilkins 'JohnAlbin' http://drupal.org/user/32095
|
||||
- John Albin Wilkins 'JohnAlbin' https://www.drupal.org/u/johnalbin
|
||||
|
||||
Seven theme
|
||||
- Jeff Burns 'Jeff Burnz' http://drupal.org/user/61393
|
||||
- Jeff Burns 'Jeff Burnz' https://www.drupal.org/u/jeff-burnz
|
||||
|
||||
Stark theme
|
||||
- John Albin Wilkins 'JohnAlbin' http://drupal.org/user/32095
|
||||
- John Albin Wilkins 'JohnAlbin' https://www.drupal.org/u/johnalbin
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
cer
|
||||
contentadminrelink
|
||||
entity_translation_search_api
|
||||
entityreference
|
||||
feedback
|
||||
//field_group
|
||||
filter_path_alias
|
||||
flag_lists
|
||||
//nodeformcols
|
||||
search_api
|
||||
search_api_page
|
||||
search_api_solr
|
||||
termreferencetree
|
||||
views
|
||||
wysiwyg
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Core Patches :
|
||||
- Implement language aware tokens for one time login link and cancel link
|
||||
https://www.drupal.org/node/1754162
|
||||
|
||||
//- est-ce que je dois faire ce patch ???
|
||||
//includes/entity.inc
|
||||
//see https://www.drupal.org/node/1003788
|
||||
|
||||
|
||||
# Modules :
|
||||
|
||||
link : allow any tld (https://www.drupal.org/node/2299657#comment-11414075)
|
||||
cer
|
||||
contentadminrelink
|
||||
// entity_translation_search_api
|
||||
entityreference
|
||||
feedback
|
||||
// field_group
|
||||
filter_path_alias
|
||||
// flag_lists
|
||||
// nodeformcols
|
||||
// search_api
|
||||
// search_api_page
|
||||
// search_api_solr
|
||||
termreferencetree
|
||||
views
|
||||
wysiwyg
|
||||
views_rss_media
|
||||
node_export :
|
||||
- https://www.drupal.org/node/1869918
|
||||
- https://www.drupal.org/node/1911638
|
||||
login_tobogan (pd with field permission et donc field collection)
|
||||
- https://www.drupal.org/node/1365764#comment-10286257
|
||||
- logintoboggan-exempting_lt_preauth_role_from_user_permissions_js-1365764-52.patch
|
||||
- interdiff-1365764-23-52-do-not-test.diff
|
||||
+10
@@ -64,6 +64,9 @@ following the instructions in the INTRODUCTION section at the top of this file:
|
||||
Sometimes an update includes changes to default.settings.php (this will be
|
||||
noted in the release notes). If that's the case, follow these steps:
|
||||
|
||||
- Locate your settings.php file in the /sites/* directory. (Typically
|
||||
sites/default.)
|
||||
|
||||
- Make a backup copy of your settings.php file, with a different file name.
|
||||
|
||||
- Make a copy of the new default.settings.php file, and name the copy
|
||||
@@ -74,6 +77,13 @@ following the instructions in the INTRODUCTION section at the top of this file:
|
||||
database information, and you will also want to copy in any other
|
||||
customizations you have added.
|
||||
|
||||
You can find the release notes for your version at
|
||||
https://www.drupal.org/project/drupal. At bottom of the project page under
|
||||
"Downloads" use the link for your version of Drupal to view the release
|
||||
notes. If your version is not listed, use the 'View all releases' link. From
|
||||
this page you can scroll down or use the filter to find your version and its
|
||||
release notes.
|
||||
|
||||
4. Download the latest Drupal 7.x release from http://drupal.org to a
|
||||
directory outside of your web root. Extract the archive and copy the files
|
||||
into your Drupal directory.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#! /bin/bash
|
||||
|
||||
sudo chown -R $USER:http sites/all/modules/features/
|
||||
sudo chmod -R g+w sites/all/modules/features/
|
||||
+37
-2
@@ -230,6 +230,10 @@
|
||||
* functions.
|
||||
*/
|
||||
function ajax_render($commands = array()) {
|
||||
// Although ajax_deliver() does this, some contributed and custom modules
|
||||
// render Ajax responses without using that delivery callback.
|
||||
ajax_set_verification_header();
|
||||
|
||||
// Ajax responses aren't rendered with html.tpl.php, so we have to call
|
||||
// drupal_get_css() and drupal_get_js() here, in order to have new files added
|
||||
// during this request to be loaded by the page. We only want to send back
|
||||
@@ -390,7 +394,7 @@ function ajax_form_callback() {
|
||||
if (!empty($form_state['triggering_element'])) {
|
||||
$callback = $form_state['triggering_element']['#ajax']['callback'];
|
||||
}
|
||||
if (!empty($callback) && function_exists($callback)) {
|
||||
if (!empty($callback) && is_callable($callback)) {
|
||||
$result = $callback($form, $form_state);
|
||||
|
||||
if (!(is_array($result) && isset($result['#type']) && $result['#type'] == 'ajax')) {
|
||||
@@ -487,6 +491,9 @@ function ajax_deliver($page_callback_result) {
|
||||
}
|
||||
}
|
||||
|
||||
// Let ajax.js know that this response is safe to process.
|
||||
ajax_set_verification_header();
|
||||
|
||||
// Print the response.
|
||||
$commands = ajax_prepare_response($page_callback_result);
|
||||
$json = ajax_render($commands);
|
||||
@@ -576,6 +583,29 @@ function ajax_prepare_response($page_callback_result) {
|
||||
return $commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a response header for ajax.js to trust the response body.
|
||||
*
|
||||
* It is not safe to invoke Ajax commands within user-uploaded files, so this
|
||||
* header protects against those being invoked.
|
||||
*
|
||||
* @see Drupal.ajax.options.success()
|
||||
*/
|
||||
function ajax_set_verification_header() {
|
||||
$added = &drupal_static(__FUNCTION__);
|
||||
|
||||
// User-uploaded files cannot set any response headers, so a custom header is
|
||||
// used to indicate to ajax.js that this response is safe. Note that most
|
||||
// Ajax requests bound using the Form API will be protected by having the URL
|
||||
// flagged as trusted in Drupal.settings, so this header is used only for
|
||||
// things like custom markup that gets Ajax behaviors attached.
|
||||
if (empty($added)) {
|
||||
drupal_add_http_header('X-Drupal-Ajax-Token', '1');
|
||||
// Avoid sending the header twice.
|
||||
$added = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs end-of-Ajax-request tasks.
|
||||
*
|
||||
@@ -764,7 +794,12 @@ function ajax_pre_render_element($element) {
|
||||
|
||||
$element['#attached']['js'][] = array(
|
||||
'type' => 'setting',
|
||||
'data' => array('ajax' => array($element['#id'] => $settings)),
|
||||
'data' => array(
|
||||
'ajax' => array($element['#id'] => $settings),
|
||||
'urlIsAjaxTrusted' => array(
|
||||
$settings['url'] => TRUE,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Indicate that Ajax processing was successful.
|
||||
|
||||
+2
-2
@@ -460,10 +460,10 @@ function _batch_finished() {
|
||||
if (isset($batch_set['file']) && is_file($batch_set['file'])) {
|
||||
include_once DRUPAL_ROOT . '/' . $batch_set['file'];
|
||||
}
|
||||
if (function_exists($batch_set['finished'])) {
|
||||
if (is_callable($batch_set['finished'])) {
|
||||
$queue = _batch_queue($batch_set);
|
||||
$operations = $queue->getAllItems();
|
||||
$batch_set['finished']($batch_set['success'], $batch_set['results'], $operations, format_interval($batch_set['elapsed'] / 1000));
|
||||
call_user_func($batch_set['finished'], $batch_set['success'], $batch_set['results'], $operations, format_interval($batch_set['elapsed'] / 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+362
-54
@@ -8,7 +8,7 @@
|
||||
/**
|
||||
* The current system version.
|
||||
*/
|
||||
define('VERSION', '7.36');
|
||||
define('VERSION', '7.56');
|
||||
|
||||
/**
|
||||
* Core API compatibility.
|
||||
@@ -254,8 +254,13 @@ define('DRUPAL_PHP_FUNCTION_PATTERN', '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
|
||||
* http://tools.ietf.org/html/rfc7231#section-7.1.1.1
|
||||
*
|
||||
* Example: Sun, 06 Nov 1994 08:49:37 GMT
|
||||
*
|
||||
* This constant was introduced in PHP 7.0.19 and PHP 7.1.5 but needs to be
|
||||
* defined by Drupal for earlier PHP versions.
|
||||
*/
|
||||
define('DATE_RFC7231', 'D, d M Y H:i:s \G\M\T');
|
||||
if (!defined('DATE_RFC7231')) {
|
||||
define('DATE_RFC7231', 'D, d M Y H:i:s \G\M\T');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a caching wrapper to be used in place of large array structures.
|
||||
@@ -718,6 +723,16 @@ function drupal_valid_http_host($host) {
|
||||
&& preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an HTTPS request is being served.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the request is HTTPS, FALSE otherwise.
|
||||
*/
|
||||
function drupal_is_https() {
|
||||
return isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base URL, cookie domain, and session name from configuration.
|
||||
*/
|
||||
@@ -731,7 +746,7 @@ function drupal_settings_initialize() {
|
||||
if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {
|
||||
include_once DRUPAL_ROOT . '/' . conf_path() . '/settings.php';
|
||||
}
|
||||
$is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on';
|
||||
$is_https = drupal_is_https();
|
||||
|
||||
if (isset($base_url)) {
|
||||
// Parse fixed base URL from settings.php.
|
||||
@@ -828,14 +843,21 @@ function drupal_settings_initialize() {
|
||||
* @param $filename
|
||||
* The filename of the item if it is to be set explicitly rather
|
||||
* than by consulting the database.
|
||||
* @param bool $trigger_error
|
||||
* Whether to trigger an error when a file is missing or has unexpectedly
|
||||
* moved. This defaults to TRUE, but can be set to FALSE by calling code that
|
||||
* merely wants to check whether an item exists in the filesystem.
|
||||
*
|
||||
* @return
|
||||
* The filename of the requested item or NULL if the item is not found.
|
||||
*/
|
||||
function drupal_get_filename($type, $name, $filename = NULL) {
|
||||
function drupal_get_filename($type, $name, $filename = NULL, $trigger_error = TRUE) {
|
||||
// The $files static variable will hold the locations of all requested files.
|
||||
// We can be sure that any file listed in this static variable actually
|
||||
// exists as all additions have gone through a file_exists() check.
|
||||
// The location of files will not change during the request, so do not use
|
||||
// drupal_static().
|
||||
static $files = array(), $dirs = array();
|
||||
static $files = array();
|
||||
|
||||
// Profiles are a special case: they have a fixed location and naming.
|
||||
if ($type == 'profile') {
|
||||
@@ -847,59 +869,41 @@ function drupal_get_filename($type, $name, $filename = NULL) {
|
||||
}
|
||||
|
||||
if (!empty($filename) && file_exists($filename)) {
|
||||
// Prime the static cache with the provided filename.
|
||||
$files[$type][$name] = $filename;
|
||||
}
|
||||
elseif (isset($files[$type][$name])) {
|
||||
// nothing
|
||||
// This item had already been found earlier in the request, either through
|
||||
// priming of the static cache (for example, in system_list()), through a
|
||||
// lookup in the {system} table, or through a file scan (cached or not). Do
|
||||
// nothing.
|
||||
}
|
||||
// Verify that we have an active database connection, before querying
|
||||
// the database. This is required because this function is called both
|
||||
// before we have a database connection (i.e. during installation) and
|
||||
// when a database connection fails.
|
||||
else {
|
||||
// Look for the filename listed in the {system} table. Verify that we have
|
||||
// an active database connection before doing so, since this function is
|
||||
// called both before we have a database connection (i.e. during
|
||||
// installation) and when a database connection fails.
|
||||
$database_unavailable = TRUE;
|
||||
try {
|
||||
if (function_exists('db_query')) {
|
||||
$file = db_query("SELECT filename FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
|
||||
if ($file !== FALSE && file_exists(DRUPAL_ROOT . '/' . $file)) {
|
||||
$files[$type][$name] = $file;
|
||||
}
|
||||
$database_unavailable = FALSE;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// The database table may not exist because Drupal is not yet installed,
|
||||
// or the database might be down. We have a fallback for this case so we
|
||||
// hide the error completely.
|
||||
// the database might be down, or we may have done a non-database cache
|
||||
// flush while $conf['page_cache_without_database'] = TRUE and
|
||||
// $conf['page_cache_invoke_hooks'] = TRUE. We have a fallback for these
|
||||
// cases so we hide the error completely.
|
||||
}
|
||||
// Fallback to searching the filesystem if the database could not find the
|
||||
// file or the file returned by the database is not found.
|
||||
// Fall back to searching the filesystem if the database could not find the
|
||||
// file or the file does not exist at the path returned by the database.
|
||||
if (!isset($files[$type][$name])) {
|
||||
// We have a consistent directory naming: modules, themes...
|
||||
$dir = $type . 's';
|
||||
if ($type == 'theme_engine') {
|
||||
$dir = 'themes/engines';
|
||||
$extension = 'engine';
|
||||
}
|
||||
elseif ($type == 'theme') {
|
||||
$extension = 'info';
|
||||
}
|
||||
else {
|
||||
$extension = $type;
|
||||
}
|
||||
|
||||
if (!isset($dirs[$dir][$extension])) {
|
||||
$dirs[$dir][$extension] = TRUE;
|
||||
if (!function_exists('drupal_system_listing')) {
|
||||
require_once DRUPAL_ROOT . '/includes/common.inc';
|
||||
}
|
||||
// Scan the appropriate directories for all files with the requested
|
||||
// extension, not just the file we are currently looking for. This
|
||||
// prevents unnecessary scans from being repeated when this function is
|
||||
// called more than once in the same page request.
|
||||
$matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0);
|
||||
foreach ($matches as $matched_name => $file) {
|
||||
$files[$type][$matched_name] = $file->uri;
|
||||
}
|
||||
}
|
||||
$files[$type][$name] = _drupal_get_filename_fallback($type, $name, $trigger_error, $database_unavailable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -908,6 +912,256 @@ function drupal_get_filename($type, $name, $filename = NULL) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a cached file system scan as a fallback when searching for a file.
|
||||
*
|
||||
* This function looks for the requested file by triggering a file scan,
|
||||
* caching the new location if the file has moved and caching the miss
|
||||
* if the file is missing. If a file had been marked as missing in a previous
|
||||
* file scan, or if it has been marked as moved and is still in the last known
|
||||
* location, no new file scan will be performed.
|
||||
*
|
||||
* @param string $type
|
||||
* The type of the item (theme, theme_engine, module, profile).
|
||||
* @param string $name
|
||||
* The name of the item for which the filename is requested.
|
||||
* @param bool $trigger_error
|
||||
* Whether to trigger an error when a file is missing or has unexpectedly
|
||||
* moved.
|
||||
* @param bool $database_unavailable
|
||||
* Whether this function is being called because the Drupal database could
|
||||
* not be queried for the file's location.
|
||||
*
|
||||
* @return
|
||||
* The filename of the requested item or NULL if the item is not found.
|
||||
*
|
||||
* @see drupal_get_filename()
|
||||
*/
|
||||
function _drupal_get_filename_fallback($type, $name, $trigger_error, $database_unavailable) {
|
||||
$file_scans = &_drupal_file_scan_cache();
|
||||
$filename = NULL;
|
||||
|
||||
// If the cache indicates that the item is missing, or we can verify that the
|
||||
// item exists in the location the cache says it exists in, use that.
|
||||
if (isset($file_scans[$type][$name]) && ($file_scans[$type][$name] === FALSE || file_exists($file_scans[$type][$name]))) {
|
||||
$filename = $file_scans[$type][$name];
|
||||
}
|
||||
// Otherwise, perform a new file scan to find the item.
|
||||
else {
|
||||
$filename = _drupal_get_filename_perform_file_scan($type, $name);
|
||||
// Update the static cache, and mark the persistent cache for updating at
|
||||
// the end of the page request. See drupal_file_scan_write_cache().
|
||||
$file_scans[$type][$name] = $filename;
|
||||
$file_scans['#write_cache'] = TRUE;
|
||||
}
|
||||
|
||||
// If requested, trigger a user-level warning about the missing or
|
||||
// unexpectedly moved file. If the database was unavailable, do not trigger a
|
||||
// warning in the latter case, though, since if the {system} table could not
|
||||
// be queried there is no way to know if the location found here was
|
||||
// "unexpected" or not.
|
||||
if ($trigger_error) {
|
||||
$error_type = $filename === FALSE ? 'missing' : 'moved';
|
||||
if ($error_type == 'missing' || !$database_unavailable) {
|
||||
_drupal_get_filename_fallback_trigger_error($type, $name, $error_type);
|
||||
}
|
||||
}
|
||||
|
||||
// The cache stores FALSE for files that aren't found (to be able to
|
||||
// distinguish them from files that have not yet been searched for), but
|
||||
// drupal_get_filename() expects NULL for these instead, so convert to NULL
|
||||
// before returning.
|
||||
if ($filename === FALSE) {
|
||||
$filename = NULL;
|
||||
}
|
||||
return $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current list of cached file system scan results.
|
||||
*
|
||||
* @return
|
||||
* An associative array tracking the most recent file scan results for all
|
||||
* files that have had scans performed. The keys are the type and name of the
|
||||
* item that was searched for, and the values can be either:
|
||||
* - Boolean FALSE if the item was not found in the file system.
|
||||
* - A string pointing to the location where the item was found.
|
||||
*/
|
||||
function &_drupal_file_scan_cache() {
|
||||
$file_scans = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
// The file scan results are stored in a persistent cache (in addition to the
|
||||
// static cache) but because this function can be called before the
|
||||
// persistent cache is available, we must merge any items that were found
|
||||
// earlier in the page request into the results from the persistent cache.
|
||||
if (!isset($file_scans['#cache_merge_done'])) {
|
||||
try {
|
||||
if (function_exists('cache_get')) {
|
||||
$cache = cache_get('_drupal_file_scan_cache', 'cache_bootstrap');
|
||||
if (!empty($cache->data)) {
|
||||
// File scan results from the current request should take precedence
|
||||
// over the results from the persistent cache, since they are newer.
|
||||
$file_scans = drupal_array_merge_deep($cache->data, $file_scans);
|
||||
}
|
||||
// Set a flag to indicate that the persistent cache does not need to be
|
||||
// merged again.
|
||||
$file_scans['#cache_merge_done'] = TRUE;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Hide the error.
|
||||
}
|
||||
}
|
||||
|
||||
return $file_scans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a file system scan to search for a system resource.
|
||||
*
|
||||
* @param $type
|
||||
* The type of the item (theme, theme_engine, module, profile).
|
||||
* @param $name
|
||||
* The name of the item for which the filename is requested.
|
||||
*
|
||||
* @return
|
||||
* The filename of the requested item or FALSE if the item is not found.
|
||||
*
|
||||
* @see drupal_get_filename()
|
||||
* @see _drupal_get_filename_fallback()
|
||||
*/
|
||||
function _drupal_get_filename_perform_file_scan($type, $name) {
|
||||
// The location of files will not change during the request, so do not use
|
||||
// drupal_static().
|
||||
static $dirs = array(), $files = array();
|
||||
|
||||
// We have a consistent directory naming: modules, themes...
|
||||
$dir = $type . 's';
|
||||
if ($type == 'theme_engine') {
|
||||
$dir = 'themes/engines';
|
||||
$extension = 'engine';
|
||||
}
|
||||
elseif ($type == 'theme') {
|
||||
$extension = 'info';
|
||||
}
|
||||
else {
|
||||
$extension = $type;
|
||||
}
|
||||
|
||||
// Check if we had already scanned this directory/extension combination.
|
||||
if (!isset($dirs[$dir][$extension])) {
|
||||
// Log that we have now scanned this directory/extension combination
|
||||
// into a static variable so as to prevent unnecessary file scans.
|
||||
$dirs[$dir][$extension] = TRUE;
|
||||
if (!function_exists('drupal_system_listing')) {
|
||||
require_once DRUPAL_ROOT . '/includes/common.inc';
|
||||
}
|
||||
// Scan the appropriate directories for all files with the requested
|
||||
// extension, not just the file we are currently looking for. This
|
||||
// prevents unnecessary scans from being repeated when this function is
|
||||
// called more than once in the same page request.
|
||||
$matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0);
|
||||
foreach ($matches as $matched_name => $file) {
|
||||
// Log the locations found in the file scan into a static variable.
|
||||
$files[$type][$matched_name] = $file->uri;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the results of the file system scan, or FALSE to indicate the file
|
||||
// was not found.
|
||||
return isset($files[$type][$name]) ? $files[$type][$name] : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a user-level warning for missing or unexpectedly moved files.
|
||||
*
|
||||
* @param $type
|
||||
* The type of the item (theme, theme_engine, module, profile).
|
||||
* @param $name
|
||||
* The name of the item for which the filename is requested.
|
||||
* @param $error_type
|
||||
* The type of the error ('missing' or 'moved').
|
||||
*
|
||||
* @see drupal_get_filename()
|
||||
* @see _drupal_get_filename_fallback()
|
||||
*/
|
||||
function _drupal_get_filename_fallback_trigger_error($type, $name, $error_type) {
|
||||
// Hide messages due to known bugs that will appear on a lot of sites.
|
||||
// @todo Remove this in https://www.drupal.org/node/2383823
|
||||
if (empty($name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we only show any missing or moved file errors only once per
|
||||
// request.
|
||||
static $errors_triggered = array();
|
||||
if (empty($errors_triggered[$type][$name][$error_type])) {
|
||||
// Use _drupal_trigger_error_with_delayed_logging() here since these are
|
||||
// triggered during low-level operations that cannot necessarily be
|
||||
// interrupted by a watchdog() call.
|
||||
if ($error_type == 'missing') {
|
||||
_drupal_trigger_error_with_delayed_logging(format_string('The following @type is missing from the file system: %name. For information about how to fix this, see <a href="@documentation">the documentation page</a>.', array('@type' => $type, '%name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
|
||||
}
|
||||
elseif ($error_type == 'moved') {
|
||||
_drupal_trigger_error_with_delayed_logging(format_string('The following @type has moved within the file system: %name. In order to fix this, clear caches or put the @type back in its original location. For more information, see <a href="@documentation">the documentation page</a>.', array('@type' => $type, '%name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
|
||||
}
|
||||
$errors_triggered[$type][$name][$error_type] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes trigger_error() with logging delayed until the end of the request.
|
||||
*
|
||||
* This is an alternative to PHP's trigger_error() function which can be used
|
||||
* during low-level Drupal core operations that need to avoid being interrupted
|
||||
* by a watchdog() call.
|
||||
*
|
||||
* Normally, Drupal's error handler calls watchdog() in response to a
|
||||
* trigger_error() call. However, this invokes hook_watchdog() which can run
|
||||
* arbitrary code. If the trigger_error() happens in the middle of an
|
||||
* operation such as a rebuild operation which should not be interrupted by
|
||||
* arbitrary code, that could potentially break or trigger the rebuild again.
|
||||
* This function protects against that by delaying the watchdog() call until
|
||||
* the end of the current page request.
|
||||
*
|
||||
* This is an internal function which should only be called by low-level Drupal
|
||||
* core functions. It may be removed in a future Drupal 7 release.
|
||||
*
|
||||
* @param string $error_msg
|
||||
* The error message to trigger. As with trigger_error() itself, this is
|
||||
* limited to 1024 bytes; additional characters beyond that will be removed.
|
||||
* @param int $error_type
|
||||
* (optional) The type of error. This should be one of the E_USER family of
|
||||
* constants. As with trigger_error() itself, this defaults to E_USER_NOTICE
|
||||
* if not provided.
|
||||
*
|
||||
* @see _drupal_log_error()
|
||||
*/
|
||||
function _drupal_trigger_error_with_delayed_logging($error_msg, $error_type = E_USER_NOTICE) {
|
||||
$delay_logging = &drupal_static(__FUNCTION__, FALSE);
|
||||
$delay_logging = TRUE;
|
||||
trigger_error($error_msg, $error_type);
|
||||
$delay_logging = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the file scan cache to the persistent cache.
|
||||
*
|
||||
* This cache stores all files marked as missing or moved after a file scan
|
||||
* to prevent unnecessary file scans in subsequent requests. This cache is
|
||||
* cleared in system_list_reset() (i.e. after a module/theme rebuild).
|
||||
*/
|
||||
function drupal_file_scan_write_cache() {
|
||||
// Only write to the persistent cache if requested, and if we know that any
|
||||
// data previously in the cache was successfully loaded and merged in by
|
||||
// _drupal_file_scan_cache().
|
||||
$file_scans = &_drupal_file_scan_cache();
|
||||
if (isset($file_scans['#write_cache']) && isset($file_scans['#cache_merge_done'])) {
|
||||
unset($file_scans['#write_cache']);
|
||||
cache_set('_drupal_file_scan_cache', $file_scans, 'cache_bootstrap');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the persistent variable table.
|
||||
*
|
||||
@@ -1055,7 +1309,7 @@ function drupal_page_get_cache($check_only = FALSE) {
|
||||
* Determines the cacheability of the current page.
|
||||
*
|
||||
* @param $allow_caching
|
||||
* Set to FALSE if you want to prevent this page to get cached.
|
||||
* Set to FALSE if you want to prevent this page from being cached.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the current page can be cached, FALSE otherwise.
|
||||
@@ -1261,7 +1515,11 @@ function drupal_page_header() {
|
||||
|
||||
$default_headers = array(
|
||||
'Expires' => 'Sun, 19 Nov 1978 05:00:00 GMT',
|
||||
'Cache-Control' => 'no-cache, must-revalidate, post-check=0, pre-check=0',
|
||||
'Cache-Control' => 'no-cache, must-revalidate',
|
||||
// Prevent browsers from sniffing a response and picking a MIME type
|
||||
// different from the declared content-type, since that can lead to
|
||||
// XSS and other vulnerabilities.
|
||||
'X-Content-Type-Options' => 'nosniff',
|
||||
);
|
||||
drupal_send_headers($default_headers);
|
||||
}
|
||||
@@ -1435,6 +1693,23 @@ function drupal_unpack($obj, $field = 'data') {
|
||||
* available to code that needs localization. See st() and get_t() for
|
||||
* alternatives.
|
||||
*
|
||||
* @section sec_context String context
|
||||
* Matching source strings are normally only translated once, and the same
|
||||
* translation is used everywhere that has a matching string. However, in some
|
||||
* cases, a certain English source string needs to have multiple translations.
|
||||
* One example of this is the string "May", which could be used as either a
|
||||
* full month name or a 3-letter abbreviated month. In other languages where
|
||||
* the month name for May has more than 3 letters, you would need to provide
|
||||
* two different translations (one for the full name and one abbreviated), and
|
||||
* the correct form would need to be chosen, depending on how "May" is being
|
||||
* used. To facilitate this, the "May" string should be provided with two
|
||||
* different contexts in the $options parameter when calling t(). For example:
|
||||
* @code
|
||||
* t('May', array(), array('context' => 'Long month name')
|
||||
* t('May', array(), array('context' => 'Abbreviated month name')
|
||||
* @endcode
|
||||
* See https://localize.drupal.org/node/2109 for more information.
|
||||
*
|
||||
* @param $string
|
||||
* A string containing the English string to translate.
|
||||
* @param $args
|
||||
@@ -1445,8 +1720,9 @@ function drupal_unpack($obj, $field = 'data') {
|
||||
* An associative array of additional options, with the following elements:
|
||||
* - 'langcode' (defaults to the current language): The language code to
|
||||
* translate to a language other than what is used to display the page.
|
||||
* - 'context' (defaults to the empty context): The context the source string
|
||||
* belongs to.
|
||||
* - 'context' (defaults to the empty context): A string giving the context
|
||||
* that the source string belongs to. See @ref sec_context above for more
|
||||
* information.
|
||||
*
|
||||
* @return
|
||||
* The translated string.
|
||||
@@ -1776,7 +2052,7 @@ function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NO
|
||||
* @see theme_status_messages()
|
||||
*/
|
||||
function drupal_set_message($message = NULL, $type = 'status', $repeat = TRUE) {
|
||||
if ($message) {
|
||||
if ($message || $message === '0' || $message === 0) {
|
||||
if (!isset($_SESSION['messages'][$type])) {
|
||||
$_SESSION['messages'][$type] = array();
|
||||
}
|
||||
@@ -2464,6 +2740,9 @@ function _drupal_bootstrap_database() {
|
||||
// the install or upgrade process.
|
||||
spl_autoload_register('drupal_autoload_class');
|
||||
spl_autoload_register('drupal_autoload_interface');
|
||||
if (version_compare(PHP_VERSION, '5.4') >= 0) {
|
||||
spl_autoload_register('drupal_autoload_trait');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2779,10 +3058,14 @@ function language_list($field = 'language') {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default language used on the site
|
||||
* Returns the default language, as an object, or one of its properties.
|
||||
*
|
||||
* @param $property
|
||||
* Optional property of the language object to return
|
||||
* (optional) The property of the language object to return.
|
||||
*
|
||||
* @return
|
||||
* Either the language object for the default language used on the site,
|
||||
* or the property of that object named in the $property parameter.
|
||||
*/
|
||||
function language_default($property = NULL) {
|
||||
$language = variable_get('language_default', (object) array('language' => 'en', 'name' => 'English', 'native' => 'English', 'direction' => 0, 'enabled' => 1, 'plurals' => 0, 'formula' => '', 'domain' => '', 'prefix' => '', 'weight' => 0, 'javascript' => ''));
|
||||
@@ -2934,8 +3217,15 @@ function ip_address() {
|
||||
// Eliminate all trusted IPs.
|
||||
$untrusted = array_diff($forwarded, $reverse_proxy_addresses);
|
||||
|
||||
// The right-most IP is the most specific we can trust.
|
||||
$ip_address = array_pop($untrusted);
|
||||
if (!empty($untrusted)) {
|
||||
// The right-most IP is the most specific we can trust.
|
||||
$ip_address = array_pop($untrusted);
|
||||
}
|
||||
else {
|
||||
// All IP addresses in the forwarded array are configured proxy IPs
|
||||
// (and thus trusted). We take the leftmost IP.
|
||||
$ip_address = array_shift($forwarded);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2952,7 +3242,9 @@ function ip_address() {
|
||||
* Gets the schema definition of a table, or the whole database schema.
|
||||
*
|
||||
* The returned schema will include any modifications made by any
|
||||
* module that implements hook_schema_alter().
|
||||
* module that implements hook_schema_alter(). To get the schema without
|
||||
* modifications, use drupal_get_schema_unprocessed().
|
||||
*
|
||||
*
|
||||
* @param $table
|
||||
* The name of the table. If not given, the schema of all tables is returned.
|
||||
@@ -3107,6 +3399,22 @@ function drupal_autoload_class($class) {
|
||||
return _registry_check_code('class', $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms that a trait is available.
|
||||
*
|
||||
* This function is rarely called directly. Instead, it is registered as an
|
||||
* spl_autoload() handler, and PHP calls it for us when necessary.
|
||||
*
|
||||
* @param string $trait
|
||||
* The name of the trait to check or load.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the trait is currently available, FALSE otherwise.
|
||||
*/
|
||||
function drupal_autoload_trait($trait) {
|
||||
return _registry_check_code('trait', $trait);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for a resource in the registry.
|
||||
*
|
||||
@@ -3125,7 +3433,7 @@ function drupal_autoload_class($class) {
|
||||
function _registry_check_code($type, $name = NULL) {
|
||||
static $lookup_cache, $cache_update_needed;
|
||||
|
||||
if ($type == 'class' && class_exists($name) || $type == 'interface' && interface_exists($name)) {
|
||||
if ($type == 'class' && class_exists($name) || $type == 'interface' && interface_exists($name) || $type == 'trait' && trait_exists($name)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -3158,7 +3466,7 @@ function _registry_check_code($type, $name = NULL) {
|
||||
$cache_key = $type[0] . $name;
|
||||
if (isset($lookup_cache[$cache_key])) {
|
||||
if ($lookup_cache[$cache_key]) {
|
||||
require_once DRUPAL_ROOT . '/' . $lookup_cache[$cache_key];
|
||||
include_once DRUPAL_ROOT . '/' . $lookup_cache[$cache_key];
|
||||
}
|
||||
return (bool) $lookup_cache[$cache_key];
|
||||
}
|
||||
@@ -3183,7 +3491,7 @@ function _registry_check_code($type, $name = NULL) {
|
||||
$lookup_cache[$cache_key] = $file;
|
||||
|
||||
if ($file) {
|
||||
require_once DRUPAL_ROOT . '/' . $file;
|
||||
include_once DRUPAL_ROOT . '/' . $file;
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
|
||||
+13
-2
@@ -14,6 +14,7 @@
|
||||
*
|
||||
* @param $bin
|
||||
* The cache bin for which the cache object should be returned.
|
||||
*
|
||||
* @return DrupalCacheInterface
|
||||
* The cache object associated with the specified bin.
|
||||
*
|
||||
@@ -121,7 +122,12 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
|
||||
* the administrator panel.
|
||||
* - cache_path: Stores the system paths that have an alias.
|
||||
* @param $expire
|
||||
* (optional) One of the following values:
|
||||
* (optional) Controls the maximum lifetime of this cache entry. Note that
|
||||
* caches might be subject to clearing at any time, so this setting does not
|
||||
* guarantee a minimum lifetime. With this in mind, the cache should not be
|
||||
* used for data that must be kept during a cache clear, like sessions.
|
||||
*
|
||||
* Use one of the following values:
|
||||
* - CACHE_PERMANENT: Indicates that the item should never be removed unless
|
||||
* explicitly told to using cache_clear_all() with a cache ID.
|
||||
* - CACHE_TEMPORARY: Indicates that the item should be removed at the next
|
||||
@@ -261,7 +267,12 @@ interface DrupalCacheInterface {
|
||||
* 1MB in size to be stored by default. When caching large arrays or
|
||||
* similar, take care to ensure $data does not exceed this size.
|
||||
* @param $expire
|
||||
* (optional) One of the following values:
|
||||
* (optional) Controls the maximum lifetime of this cache entry. Note that
|
||||
* caches might be subject to clearing at any time, so this setting does not
|
||||
* guarantee a minimum lifetime. With this in mind, the cache should not be
|
||||
* used for data that must be kept during a cache clear, like sessions.
|
||||
*
|
||||
* Use one of the following values:
|
||||
* - CACHE_PERMANENT: Indicates that the item should never be removed unless
|
||||
* explicitly told to using cache_clear_all() with a cache ID.
|
||||
* - CACHE_TEMPORARY: Indicates that the item should be removed at the next
|
||||
|
||||
+156
-45
@@ -487,7 +487,7 @@ function drupal_http_build_query(array $query, $parent = '') {
|
||||
$params = array();
|
||||
|
||||
foreach ($query as $key => $value) {
|
||||
$key = ($parent ? $parent . '[' . rawurlencode($key) . ']' : rawurlencode($key));
|
||||
$key = $parent ? $parent . rawurlencode('[' . $key . ']') : rawurlencode($key);
|
||||
|
||||
// Recurse into children.
|
||||
if (is_array($value)) {
|
||||
@@ -688,6 +688,13 @@ function drupal_goto($path = '', array $options = array(), $http_response_code =
|
||||
$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);
|
||||
|
||||
// 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.
|
||||
* - method: A string containing the request method. Defaults to 'GET'.
|
||||
* - 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
|
||||
* may be followed. Defaults to 3.
|
||||
* - 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
|
||||
* easy access the array keys are returned in lower case.
|
||||
* - data: A string containing the response body that was received.
|
||||
*
|
||||
* @see http_build_query()
|
||||
*/
|
||||
function drupal_http_request($url, array $options = array()) {
|
||||
// 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) {
|
||||
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
|
||||
break;
|
||||
case 301: // Moved permanently
|
||||
@@ -1522,7 +1538,7 @@ function _filter_xss_split($m, $store = FALSE) {
|
||||
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.
|
||||
return '';
|
||||
}
|
||||
@@ -1754,9 +1770,15 @@ function format_rss_item($title, $link, $description, $args = array()) {
|
||||
* - 'key': element name
|
||||
* - 'value': element contents
|
||||
* - '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
|
||||
* 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) {
|
||||
$output = '';
|
||||
@@ -1769,7 +1791,7 @@ function format_xml_elements($array) {
|
||||
}
|
||||
|
||||
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 {
|
||||
$output .= " />\n";
|
||||
@@ -2214,20 +2236,8 @@ function url($path = NULL, array $options = array()) {
|
||||
'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'])) {
|
||||
// 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.
|
||||
@@ -2347,12 +2357,18 @@ function url($path = NULL, array $options = array()) {
|
||||
*/
|
||||
function url_is_external($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)
|
||||
// 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
|
||||
&& !preg_match('![/?#]!', substr($path, 0, $colonpos))
|
||||
&& drupal_strip_dangerous_protocols($path) == $path);
|
||||
@@ -2637,6 +2653,15 @@ function drupal_deliver_html_page($page_callback_result) {
|
||||
global $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.
|
||||
if (is_int($page_callback_result)) {
|
||||
// @todo: Break these up into separate functions?
|
||||
@@ -2751,6 +2776,7 @@ function drupal_page_footer() {
|
||||
_registry_check_code(REGISTRY_WRITE_LOOKUP_CACHE);
|
||||
drupal_cache_system_paths();
|
||||
module_implements_write_cache();
|
||||
drupal_file_scan_write_cache();
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* 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) {
|
||||
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) {
|
||||
$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.
|
||||
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.
|
||||
$options['weight'] += count($css) / 1000;
|
||||
$options['weight'] += $count / 1000;
|
||||
$count++;
|
||||
|
||||
// Add the data to the CSS array depending on the type.
|
||||
switch ($options['type']) {
|
||||
@@ -3802,7 +3840,7 @@ function drupal_load_stylesheet_content($contents, $optimize = FALSE) {
|
||||
|
||||
// Replaces @import commands with the actual stylesheet content.
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -3862,6 +3900,21 @@ function drupal_delete_file_if_stale($uri) {
|
||||
* The cleaned identifier.
|
||||
*/
|
||||
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.
|
||||
$identifier = strtr($identifier, $filter);
|
||||
|
||||
@@ -3933,7 +3986,11 @@ function drupal_html_id($id) {
|
||||
// be merged with content already on the base page. The HTML IDs must be
|
||||
// unique for the fully merged content. Therefore, initialize $seen_ids to
|
||||
// take into account IDs that are already in use on the base page.
|
||||
$seen_ids_init = &drupal_static(__FUNCTION__ . ':init');
|
||||
static $drupal_static_fast;
|
||||
if (!isset($drupal_static_fast['seen_ids_init'])) {
|
||||
$drupal_static_fast['seen_ids_init'] = &drupal_static(__FUNCTION__ . ':init');
|
||||
}
|
||||
$seen_ids_init = &$drupal_static_fast['seen_ids_init'];
|
||||
if (!isset($seen_ids_init)) {
|
||||
// Ideally, Drupal would provide an API to persist state information about
|
||||
// prior page requests in the database, and we'd be able to add this
|
||||
@@ -3978,7 +4035,10 @@ function drupal_html_id($id) {
|
||||
}
|
||||
}
|
||||
}
|
||||
$seen_ids = &drupal_static(__FUNCTION__, $seen_ids_init);
|
||||
if (!isset($drupal_static_fast['seen_ids'])) {
|
||||
$drupal_static_fast['seen_ids'] = &drupal_static(__FUNCTION__, $seen_ids_init);
|
||||
}
|
||||
$seen_ids = &$drupal_static_fast['seen_ids'];
|
||||
|
||||
$id = strtr(drupal_strtolower($id), array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
|
||||
|
||||
@@ -5212,6 +5272,11 @@ function _drupal_bootstrap_full() {
|
||||
fix_gpc_magic();
|
||||
// Load all enabled modules
|
||||
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.
|
||||
file_get_stream_wrappers();
|
||||
// Ensure mt_rand is reseeded, to prevent random values from one page load
|
||||
@@ -5308,8 +5373,8 @@ function drupal_page_set_cache() {
|
||||
*
|
||||
* 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() {
|
||||
// Allow execution to continue even if the request gets canceled.
|
||||
@@ -5371,12 +5436,12 @@ function drupal_cron_run() {
|
||||
// Do not run if queue wants to skip.
|
||||
continue;
|
||||
}
|
||||
$function = $info['worker callback'];
|
||||
$callback = $info['worker callback'];
|
||||
$end = time() + (isset($info['time']) ? $info['time'] : 15);
|
||||
$queue = DrupalQueue::get($queue_name);
|
||||
while (time() < $end && ($item = $queue->claimItem())) {
|
||||
try {
|
||||
$function($item->data);
|
||||
call_user_func($callback, $item->data);
|
||||
$queue->deleteItem($item);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
@@ -6329,13 +6394,21 @@ function drupal_render_cid_parts($granularity = NULL) {
|
||||
}
|
||||
|
||||
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
|
||||
// resource drag for sites with many users, so when a module is being
|
||||
// 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));
|
||||
}
|
||||
elseif ($granularity & DRUPAL_CACHE_PER_USER) {
|
||||
elseif ($cache_per_user) {
|
||||
$cid_parts[] = "u.$user->uid";
|
||||
}
|
||||
|
||||
@@ -7075,7 +7148,8 @@ function drupal_uninstall_schema($module) {
|
||||
* specification of a schema, as it was defined in a module's
|
||||
* hook_schema(). No additional default values will be set,
|
||||
* 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
|
||||
* hook_schema(), so it allows you to derive your tables from existing
|
||||
@@ -7137,6 +7211,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.
|
||||
*
|
||||
@@ -7338,7 +7430,16 @@ function drupal_write_record($table, &$record, $primary_keys = array()) {
|
||||
* Information stored in a module .info file:
|
||||
* - name: The real name of the module for display purposes.
|
||||
* - 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.
|
||||
*
|
||||
* See forum.info for an example of a module .info file.
|
||||
@@ -7418,7 +7519,6 @@ function drupal_parse_info_file($filename) {
|
||||
*/
|
||||
function drupal_parse_info_format($data) {
|
||||
$info = array();
|
||||
$constants = get_defined_constants();
|
||||
|
||||
if (preg_match_all('
|
||||
@^\s* # Start at the beginning of a line, ignoring leading whitespace
|
||||
@@ -7458,8 +7558,8 @@ function drupal_parse_info_format($data) {
|
||||
}
|
||||
|
||||
// Handle PHP constants.
|
||||
if (isset($constants[$value])) {
|
||||
$value = $constants[$value];
|
||||
if (preg_match('/^\w+$/i', $value) && defined($value)) {
|
||||
$value = constant($value);
|
||||
}
|
||||
|
||||
// Insert actual value.
|
||||
@@ -7623,7 +7723,12 @@ function debug($data, $label = NULL, $print_r = FALSE) {
|
||||
* Parses a dependency for comparison by drupal_check_incompatibility().
|
||||
*
|
||||
* @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
|
||||
* An associative array with three keys:
|
||||
@@ -7638,6 +7743,12 @@ function debug($data, $label = NULL, $print_r = FALSE) {
|
||||
* @see drupal_check_incompatibility()
|
||||
*/
|
||||
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
|
||||
// supports. Also, op is optional and defaults to equals.
|
||||
$p_op = '(?P<operation>!=|==|=|<|<=|>|>=|<>)?';
|
||||
@@ -7646,7 +7757,6 @@ function drupal_parse_dependency($dependency) {
|
||||
$p_major = '(?P<major>\d+)';
|
||||
// By setting the minor version to x, branches can be matched.
|
||||
$p_minor = '(?P<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
|
||||
$value = array();
|
||||
$parts = explode('(', $dependency, 2);
|
||||
$value['name'] = trim($parts[0]);
|
||||
if (isset($parts[1])) {
|
||||
@@ -7761,6 +7871,7 @@ function entity_get_info($entity_type = NULL) {
|
||||
// Prepare entity schema fields SQL info for
|
||||
// DrupalEntityControllerInterface::buildQuery().
|
||||
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']);
|
||||
if (isset($entity_info[$name]['revision table'])) {
|
||||
$entity_info[$name]['schema_fields_sql']['revision table'] = drupal_schema_fields_sql($entity_info[$name]['revision table']);
|
||||
|
||||
@@ -296,6 +296,20 @@ abstract class DatabaseConnection extends PDO {
|
||||
*/
|
||||
protected $prefixReplace = array();
|
||||
|
||||
/**
|
||||
* List of escaped database, table, and field names, keyed by unescaped names.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $escapedNames = array();
|
||||
|
||||
/**
|
||||
* List of escaped aliases names, keyed by unescaped aliases.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $escapedAliases = array();
|
||||
|
||||
function __construct($dsn, $username, $password, $driver_options = array()) {
|
||||
// Initialize and prepare the connection prefix.
|
||||
$this->setPrefix(isset($this->connectionOptions['prefix']) ? $this->connectionOptions['prefix'] : '');
|
||||
@@ -626,7 +640,7 @@ abstract class DatabaseConnection extends PDO {
|
||||
* A sanitized version of the query comment string.
|
||||
*/
|
||||
protected function filterComment($comment = '') {
|
||||
return preg_replace('/(\/\*\s*)|(\s*\*\/)/', '', $comment);
|
||||
return strtr($comment, array('*' => ' * '));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -656,7 +670,7 @@ abstract class DatabaseConnection extends PDO {
|
||||
* @return DatabaseStatementInterface
|
||||
* This method will return one of: the executed statement, the number of
|
||||
* rows affected by the query (not the number matched), or the generated
|
||||
* insert IT of the last query, depending on the value of
|
||||
* insert ID of the last query, depending on the value of
|
||||
* $options['return']. Typically that value will be set by default or a
|
||||
* query builder and should not be set by a user. If there is an error,
|
||||
* this method will return NULL and may throw an exception if
|
||||
@@ -919,11 +933,14 @@ abstract class DatabaseConnection extends PDO {
|
||||
* For some database drivers, it may also wrap the table name in
|
||||
* database-specific escape characters.
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* The sanitized table name string.
|
||||
*/
|
||||
public function escapeTable($table) {
|
||||
return preg_replace('/[^A-Za-z0-9_.]+/', '', $table);
|
||||
if (!isset($this->escapedNames[$table])) {
|
||||
$this->escapedNames[$table] = preg_replace('/[^A-Za-z0-9_.]+/', '', $table);
|
||||
}
|
||||
return $this->escapedNames[$table];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -933,11 +950,14 @@ abstract class DatabaseConnection extends PDO {
|
||||
* For some database drivers, it may also wrap the field name in
|
||||
* database-specific escape characters.
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* The sanitized field name string.
|
||||
*/
|
||||
public function escapeField($field) {
|
||||
return preg_replace('/[^A-Za-z0-9_.]+/', '', $field);
|
||||
if (!isset($this->escapedNames[$field])) {
|
||||
$this->escapedNames[$field] = preg_replace('/[^A-Za-z0-9_.]+/', '', $field);
|
||||
}
|
||||
return $this->escapedNames[$field];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -948,11 +968,14 @@ abstract class DatabaseConnection extends PDO {
|
||||
* DatabaseConnection::escapeTable(), this doesn't allow the period (".")
|
||||
* because that is not allowed in aliases.
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* The sanitized field name string.
|
||||
*/
|
||||
public function escapeAlias($field) {
|
||||
return preg_replace('/[^A-Za-z0-9_]+/', '', $field);
|
||||
if (!isset($this->escapedAliases[$field])) {
|
||||
$this->escapedAliases[$field] = preg_replace('/[^A-Za-z0-9_]+/', '', $field);
|
||||
}
|
||||
return $this->escapedAliases[$field];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1313,6 +1336,39 @@ abstract class DatabaseConnection extends PDO {
|
||||
* also larger than the $existing_id if one was passed in.
|
||||
*/
|
||||
abstract public function nextId($existing_id = 0);
|
||||
|
||||
/**
|
||||
* Checks whether utf8mb4 support is configurable in settings.php.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function utf8mb4IsConfigurable() {
|
||||
// Since 4 byte UTF-8 is not supported by default, there is nothing to
|
||||
// configure.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether utf8mb4 support is currently active.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function utf8mb4IsActive() {
|
||||
// Since 4 byte UTF-8 is not supported by default, there is nothing to
|
||||
// activate.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether utf8mb4 support is available on the current database system.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function utf8mb4IsSupported() {
|
||||
// By default we assume that the database backend may not support 4 byte
|
||||
// UTF-8.
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,12 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
|
||||
$this->connectionOptions = $connection_options;
|
||||
|
||||
$charset = 'utf8';
|
||||
// Check if the charset is overridden to utf8mb4 in settings.php.
|
||||
if ($this->utf8mb4IsActive()) {
|
||||
$charset = 'utf8mb4';
|
||||
}
|
||||
|
||||
// The DSN should use either a socket or a host/port.
|
||||
if (isset($connection_options['unix_socket'])) {
|
||||
$dsn = 'mysql:unix_socket=' . $connection_options['unix_socket'];
|
||||
@@ -39,7 +45,7 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
// Character set is added to dsn to ensure PDO uses the proper character
|
||||
// set when escaping. This has security implications. See
|
||||
// https://www.drupal.org/node/1201452 for further discussion.
|
||||
$dsn .= ';charset=utf8';
|
||||
$dsn .= ';charset=' . $charset;
|
||||
$dsn .= ';dbname=' . $connection_options['database'];
|
||||
// Allow PDO options to be overridden.
|
||||
$connection_options += array(
|
||||
@@ -51,6 +57,11 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
// Because MySQL's prepared statements skip the query cache, because it's dumb.
|
||||
PDO::ATTR_EMULATE_PREPARES => TRUE,
|
||||
);
|
||||
if (defined('PDO::MYSQL_ATTR_MULTI_STATEMENTS')) {
|
||||
// An added connection option in PHP 5.5.21+ to optionally limit SQL to a
|
||||
// single statement like mysqli.
|
||||
$connection_options['pdo'] += array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => FALSE);
|
||||
}
|
||||
|
||||
parent::__construct($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
|
||||
|
||||
@@ -58,10 +69,10 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
// certain one has been set; otherwise, MySQL defaults to 'utf8_general_ci'
|
||||
// for UTF-8.
|
||||
if (!empty($connection_options['collation'])) {
|
||||
$this->exec('SET NAMES utf8 COLLATE ' . $connection_options['collation']);
|
||||
$this->exec('SET NAMES ' . $charset . ' COLLATE ' . $connection_options['collation']);
|
||||
}
|
||||
else {
|
||||
$this->exec('SET NAMES utf8');
|
||||
$this->exec('SET NAMES ' . $charset);
|
||||
}
|
||||
|
||||
// Set MySQL init_commands if not already defined. Default Drupal's MySQL
|
||||
@@ -76,10 +87,12 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
'init_commands' => array(),
|
||||
);
|
||||
$connection_options['init_commands'] += array(
|
||||
'sql_mode' => "SET sql_mode = 'ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER'",
|
||||
'sql_mode' => "SET sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER'",
|
||||
);
|
||||
// Set connection options.
|
||||
$this->exec(implode('; ', $connection_options['init_commands']));
|
||||
// Execute initial commands.
|
||||
foreach ($connection_options['init_commands'] as $sql) {
|
||||
$this->exec($sql);
|
||||
}
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
@@ -199,6 +212,42 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function utf8mb4IsConfigurable() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function utf8mb4IsActive() {
|
||||
return isset($this->connectionOptions['charset']) && $this->connectionOptions['charset'] === 'utf8mb4';
|
||||
}
|
||||
|
||||
public function utf8mb4IsSupported() {
|
||||
// Ensure that the MySQL driver supports utf8mb4 encoding.
|
||||
$version = $this->getAttribute(PDO::ATTR_CLIENT_VERSION);
|
||||
if (strpos($version, 'mysqlnd') !== FALSE) {
|
||||
// The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
|
||||
$version = preg_replace('/^\D+([\d.]+).*/', '$1', $version);
|
||||
if (version_compare($version, '5.0.9', '<')) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The libmysqlclient driver supports utf8mb4 starting at version 5.5.3.
|
||||
if (version_compare($version, '5.5.3', '<')) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the MySQL server supports large prefixes and utf8mb4.
|
||||
try {
|
||||
$this->query("CREATE TABLE {drupal_utf8mb4_test} (id VARCHAR(255), PRIMARY KEY(id(255))) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci ROW_FORMAT=DYNAMIC ENGINE=INNODB");
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return FALSE;
|
||||
}
|
||||
$this->query("DROP TABLE {drupal_utf8mb4_test}");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
$info['table'] = substr($table, ++$pos);
|
||||
}
|
||||
else {
|
||||
$db_info = Database::getConnectionInfo();
|
||||
$info['database'] = $db_info[$this->connection->getTarget()]['database'];
|
||||
$db_info = $this->connection->getConnectionOptions();
|
||||
$info['database'] = $db_info['database'];
|
||||
$info['table'] = $table;
|
||||
}
|
||||
return $info;
|
||||
@@ -81,7 +81,8 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
// Provide defaults if needed.
|
||||
$table += array(
|
||||
'mysql_engine' => 'InnoDB',
|
||||
'mysql_character_set' => 'utf8',
|
||||
// Allow the default charset to be overridden in settings.php.
|
||||
'mysql_character_set' => $this->connection->utf8mb4IsActive() ? 'utf8mb4' : 'utf8',
|
||||
);
|
||||
|
||||
$sql = "CREATE TABLE {" . $name . "} (\n";
|
||||
@@ -109,6 +110,13 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
$sql .= ' COLLATE ' . $info['collation'];
|
||||
}
|
||||
|
||||
// The row format needs to be either DYNAMIC or COMPRESSED in order to allow
|
||||
// for the innodb_large_prefix setting to take effect, see
|
||||
// https://dev.mysql.com/doc/refman/5.6/en/create-table.html
|
||||
if ($this->connection->utf8mb4IsActive()) {
|
||||
$sql .= ' ROW_FORMAT=DYNAMIC';
|
||||
}
|
||||
|
||||
// Add table comment.
|
||||
if (!empty($table['description'])) {
|
||||
$sql .= ' COMMENT ' . $this->prepareComment($table['description'], self::COMMENT_MAX_TABLE);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* The name by which to obtain a lock for retrive the next insert id.
|
||||
* The name by which to obtain a lock for retrieving the next insert id.
|
||||
*/
|
||||
define('POSTGRESQL_NEXTID_LOCK', 1000);
|
||||
|
||||
@@ -55,7 +55,7 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
|
||||
$connection_options['pdo'] += array(
|
||||
// Prepared statements are most effective for performance when queries
|
||||
// are recycled (used several times). However, if they are not re-used,
|
||||
// prepared statements become ineffecient. Since most of Drupal's
|
||||
// prepared statements become inefficient. Since most of Drupal's
|
||||
// prepared queries are not re-used, it should be faster to emulate
|
||||
// the preparation than to actually ready statements for re-use. If in
|
||||
// doubt, reset to FALSE and measure performance.
|
||||
@@ -175,14 +175,14 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive a the next id in a sequence.
|
||||
* Retrieve the next id in a sequence.
|
||||
*
|
||||
* PostgreSQL has built in sequences. We'll use these instead of inserting
|
||||
* and updating a sequences table.
|
||||
*/
|
||||
public function nextId($existing = 0) {
|
||||
|
||||
// Retrive the name of the sequence. This information cannot be cached
|
||||
// Retrieve the name of the sequence. This information cannot be cached
|
||||
// because the prefix may change, for example, like it does in simpletests.
|
||||
$sequence_name = $this->makeSequenceName('sequences', 'value');
|
||||
|
||||
@@ -194,7 +194,7 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
|
||||
}
|
||||
|
||||
// PostgreSQL advisory locks are simply locks to be used by an
|
||||
// application such as Drupal. This will prevent other Drupal proccesses
|
||||
// application such as Drupal. This will prevent other Drupal processes
|
||||
// from altering the sequence while we are.
|
||||
$this->query("SELECT pg_advisory_lock(" . POSTGRESQL_NEXTID_LOCK . ")");
|
||||
|
||||
@@ -209,13 +209,21 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
|
||||
// Reset the sequence to a higher value than the existing id.
|
||||
$this->query("ALTER SEQUENCE " . $sequence_name . " RESTART WITH " . ($existing + 1));
|
||||
|
||||
// Retrive the next id. We know this will be as high as we want it.
|
||||
// Retrieve the next id. We know this will be as high as we want it.
|
||||
$id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
|
||||
|
||||
$this->query("SELECT pg_advisory_unlock(" . POSTGRESQL_NEXTID_LOCK . ")");
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function utf8mb4IsActive() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function utf8mb4IsSupported() {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -165,7 +165,7 @@ class DatabaseTasks_pgsql extends DatabaseTasks {
|
||||
LANGUAGE \'sql\''
|
||||
);
|
||||
|
||||
// Using || to concatenate in Drupal is not recommeneded because there are
|
||||
// Using || to concatenate in Drupal is not recommended because there are
|
||||
// database drivers for Drupal that do not support the syntax, however
|
||||
// they do support CONCAT(item1, item2) which we can replicate in
|
||||
// PostgreSQL. PostgreSQL requires the function to be defined for each
|
||||
|
||||
@@ -80,7 +80,7 @@ class SelectQuery_pgsql extends SelectQuery {
|
||||
}
|
||||
|
||||
// If a table loads all fields, it can not be added again. It would
|
||||
// result in an ambigious alias error because that field would be loaded
|
||||
// result in an ambiguous alias error because that field would be loaded
|
||||
// twice: Once through table_alias.* and once directly. If the field
|
||||
// actually belongs to a different table, it must be added manually.
|
||||
foreach ($this->tables as $table) {
|
||||
@@ -90,7 +90,7 @@ class SelectQuery_pgsql extends SelectQuery {
|
||||
}
|
||||
|
||||
// If $field contains an characters which are not allowed in a field name
|
||||
// it is considered an expression, these can't be handeld automatically
|
||||
// it is considered an expression, these can't be handled automatically
|
||||
// either.
|
||||
if ($this->connection->escapeField($field) != $field) {
|
||||
return $return;
|
||||
|
||||
@@ -845,8 +845,8 @@ class DeleteQuery extends Query implements QueryConditionInterface {
|
||||
/**
|
||||
* Executes the DELETE query.
|
||||
*
|
||||
* @return
|
||||
* The return value is dependent on the database connection.
|
||||
* @return int
|
||||
* The number of rows affected by the delete query.
|
||||
*/
|
||||
public function execute() {
|
||||
$values = array();
|
||||
@@ -1242,7 +1242,7 @@ class UpdateQuery extends Query implements QueryConditionInterface {
|
||||
* MergeQuery::updateFields() and MergeQuery::insertFields() needs to be called
|
||||
* instead. MergeQuery::fields() can also be called which calls both of these
|
||||
* methods as the common case is to use the same column-value pairs for both
|
||||
* INSERT and UPDATE. However, this is not mandatory. Another convinient
|
||||
* INSERT and UPDATE. However, this is not mandatory. Another convenient
|
||||
* wrapper is MergeQuery::key() which adds the same column-value pairs to the
|
||||
* condition and the INSERT query part.
|
||||
*
|
||||
|
||||
@@ -92,7 +92,8 @@ require_once dirname(__FILE__) . '/query.inc';
|
||||
* specification). Each specification is an array containing the name of
|
||||
* the referenced table ('table'), and an array of column mappings
|
||||
* ('columns'). Column mappings are defined by key pairs ('source_column' =>
|
||||
* 'referenced_column').
|
||||
* 'referenced_column'). This key is for documentation purposes only; foreign
|
||||
* keys are not created in the database, nor are they enforced by Drupal.
|
||||
* - 'indexes': An associative array of indexes ('indexname' =>
|
||||
* specification). Each specification is an array of one or more
|
||||
* key column specifiers (see below) that form an index on the
|
||||
@@ -144,6 +145,8 @@ require_once dirname(__FILE__) . '/query.inc';
|
||||
* 'unique keys' => array(
|
||||
* 'vid' => array('vid'),
|
||||
* ),
|
||||
* // For documentation purposes only; foreign keys are not created in the
|
||||
* // database.
|
||||
* 'foreign keys' => array(
|
||||
* 'node_revision' => array(
|
||||
* 'table' => 'node_revision',
|
||||
@@ -161,6 +164,9 @@ require_once dirname(__FILE__) . '/query.inc';
|
||||
* @see drupal_install_schema()
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for database schema definitions.
|
||||
*/
|
||||
abstract class DatabaseSchema implements QueryPlaceholderInterface {
|
||||
|
||||
protected $connection;
|
||||
@@ -288,7 +294,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
|
||||
protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) {
|
||||
$info = $this->connection->getConnectionOptions();
|
||||
|
||||
// Retrive the table name and schema
|
||||
// Retrieve the table name and schema
|
||||
$table_info = $this->getPrefixInfo($table_name, $add_prefix);
|
||||
|
||||
$condition = new DatabaseCondition('AND');
|
||||
|
||||
@@ -1231,6 +1231,21 @@ class SelectQuery extends Query implements SelectQueryInterface {
|
||||
|
||||
// Modules may alter all queries or only those having a particular tag.
|
||||
if (isset($this->alterTags)) {
|
||||
// Many contrib modules assume that query tags used for access-checking
|
||||
// purposes follow the pattern $entity_type . '_access'. But this is
|
||||
// not the case for taxonomy terms, since core used to add term_access
|
||||
// instead of taxonomy_term_access to its queries. Provide backwards
|
||||
// compatibility by adding both tags here instead of attempting to fix
|
||||
// all contrib modules in a coordinated effort.
|
||||
// TODO:
|
||||
// - Extract this mechanism into a hook as part of a public (non-security)
|
||||
// issue.
|
||||
// - Emit E_USER_DEPRECATED if term_access is used.
|
||||
// https://www.drupal.org/node/2575081
|
||||
$term_access_tags = array('term_access' => 1, 'taxonomy_term_access' => 1);
|
||||
if (array_intersect_key($this->alterTags, $term_access_tags)) {
|
||||
$this->alterTags += $term_access_tags;
|
||||
}
|
||||
$hooks = array('query');
|
||||
foreach ($this->alterTags as $tag => $value) {
|
||||
$hooks[] = 'query_' . $tag;
|
||||
|
||||
@@ -378,6 +378,14 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
|
||||
}
|
||||
}
|
||||
|
||||
public function utf8mb4IsActive() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function utf8mb4IsSupported() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,8 +14,6 @@ class DatabaseTasks_sqlite extends DatabaseTasks {
|
||||
|
||||
/**
|
||||
* Minimum engine version.
|
||||
*
|
||||
* @todo: consider upping to 3.6.8 in Drupal 8 to get SAVEPOINT support.
|
||||
*/
|
||||
public function minimumVersion() {
|
||||
return '3.3.7';
|
||||
|
||||
@@ -99,16 +99,15 @@ class UpdateQuery_sqlite extends UpdateQuery {
|
||||
|
||||
/**
|
||||
* SQLite specific implementation of DeleteQuery.
|
||||
*
|
||||
* When the WHERE is omitted from a DELETE statement and the table being deleted
|
||||
* has no triggers, SQLite uses an optimization to erase the entire table content
|
||||
* without having to visit each row of the table individually.
|
||||
*
|
||||
* Prior to SQLite 3.6.5, SQLite does not return the actual number of rows deleted
|
||||
* by that optimized "truncate" optimization.
|
||||
*/
|
||||
class DeleteQuery_sqlite extends DeleteQuery {
|
||||
public function execute() {
|
||||
// When the WHERE is omitted from a DELETE statement and the table being
|
||||
// deleted has no triggers, SQLite uses an optimization to erase the entire
|
||||
// table content without having to visit each row of the table individually.
|
||||
// Prior to SQLite 3.6.5, SQLite does not return the actual number of rows
|
||||
// deleted by that optimized "truncate" optimization. But we want to return
|
||||
// the number of rows affected, so we calculate it directly.
|
||||
if (!count($this->condition)) {
|
||||
$total_rows = $this->connection->query('SELECT COUNT(*) FROM {' . $this->connection->escapeTable($this->table) . '}')->fetchField();
|
||||
parent::execute();
|
||||
|
||||
@@ -244,7 +244,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
// database. So the syntax '...RENAME TO database.table' would fail.
|
||||
// So we must determine the full table name here rather than surrounding
|
||||
// the table with curly braces incase the db_prefix contains a reference
|
||||
// to a database outside of our existsing database.
|
||||
// to a database outside of our existing database.
|
||||
$info = $this->getPrefixInfo($new_name);
|
||||
$this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $info['table']);
|
||||
|
||||
|
||||
+10
-10
@@ -12,11 +12,6 @@ function system_default_date_formats() {
|
||||
$formats = array();
|
||||
|
||||
// Short date formats.
|
||||
$formats[] = array(
|
||||
'type' => 'short',
|
||||
'format' => 'Y-m-d H:i',
|
||||
'locales' => array(),
|
||||
);
|
||||
$formats[] = array(
|
||||
'type' => 'short',
|
||||
'format' => 'm/d/Y - H:i',
|
||||
@@ -37,6 +32,11 @@ function system_default_date_formats() {
|
||||
'format' => 'd.m.Y - H:i',
|
||||
'locales' => array('de-ch', 'de-de', 'de-lu', 'fi-fi', 'fr-ch', 'is-is', 'pl-pl', 'ro-ro', 'ru-ru'),
|
||||
);
|
||||
$formats[] = array(
|
||||
'type' => 'short',
|
||||
'format' => 'Y-m-d H:i',
|
||||
'locales' => array(),
|
||||
);
|
||||
$formats[] = array(
|
||||
'type' => 'short',
|
||||
'format' => 'm/d/Y - g:ia',
|
||||
@@ -84,11 +84,6 @@ function system_default_date_formats() {
|
||||
);
|
||||
|
||||
// Medium date formats.
|
||||
$formats[] = array(
|
||||
'type' => 'medium',
|
||||
'format' => 'D, Y-m-d H:i',
|
||||
'locales' => array(),
|
||||
);
|
||||
$formats[] = array(
|
||||
'type' => 'medium',
|
||||
'format' => 'D, m/d/Y - H:i',
|
||||
@@ -104,6 +99,11 @@ function system_default_date_formats() {
|
||||
'format' => 'D, Y/m/d - H:i',
|
||||
'locales' => array('en-ca', 'fr-ca', 'no-no', 'sv-se'),
|
||||
);
|
||||
$formats[] = array(
|
||||
'type' => 'medium',
|
||||
'format' => 'D, Y-m-d H:i',
|
||||
'locales' => array(),
|
||||
);
|
||||
$formats[] = array(
|
||||
'type' => 'medium',
|
||||
'format' => 'F j, Y - H:i',
|
||||
|
||||
+68
-22
@@ -157,18 +157,6 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
|
||||
public function load($ids = array(), $conditions = array()) {
|
||||
$entities = array();
|
||||
|
||||
# PATCH http://drupal.org/node/1003788#comment-5195682
|
||||
// Clean the $ids array to remove non-integer values that can be passed
|
||||
// in from various sources, including menu callbacks.
|
||||
if (is_array($ids)) {
|
||||
foreach ($ids as $key => $id) {
|
||||
if (empty($id) || ((string) $id !== (string) (int) $id)) {
|
||||
unset($ids[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endpatch
|
||||
|
||||
// Revisions are not statically cached, and require a different query to
|
||||
// other conditions, so separate the revision id into its own variable.
|
||||
if ($this->revisionKey && isset($conditions[$this->revisionKey])) {
|
||||
@@ -195,6 +183,11 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure integer entity IDs are valid.
|
||||
if (!empty($ids)) {
|
||||
$this->cleanIds($ids);
|
||||
}
|
||||
|
||||
// Load any remaining entities from the database. This is the case if $ids
|
||||
// is set to FALSE (so we load all entities), if there are any ids left to
|
||||
// load, if loading a revision, or if $conditions was passed without $ids.
|
||||
@@ -235,6 +228,35 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures integer entity IDs are valid.
|
||||
*
|
||||
* The identifier sanitization provided by this method has been introduced
|
||||
* as Drupal used to rely on the database to facilitate this, which worked
|
||||
* correctly with MySQL but led to errors with other DBMS such as PostgreSQL.
|
||||
*
|
||||
* @param array $ids
|
||||
* The entity IDs to verify. Non-integer IDs are removed from this array if
|
||||
* the entity type requires IDs to be integers.
|
||||
*/
|
||||
protected function cleanIds(&$ids) {
|
||||
$entity_info = entity_get_info($this->entityType);
|
||||
if (isset($entity_info['base table field types'])) {
|
||||
$id_type = $entity_info['base table field types'][$this->idKey];
|
||||
if ($id_type == 'serial' || $id_type == 'int') {
|
||||
$ids = array_filter($ids, array($this, 'filterId'));
|
||||
$ids = array_map('intval', $ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for array_filter that removes non-integer IDs.
|
||||
*/
|
||||
protected function filterId($id) {
|
||||
return is_numeric($id) && $id == (int) $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the query to load the entity.
|
||||
*
|
||||
@@ -424,7 +446,7 @@ class EntityFieldQueryException extends Exception {}
|
||||
*
|
||||
* This class allows finding entities based on entity properties (for example,
|
||||
* node->changed), field values, and generic entity meta data (bundle,
|
||||
* entity type, entity id, and revision ID). It is not possible to query across
|
||||
* entity type, entity ID, and revision ID). It is not possible to query across
|
||||
* multiple entity types. For example, there is no facility to find published
|
||||
* nodes written by users created in the last hour, as this would require
|
||||
* querying both node->status and user->created.
|
||||
@@ -666,14 +688,36 @@ class EntityFieldQuery {
|
||||
* @param $field
|
||||
* Either a field name or a field array.
|
||||
* @param $column
|
||||
* The column that should hold the value to be matched.
|
||||
* The column that should hold the value to be matched, defined in the
|
||||
* hook_field_schema() of this field. If this is omitted then all of the
|
||||
* other parameters are ignored, except $field, and this call will just be
|
||||
* adding a condition that says that the field has a value, rather than
|
||||
* testing the value itself.
|
||||
* @param $value
|
||||
* The value to test the column value against.
|
||||
* The value to test the column value against. In most cases, this is a
|
||||
* scalar. For more complex options, it is an array. The meaning of each
|
||||
* element in the array is dependent on $operator.
|
||||
* @param $operator
|
||||
* The operator to be used to test the given value.
|
||||
* The operator to be used to test the given value. The possible values are:
|
||||
* - '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS': These
|
||||
* operators expect $value to be a literal of the same type as the
|
||||
* column.
|
||||
* - 'IN', 'NOT IN': These operators expect $value to be an array of
|
||||
* literals of the same type as the column.
|
||||
* - 'BETWEEN': This operator expects $value to be an array of two literals
|
||||
* of the same type as the column.
|
||||
* The operator can be omitted, and will default to 'IN' if the value is an
|
||||
* array, or to '=' otherwise.
|
||||
* @param $delta_group
|
||||
* An arbitrary identifier: conditions in the same group must have the same
|
||||
* $delta_group.
|
||||
* $delta_group. For example, let's presume a multivalue field which has
|
||||
* two columns, 'color' and 'shape', and for entity ID 1, there are two
|
||||
* values: red/square and blue/circle. Entity ID 1 does not have values
|
||||
* corresponding to 'red circle'; however if you pass 'red' and 'circle' as
|
||||
* conditions, it will appear in the results -- by default queries will run
|
||||
* against any combination of deltas. By passing the conditions with the
|
||||
* same $delta_group it will ensure that only values attached to the same
|
||||
* delta are matched, and entity 1 would then be excluded from the results.
|
||||
* @param $language_group
|
||||
* An arbitrary identifier: conditions in the same group must have the same
|
||||
* $language_group.
|
||||
@@ -748,9 +792,11 @@ class EntityFieldQuery {
|
||||
* @param $field
|
||||
* Either a field name or a field array.
|
||||
* @param $column
|
||||
* A column defined in the hook_field_schema() of this field. If this is
|
||||
* omitted then the query will find only entities that have data in this
|
||||
* field, using the entity and property conditions if there are any.
|
||||
* The column that should hold the value to be matched, defined in the
|
||||
* hook_field_schema() of this field. If this is omitted then all of the
|
||||
* other parameters are ignored, except $field, and this call will just be
|
||||
* adding a condition that says that the field has a value, rather than
|
||||
* testing the value itself.
|
||||
* @param $value
|
||||
* The value to test the column value against. In most cases, this is a
|
||||
* scalar. For more complex options, it is an array. The meaning of each
|
||||
@@ -769,10 +815,10 @@ class EntityFieldQuery {
|
||||
* @param $delta_group
|
||||
* An arbitrary identifier: conditions in the same group must have the same
|
||||
* $delta_group. For example, let's presume a multivalue field which has
|
||||
* two columns, 'color' and 'shape', and for entity id 1, there are two
|
||||
* two columns, 'color' and 'shape', and for entity ID 1, there are two
|
||||
* values: red/square and blue/circle. Entity ID 1 does not have values
|
||||
* corresponding to 'red circle', however if you pass 'red' and 'circle' as
|
||||
* conditions, it will appear in the results - by default queries will run
|
||||
* conditions, it will appear in the results -- by default queries will run
|
||||
* against any combination of deltas. By passing the conditions with the
|
||||
* same $delta_group it will ensure that only values attached to the same
|
||||
* delta are matched, and entity 1 would then be excluded from the results.
|
||||
|
||||
+13
-4
@@ -66,7 +66,7 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c
|
||||
_drupal_log_error(array(
|
||||
'%type' => isset($types[$error_level]) ? $severity_msg : 'Unknown error',
|
||||
// The standard PHP error handler considers that the error messages
|
||||
// are HTML. We mimick this behavior here.
|
||||
// are HTML. We mimic this behavior here.
|
||||
'!message' => filter_xss_admin($message),
|
||||
'%function' => $caller['function'],
|
||||
'%file' => $caller['file'],
|
||||
@@ -114,7 +114,7 @@ function _drupal_decode_exception($exception) {
|
||||
return array(
|
||||
'%type' => get_class($exception),
|
||||
// The standard PHP exception handler considers that the exception message
|
||||
// is plain-text. We mimick this behavior here.
|
||||
// is plain-text. We mimic this behavior here.
|
||||
'!message' => check_plain($message),
|
||||
'%function' => $caller['function'],
|
||||
'%file' => $caller['file'],
|
||||
@@ -199,7 +199,16 @@ function _drupal_log_error($error, $fatal = FALSE) {
|
||||
$number++;
|
||||
}
|
||||
|
||||
watchdog('php', '%type: !message in %function (line %line of %file).', $error, $error['severity_level']);
|
||||
// Log the error immediately, unless this is a non-fatal error which has been
|
||||
// triggered via drupal_trigger_error_with_delayed_logging(); in that case
|
||||
// trigger it in a shutdown function. Fatal errors are always triggered
|
||||
// immediately since for a fatal error the page request will end here anyway.
|
||||
if (!$fatal && drupal_static('_drupal_trigger_error_with_delayed_logging')) {
|
||||
drupal_register_shutdown_function('watchdog', 'php', '%type: !message in %function (line %line of %file).', $error, $error['severity_level']);
|
||||
}
|
||||
else {
|
||||
watchdog('php', '%type: !message in %function (line %line of %file).', $error, $error['severity_level']);
|
||||
}
|
||||
|
||||
if ($fatal) {
|
||||
drupal_add_http_header('Status', '500 Service unavailable (with message)');
|
||||
@@ -224,7 +233,7 @@ function _drupal_log_error($error, $fatal = FALSE) {
|
||||
}
|
||||
else {
|
||||
// Display the message if the current error reporting level allows this type
|
||||
// of message to be displayed, and unconditionnaly in update.php.
|
||||
// of message to be displayed, and unconditionally in update.php.
|
||||
if (error_displayable($error)) {
|
||||
$class = 'error';
|
||||
|
||||
|
||||
+31
-6
@@ -273,7 +273,9 @@ function file_default_scheme() {
|
||||
* The normalized URI.
|
||||
*/
|
||||
function file_stream_wrapper_uri_normalize($uri) {
|
||||
$scheme = file_uri_scheme($uri);
|
||||
// Inline file_uri_scheme() function call for performance reasons.
|
||||
$position = strpos($uri, '://');
|
||||
$scheme = $position ? substr($uri, 0, $position) : FALSE;
|
||||
|
||||
if ($scheme && file_stream_wrapper_valid_scheme($scheme)) {
|
||||
$target = file_uri_target($uri);
|
||||
@@ -533,7 +535,18 @@ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
|
||||
EOF;
|
||||
|
||||
if ($private) {
|
||||
$lines = "Deny from all\n\n" . $lines;
|
||||
$lines = <<<EOF
|
||||
# Deny all requests from Apache 2.4+.
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
# Deny all requests from Apache 2.0-2.2.
|
||||
<IfModule !mod_authz_core.c>
|
||||
Deny from all
|
||||
</IfModule>
|
||||
EOF
|
||||
. "\n\n" . $lines;
|
||||
}
|
||||
|
||||
return $lines;
|
||||
@@ -887,7 +900,6 @@ function file_valid_uri($uri) {
|
||||
*/
|
||||
function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
|
||||
$original_source = $source;
|
||||
$original_destination = $destination;
|
||||
|
||||
// Assert that the source file actually exists.
|
||||
if (!file_exists($source)) {
|
||||
@@ -1602,6 +1614,20 @@ function file_save_upload($form_field_name, $validators = array(), $destination
|
||||
|
||||
// If we made it this far it's safe to record this file in the database.
|
||||
if ($file = file_save($file)) {
|
||||
// Track non-public files in the session if they were uploaded by an
|
||||
// anonymous user. This allows modules such as the File module to only
|
||||
// grant view access to the specific anonymous user who uploaded the file.
|
||||
// See file_file_download().
|
||||
// The 'file_public_schema' variable is used to allow other publicly
|
||||
// accessible file schemes to be treated the same as the public:// scheme
|
||||
// provided by Drupal core and to avoid adding unnecessary data to the
|
||||
// session (and the resulting bypass of the page cache) in those cases. For
|
||||
// security reasons, only schemes that are completely publicly accessible,
|
||||
// with no download restrictions, should be added to this variable. See
|
||||
// file_managed_file_value().
|
||||
if (!$user->uid && !in_array($destination_scheme, variable_get('file_public_schema', array('public')))) {
|
||||
$_SESSION['anonymous_allowed_file_ids'][$file->fid] = $file->fid;
|
||||
}
|
||||
// Add file to the cache.
|
||||
$upload_cache[$form_field_name] = $file;
|
||||
return $file;
|
||||
@@ -1785,7 +1811,7 @@ function file_validate_is_image(stdClass $file) {
|
||||
/**
|
||||
* Verifies that image dimensions are within the specified maximum and minimum.
|
||||
*
|
||||
* Non-image files will be ignored. If a image toolkit is available the image
|
||||
* Non-image files will be ignored. If an image toolkit is available the image
|
||||
* will be scaled to fit within the desired maximum dimensions.
|
||||
*
|
||||
* @param $file
|
||||
@@ -2022,7 +2048,7 @@ function file_download() {
|
||||
*
|
||||
* @see file_transfer()
|
||||
* @see file_download_access()
|
||||
* @see hook_file_downlaod()
|
||||
* @see hook_file_download()
|
||||
*/
|
||||
function file_download_headers($uri) {
|
||||
// Let other modules provide headers and control access to the file.
|
||||
@@ -2551,7 +2577,6 @@ function file_directory_temp() {
|
||||
* An associative array of headers, as expected by file_transfer().
|
||||
*/
|
||||
function file_get_content_headers($file) {
|
||||
$name = mime_header_encode($file->filename);
|
||||
$type = mime_header_encode($file->filemime);
|
||||
|
||||
return array(
|
||||
|
||||
+109
-24
@@ -105,7 +105,8 @@
|
||||
* generate the same form (or very similar forms) using different $form_ids
|
||||
* can implement hook_forms(), which maps different $form_id values to the
|
||||
* proper form constructor function. Examples may be found in node_forms(),
|
||||
* and search_forms().
|
||||
* and search_forms(). hook_forms() can also be used to define forms in
|
||||
* classes.
|
||||
* @param ...
|
||||
* Any additional arguments are passed on to the functions called by
|
||||
* drupal_get_form(), including the unique form constructor function. For
|
||||
@@ -809,7 +810,7 @@ function drupal_retrieve_form($form_id, &$form_state) {
|
||||
}
|
||||
if (isset($form_definition['callback'])) {
|
||||
$callback = $form_definition['callback'];
|
||||
$form_state['build_info']['base_form_id'] = $callback;
|
||||
$form_state['build_info']['base_form_id'] = isset($form_definition['base_form_id']) ? $form_definition['base_form_id'] : $callback;
|
||||
}
|
||||
// In case $form_state['wrapper_callback'] is not defined already, we also
|
||||
// allow hook_forms() to define one.
|
||||
@@ -830,7 +831,7 @@ function drupal_retrieve_form($form_id, &$form_state) {
|
||||
// the actual form builder function ($callback) expects. This allows for
|
||||
// pre-populating a form with common elements for certain forms, such as
|
||||
// back/next/save buttons in multi-step form wizards. See drupal_build_form().
|
||||
if (isset($form_state['wrapper_callback']) && function_exists($form_state['wrapper_callback'])) {
|
||||
if (isset($form_state['wrapper_callback']) && is_callable($form_state['wrapper_callback'])) {
|
||||
$form = call_user_func_array($form_state['wrapper_callback'], $args);
|
||||
// Put the prepopulated $form into $args.
|
||||
$args[0] = $form;
|
||||
@@ -1128,6 +1129,17 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
|
||||
drupal_alter($hooks, $form, $form_state, $form_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to call form_set_error() if there is a token error.
|
||||
*/
|
||||
function _drupal_invalid_token_set_form_error() {
|
||||
$path = current_path();
|
||||
$query = drupal_get_query_parameters();
|
||||
$url = url($path, array('query' => $query));
|
||||
|
||||
// Setting this error will cause the form to fail validation.
|
||||
form_set_error('form_token', t('The form has become outdated. Copy any unsaved work in the form below and then <a href="@link">reload this page</a>.', array('@link' => $url)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates user-submitted form data in the $form_state array.
|
||||
@@ -1162,16 +1174,11 @@ function drupal_validate_form($form_id, &$form, &$form_state) {
|
||||
}
|
||||
|
||||
// If the session token was set by drupal_prepare_form(), ensure that it
|
||||
// matches the current user's session.
|
||||
if (isset($form['#token'])) {
|
||||
if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
|
||||
$path = current_path();
|
||||
$query = drupal_get_query_parameters();
|
||||
$url = url($path, array('query' => $query));
|
||||
|
||||
// Setting this error will cause the form to fail validation.
|
||||
form_set_error('form_token', t('The form has become outdated. Copy any unsaved work in the form below and then <a href="@link">reload this page</a>.', array('@link' => $url)));
|
||||
|
||||
// matches the current user's session. This is duplicate to code in
|
||||
// form_builder() but left to protect any custom form handling code.
|
||||
if (!empty($form['#token'])) {
|
||||
if (!drupal_valid_token($form_state['values']['form_token'], $form['#token']) || !empty($form_state['invalid_token'])) {
|
||||
_drupal_invalid_token_set_form_error();
|
||||
// Stop here and don't run any further validation handlers, because they
|
||||
// could invoke non-safe operations which opens the door for CSRF
|
||||
// vulnerabilities.
|
||||
@@ -1827,6 +1834,20 @@ function form_builder($form_id, &$element, &$form_state) {
|
||||
// from the POST data is set and matches the current form_id.
|
||||
if ($form_state['programmed'] || (!empty($form_state['input']) && (isset($form_state['input']['form_id']) && ($form_state['input']['form_id'] == $form_id)))) {
|
||||
$form_state['process_input'] = TRUE;
|
||||
// If the session token was set by drupal_prepare_form(), ensure that it
|
||||
// matches the current user's session.
|
||||
$form_state['invalid_token'] = FALSE;
|
||||
if (!empty($element['#token'])) {
|
||||
if (empty($form_state['input']['form_token']) || !drupal_valid_token($form_state['input']['form_token'], $element['#token'])) {
|
||||
// Set an early form error to block certain input processing since that
|
||||
// opens the door for CSRF vulnerabilities.
|
||||
_drupal_invalid_token_set_form_error();
|
||||
// This value is checked in _form_builder_handle_input_element().
|
||||
$form_state['invalid_token'] = TRUE;
|
||||
// Make sure file uploads do not get processed.
|
||||
$_FILES = array();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$form_state['process_input'] = FALSE;
|
||||
@@ -1930,6 +1951,18 @@ function form_builder($form_id, &$element, &$form_state) {
|
||||
$element['#attributes']['enctype'] = 'multipart/form-data';
|
||||
}
|
||||
|
||||
// Allow Ajax submissions to the form action to bypass verification. This is
|
||||
// especially useful for multipart forms, which cannot be verified via a
|
||||
// response header.
|
||||
$element['#attached']['js'][] = array(
|
||||
'type' => 'setting',
|
||||
'data' => array(
|
||||
'urlIsAjaxTrusted' => array(
|
||||
$element['#action'] => TRUE,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// If a form contains a single textfield, and the ENTER key is pressed
|
||||
// within it, Internet Explorer submits the form with no POST data
|
||||
// identifying any submit button. Other browsers submit POST data as though
|
||||
@@ -1978,6 +2011,19 @@ function form_builder($form_id, &$element, &$form_state) {
|
||||
* Adds the #name and #value properties of an input element before rendering.
|
||||
*/
|
||||
function _form_builder_handle_input_element($form_id, &$element, &$form_state) {
|
||||
static $safe_core_value_callbacks = array(
|
||||
'form_type_token_value',
|
||||
'form_type_textarea_value',
|
||||
'form_type_textfield_value',
|
||||
'form_type_checkbox_value',
|
||||
'form_type_checkboxes_value',
|
||||
'form_type_radios_value',
|
||||
'form_type_password_confirm_value',
|
||||
'form_type_select_value',
|
||||
'form_type_tableselect_value',
|
||||
'list_boolean_allowed_values_callback',
|
||||
);
|
||||
|
||||
if (!isset($element['#name'])) {
|
||||
$name = array_shift($element['#parents']);
|
||||
$element['#name'] = $name;
|
||||
@@ -2056,7 +2102,14 @@ function _form_builder_handle_input_element($form_id, &$element, &$form_state) {
|
||||
// property, optionally filtered through $value_callback.
|
||||
if ($input_exists) {
|
||||
if (function_exists($value_callback)) {
|
||||
$element['#value'] = $value_callback($element, $input, $form_state);
|
||||
// Skip all value callbacks except safe ones like text if the CSRF
|
||||
// token was invalid.
|
||||
if (empty($form_state['invalid_token']) || in_array($value_callback, $safe_core_value_callbacks)) {
|
||||
$element['#value'] = $value_callback($element, $input, $form_state);
|
||||
}
|
||||
else {
|
||||
$input = NULL;
|
||||
}
|
||||
}
|
||||
if (!isset($element['#value']) && isset($input)) {
|
||||
$element['#value'] = $input;
|
||||
@@ -2519,7 +2572,7 @@ function form_type_select_value($element, $input = FALSE) {
|
||||
* for this element. Return nothing to use the default.
|
||||
*/
|
||||
function form_type_textarea_value($element, $input = FALSE) {
|
||||
if ($input !== FALSE) {
|
||||
if ($input !== FALSE && $input !== NULL) {
|
||||
// This should be a string, but allow other scalars since they might be
|
||||
// valid input in programmatic form submissions.
|
||||
return is_scalar($input) ? (string) $input : '';
|
||||
@@ -2662,8 +2715,8 @@ function _form_options_flatten($array) {
|
||||
* - #required: (optional) Whether the user needs to select an option (TRUE)
|
||||
* or not (FALSE). Defaults to FALSE.
|
||||
* - #empty_option: (optional) The label to show for the first default option.
|
||||
* By default, the label is automatically set to "- Please select -" for a
|
||||
* required field and "- None -" for an optional field.
|
||||
* By default, the label is automatically set to "- Select -" for a required
|
||||
* field and "- None -" for an optional field.
|
||||
* - #empty_value: (optional) The value for the first default option, which is
|
||||
* used to determine whether the user submitted a value or not.
|
||||
* - If #required is TRUE, this defaults to '' (an empty string).
|
||||
@@ -2976,7 +3029,7 @@ function form_process_password_confirm($element) {
|
||||
function password_confirm_validate($element, &$element_state) {
|
||||
$pass1 = trim($element['pass1']['#value']);
|
||||
$pass2 = trim($element['pass2']['#value']);
|
||||
if (!empty($pass1) || !empty($pass2)) {
|
||||
if (strlen($pass1) > 0 || strlen($pass2) > 0) {
|
||||
if (strcmp($pass1, $pass2)) {
|
||||
form_error($element, t('The specified passwords do not match.'));
|
||||
}
|
||||
@@ -3333,9 +3386,12 @@ function form_process_container($element, &$form_state) {
|
||||
/**
|
||||
* Returns HTML to wrap child elements in a container.
|
||||
*
|
||||
* Used for grouped form items. Can also be used as a #theme_wrapper for any
|
||||
* Used for grouped form items. Can also be used as a theme wrapper for any
|
||||
* renderable element, to surround it with a <div> and add attributes such as
|
||||
* classes or an HTML id.
|
||||
* classes or an HTML ID.
|
||||
*
|
||||
* See the @link forms_api_reference.html Form API reference @endlink for more
|
||||
* information on the #theme_wrappers render array property.
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
@@ -3490,6 +3546,7 @@ function form_process_tableselect($element) {
|
||||
'#return_value' => $key,
|
||||
'#default_value' => isset($value[$key]) ? $key : NULL,
|
||||
'#attributes' => $element['#attributes'],
|
||||
'#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -3910,6 +3967,34 @@ function theme_hidden($variables) {
|
||||
return '<input' . drupal_attributes($element['#attributes']) . " />\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Process function to prepare autocomplete data.
|
||||
*
|
||||
* @param $element
|
||||
* A textfield or other element with a #autocomplete_path.
|
||||
*
|
||||
* @return array
|
||||
* The processed form element.
|
||||
*/
|
||||
function form_process_autocomplete($element) {
|
||||
$element['#autocomplete_input'] = array();
|
||||
if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
|
||||
$element['#autocomplete_input']['#id'] = $element['#id'] .'-autocomplete';
|
||||
// Force autocomplete to use non-clean URLs since this protects against the
|
||||
// browser interpreting the path plus search string as an actual file.
|
||||
$current_clean_url = isset($GLOBALS['conf']['clean_url']) ? $GLOBALS['conf']['clean_url'] : NULL;
|
||||
$GLOBALS['conf']['clean_url'] = 0;
|
||||
// Force the script path to 'index.php', in case the server is not
|
||||
// configured to find it automatically. Normally it is the responsibility
|
||||
// of the site to do this themselves using hook_url_outbound_alter() (see
|
||||
// url()) but since this code is forcing non-clean URLs on sites that don't
|
||||
// normally use them, it is done here instead.
|
||||
$element['#autocomplete_input']['#url_value'] = url($element['#autocomplete_path'], array('absolute' => TRUE, 'script' => 'index.php'));
|
||||
$GLOBALS['conf']['clean_url'] = $current_clean_url;
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for a textfield form element.
|
||||
*
|
||||
@@ -3928,14 +4013,14 @@ function theme_textfield($variables) {
|
||||
_form_set_class($element, array('form-text'));
|
||||
|
||||
$extra = '';
|
||||
if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
|
||||
if ($element['#autocomplete_path'] && !empty($element['#autocomplete_input'])) {
|
||||
drupal_add_library('system', 'drupal.autocomplete');
|
||||
$element['#attributes']['class'][] = 'form-autocomplete';
|
||||
|
||||
$attributes = array();
|
||||
$attributes['type'] = 'hidden';
|
||||
$attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
|
||||
$attributes['value'] = url($element['#autocomplete_path'], array('absolute' => TRUE));
|
||||
$attributes['id'] = $element['#autocomplete_input']['#id'];
|
||||
$attributes['value'] = $element['#autocomplete_input']['#url_value'];
|
||||
$attributes['disabled'] = 'disabled';
|
||||
$attributes['class'][] = 'autocomplete';
|
||||
$extra = '<input' . drupal_attributes($attributes) . ' />';
|
||||
@@ -4409,7 +4494,7 @@ function element_validate_number($element, &$form_state) {
|
||||
*
|
||||
* Sample callback_batch_finished():
|
||||
* @code
|
||||
* function batch_test_finished($success, $results, $operations) {
|
||||
* function my_finished_callback($success, $results, $operations) {
|
||||
* // The 'success' parameter means no fatal PHP errors were detected. All
|
||||
* // other error management should be handled using 'results'.
|
||||
* if ($success) {
|
||||
|
||||
@@ -362,7 +362,8 @@ function install_run_tasks(&$install_state) {
|
||||
* Runs an individual installation task.
|
||||
*
|
||||
* @param $task
|
||||
* An array of information about the task to be run.
|
||||
* An array of information about the task to be run as returned by
|
||||
* hook_install_tasks().
|
||||
* @param $install_state
|
||||
* An array of information about the current installation state. This is
|
||||
* passed in by reference so that it can be modified by the task.
|
||||
@@ -478,11 +479,15 @@ function install_run_task($task, &$install_state) {
|
||||
* the page request evolves (for example, if an installation profile hasn't
|
||||
* been selected yet, we don't yet know which profile tasks need to be run).
|
||||
*
|
||||
* You can override this using hook_install_tasks() or
|
||||
* hook_install_tasks_alter().
|
||||
*
|
||||
* @param $install_state
|
||||
* An array of information about the current installation state.
|
||||
*
|
||||
* @return
|
||||
* A list of tasks to be performed, with associated metadata.
|
||||
* A list of tasks to be performed, with associated metadata as returned by
|
||||
* hook_install_tasks().
|
||||
*/
|
||||
function install_tasks_to_perform($install_state) {
|
||||
// Start with a list of all currently available tasks.
|
||||
@@ -804,6 +809,13 @@ function install_system_module(&$install_state) {
|
||||
|
||||
variable_set('install_profile_modules', array_diff($modules, array('system')));
|
||||
$install_state['database_tables_exist'] = TRUE;
|
||||
|
||||
// Prevent the hook_requirements() check from telling us to convert the
|
||||
// database to utf8mb4.
|
||||
$connection = Database::getConnection();
|
||||
if ($connection->utf8mb4IsConfigurable() && $connection->utf8mb4IsActive()) {
|
||||
variable_set('drupal_all_databases_are_utf8mb4', TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1585,7 +1597,9 @@ function install_finished(&$install_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch callback for batch installation of modules.
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Performs batch installation of modules.
|
||||
*/
|
||||
function _install_module_batch($module, $module_name, &$context) {
|
||||
// Install and enable the module right away, so that the module will be
|
||||
@@ -1598,6 +1612,8 @@ function _install_module_batch($module, $module_name, &$context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* 'Finished' callback for module installation batch.
|
||||
*/
|
||||
function _install_profile_modules_finished($success, $results, $operations) {
|
||||
|
||||
@@ -750,7 +750,7 @@ function drupal_install_system() {
|
||||
/**
|
||||
* Uninstalls a given list of disabled modules.
|
||||
*
|
||||
* @param array $module_list
|
||||
* @param string[] $module_list
|
||||
* The modules to uninstall. It is the caller's responsibility to ensure that
|
||||
* all modules in this list have already been disabled before this function
|
||||
* is called.
|
||||
@@ -769,6 +769,7 @@ function drupal_install_system() {
|
||||
* included in $module_list).
|
||||
*
|
||||
* @see module_disable()
|
||||
* @see module_enable()
|
||||
*/
|
||||
function drupal_uninstall_modules($module_list = array(), $uninstall_dependents = TRUE) {
|
||||
if ($uninstall_dependents) {
|
||||
|
||||
+48
-3
@@ -435,6 +435,13 @@ function locale_language_url_rewrite_url(&$path, &$options) {
|
||||
switch (variable_get('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX)) {
|
||||
case LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN:
|
||||
if ($options['language']->domain) {
|
||||
// Save the original base URL. If it contains a port, we need to
|
||||
// retain it below.
|
||||
if (!empty($options['base_url'])) {
|
||||
// The colon in the URL scheme messes up the port checking below.
|
||||
$normalized_base_url = str_replace(array('https://', 'http://'), '', $options['base_url']);
|
||||
}
|
||||
|
||||
// Ask for an absolute URL with our modified base_url.
|
||||
global $is_https;
|
||||
$url_scheme = ($is_https) ? 'https://' : 'http://';
|
||||
@@ -449,6 +456,19 @@ function locale_language_url_rewrite_url(&$path, &$options) {
|
||||
|
||||
// Apply the appropriate protocol to the URL.
|
||||
$options['base_url'] = $url_scheme . $host;
|
||||
|
||||
// In case either the original base URL or the HTTP host contains a
|
||||
// port, retain it.
|
||||
$http_host = $_SERVER['HTTP_HOST'];
|
||||
if (isset($normalized_base_url) && strpos($normalized_base_url, ':') !== FALSE) {
|
||||
list($host, $port) = explode(':', $normalized_base_url);
|
||||
$options['base_url'] .= ':' . $port;
|
||||
}
|
||||
elseif (strpos($http_host, ':') !== FALSE) {
|
||||
list($host, $port) = explode(':', $http_host);
|
||||
$options['base_url'] .= ':' . $port;
|
||||
}
|
||||
|
||||
if (isset($options['https']) && variable_get('https', FALSE)) {
|
||||
if ($options['https'] === TRUE) {
|
||||
$options['base_url'] = str_replace('http://', 'https://', $options['base_url']);
|
||||
@@ -523,6 +543,22 @@ function locale_language_url_rewrite_session(&$path, &$options) {
|
||||
* possible attack vector (img).
|
||||
*/
|
||||
function locale_string_is_safe($string) {
|
||||
// Some strings have tokens in them. For tokens in the first part of href or
|
||||
// src HTML attributes, filter_xss() removes part of the token, the part
|
||||
// before the first colon. filter_xss() assumes it could be an attempt to
|
||||
// inject javascript. When filter_xss() removes part of tokens, it causes the
|
||||
// string to not be translatable when it should be translatable. See
|
||||
// LocaleStringIsSafeTest::testLocaleStringIsSafe().
|
||||
//
|
||||
// We can recognize tokens since they are wrapped with brackets and are only
|
||||
// composed of alphanumeric characters, colon, underscore, and dashes. We can
|
||||
// be sure these strings are safe to strip out before the string is checked in
|
||||
// filter_xss() because no dangerous javascript will match that pattern.
|
||||
//
|
||||
// @todo Do not strip out the token. Fix filter_xss() to not incorrectly
|
||||
// alter the string. https://www.drupal.org/node/2372127
|
||||
$string = preg_replace('/\[[a-z0-9_-]+(:[a-z0-9_-]+)+\]/i', '', $string);
|
||||
|
||||
return decode_entities($string) == decode_entities(filter_xss($string, array('a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'ins', 'kbd', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var')));
|
||||
}
|
||||
|
||||
@@ -631,9 +667,6 @@ function locale_add_language($langcode, $name = NULL, $native = NULL, $direction
|
||||
* translations).
|
||||
*/
|
||||
function _locale_import_po($file, $langcode, $mode, $group = NULL) {
|
||||
// Try to allocate enough time to parse and import the data.
|
||||
drupal_set_time_limit(240);
|
||||
|
||||
// Check if we have the language already in the database.
|
||||
if (!db_query("SELECT COUNT(language) FROM {languages} WHERE language = :language", array(':language' => $langcode))->fetchField()) {
|
||||
drupal_set_message(t('The language selected for import is not supported.'), 'error');
|
||||
@@ -717,6 +750,12 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
|
||||
$lineno = 0;
|
||||
|
||||
while (!feof($fd)) {
|
||||
// Refresh the time limit every 10 parsed rows to ensure there is always
|
||||
// enough time to import the data for large PO files.
|
||||
if (!($lineno % 10)) {
|
||||
drupal_set_time_limit(30);
|
||||
}
|
||||
|
||||
// A line should not be longer than 10 * 1024.
|
||||
$line = fgets($fd, 10 * 1024);
|
||||
|
||||
@@ -2306,6 +2345,8 @@ function _locale_batch_build($files, $finished = NULL, $components = array()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Perform interface translation import as a batch step.
|
||||
*
|
||||
* @param $filepath
|
||||
@@ -2324,6 +2365,8 @@ function _locale_batch_import($filepath, &$context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Finished callback of system page locale import batch.
|
||||
* Inform the user of translation files imported.
|
||||
*/
|
||||
@@ -2334,6 +2377,8 @@ function _locale_batch_system_finished($success, $results) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Finished callback of language addition locale import batch.
|
||||
* Inform the user of translation files imported.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -566,7 +566,7 @@ function _drupal_wrap_mail_line(&$line, $key, $values) {
|
||||
// Use soft-breaks only for purely quoted or unindented text.
|
||||
$line = wordwrap($line, 77 - $values['length'], $values['soft'] ? " \n" : "\n");
|
||||
// Break really long words at the maximum width allowed.
|
||||
$line = wordwrap($line, 996 - $values['length'], $values['soft'] ? " \n" : "\n");
|
||||
$line = wordwrap($line, 996 - $values['length'], $values['soft'] ? " \n" : "\n", TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+37
-8
@@ -229,12 +229,20 @@ define('MENU_CONTEXT_INLINE', 0x0002);
|
||||
define('MENU_FOUND', 1);
|
||||
|
||||
/**
|
||||
* Internal menu status code -- Menu item was not found.
|
||||
* Menu status code -- Not found.
|
||||
*
|
||||
* This can be used as the return value from a page callback, although it is
|
||||
* preferable to use a load function to accomplish this; see the hook_menu()
|
||||
* documentation for details.
|
||||
*/
|
||||
define('MENU_NOT_FOUND', 2);
|
||||
|
||||
/**
|
||||
* Internal menu status code -- Menu item access is denied.
|
||||
* Menu status code -- Access denied.
|
||||
*
|
||||
* This can be used as the return value from a page callback, although it is
|
||||
* preferable to use an access callback to accomplish this; see the hook_menu()
|
||||
* documentation for details.
|
||||
*/
|
||||
define('MENU_ACCESS_DENIED', 3);
|
||||
|
||||
@@ -431,7 +439,7 @@ function menu_set_item($path, $router_item) {
|
||||
*
|
||||
* @param $path
|
||||
* The path; for example, 'node/5'. The function will find the corresponding
|
||||
* node/% item and return that.
|
||||
* node/% item and return that. Defaults to the current path.
|
||||
* @param $router_item
|
||||
* Internal use only.
|
||||
*
|
||||
@@ -1487,7 +1495,7 @@ function menu_tree_collect_node_links(&$tree, &$node_links) {
|
||||
* menu_tree_collect_node_links().
|
||||
*/
|
||||
function menu_tree_check_access(&$tree, $node_links = array()) {
|
||||
if ($node_links) {
|
||||
if ($node_links && (user_access('access content') || user_access('bypass node access'))) {
|
||||
$nids = array_keys($node_links);
|
||||
$select = db_select('node', 'n');
|
||||
$select->addField('n', 'nid');
|
||||
@@ -1598,6 +1606,7 @@ function _menu_tree_data(&$links, $parents, $depth) {
|
||||
* Implements template_preprocess_HOOK() for theme_menu_tree().
|
||||
*/
|
||||
function template_preprocess_menu_tree(&$variables) {
|
||||
$variables['#tree'] = $variables['tree'];
|
||||
$variables['tree'] = $variables['tree']['#children'];
|
||||
}
|
||||
|
||||
@@ -2411,7 +2420,7 @@ function menu_set_active_trail($new_trail = NULL) {
|
||||
// argument placeholders (%). Such links are not contained in regular
|
||||
// menu trees, and have only been loaded for the additional
|
||||
// translation that happens here, so as to be able to display them in
|
||||
// the breadcumb for the current page.
|
||||
// the breadcrumb for the current page.
|
||||
// @see _menu_tree_check_access()
|
||||
// @see _menu_link_translate()
|
||||
if (strpos($link['href'], '%') !== FALSE) {
|
||||
@@ -2613,10 +2622,30 @@ function menu_get_active_breadcrumb() {
|
||||
*/
|
||||
function menu_get_active_title() {
|
||||
$active_trail = menu_get_active_trail();
|
||||
$local_task_title = NULL;
|
||||
|
||||
foreach (array_reverse($active_trail) as $item) {
|
||||
if (!(bool) ($item['type'] & MENU_IS_LOCAL_TASK)) {
|
||||
return $item['title'];
|
||||
// Local task titles are displayed as tabs and therefore should not be
|
||||
// repeated as the page title. However, if the local task appears in a
|
||||
// top-level menu, it is no longer a "local task" anymore (the front page
|
||||
// of the site does not have tabs) so it is better to use the local task
|
||||
// title in that case than to fall back on the front page link in the
|
||||
// active trail (which is usually "Home" and would not make sense in this
|
||||
// context).
|
||||
if ((bool) ($item['type'] & MENU_IS_LOCAL_TASK)) {
|
||||
// A local task title is being skipped; track it in case it needs to be
|
||||
// used later.
|
||||
$local_task_title = $item['title'];
|
||||
}
|
||||
else {
|
||||
// This is not a local task, so use it for the page title (unless the
|
||||
// conditions described above are met).
|
||||
if (isset($local_task_title) && isset($item['href']) && $item['href'] == '<front>') {
|
||||
return $local_task_title;
|
||||
}
|
||||
else {
|
||||
return $item['title'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2654,7 +2683,7 @@ function menu_link_load($mlid) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cached cached data for a single named menu.
|
||||
* Clears the cached data for a single named menu.
|
||||
*/
|
||||
function menu_cache_clear($menu_name = 'navigation') {
|
||||
$cache_cleared = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
+73
-11
@@ -227,6 +227,10 @@ function system_list_reset() {
|
||||
drupal_static_reset('list_themes');
|
||||
cache_clear_all('bootstrap_modules', 'cache_bootstrap');
|
||||
cache_clear_all('system_list', 'cache_bootstrap');
|
||||
|
||||
// Clean up the bootstrap file scan cache.
|
||||
drupal_static_reset('_drupal_file_scan_cache');
|
||||
cache_clear_all('_drupal_file_scan_cache', 'cache_bootstrap');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -320,16 +324,27 @@ function module_load_install($module) {
|
||||
* The name of the included file, if successful; FALSE otherwise.
|
||||
*/
|
||||
function module_load_include($type, $module, $name = NULL) {
|
||||
static $files = array();
|
||||
|
||||
if (!isset($name)) {
|
||||
$name = $module;
|
||||
}
|
||||
|
||||
$key = $type . ':' . $module . ':' . $name;
|
||||
if (isset($files[$key])) {
|
||||
return $files[$key];
|
||||
}
|
||||
|
||||
if (function_exists('drupal_get_path')) {
|
||||
$file = DRUPAL_ROOT . '/' . drupal_get_path('module', $module) . "/$name.$type";
|
||||
if (is_file($file)) {
|
||||
require_once $file;
|
||||
$files[$key] = $file;
|
||||
return $file;
|
||||
}
|
||||
else {
|
||||
$files[$key] = FALSE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -365,20 +380,22 @@ function module_load_all_includes($type, $name = NULL) {
|
||||
* - Invoke hook_modules_installed().
|
||||
* - Invoke hook_modules_enabled().
|
||||
*
|
||||
* @param $module_list
|
||||
* @param string[] $module_list
|
||||
* An array of module names.
|
||||
* @param $enable_dependencies
|
||||
* @param bool $enable_dependencies
|
||||
* If TRUE, dependencies will automatically be added and enabled in the
|
||||
* correct order. This incurs a significant performance cost, so use FALSE
|
||||
* if you know $module_list is already complete and in the correct order.
|
||||
*
|
||||
* @return
|
||||
* @return bool
|
||||
* FALSE if one or more dependencies are missing, TRUE otherwise.
|
||||
*
|
||||
* @see hook_install()
|
||||
* @see hook_enable()
|
||||
* @see hook_modules_installed()
|
||||
* @see hook_modules_enabled()
|
||||
* @see module_disable()
|
||||
* @see drupal_uninstall_modules()
|
||||
*/
|
||||
function module_enable($module_list, $enable_dependencies = TRUE) {
|
||||
if ($enable_dependencies) {
|
||||
@@ -505,12 +522,15 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
|
||||
/**
|
||||
* Disables a given set of modules.
|
||||
*
|
||||
* @param $module_list
|
||||
* @param string[] $module_list
|
||||
* An array of module names.
|
||||
* @param $disable_dependents
|
||||
* @param bool $disable_dependents
|
||||
* If TRUE, dependent modules will automatically be added and disabled in the
|
||||
* correct order. This incurs a significant performance cost, so use FALSE
|
||||
* if you know $module_list is already complete and in the correct order.
|
||||
*
|
||||
* @see drupal_uninstall_modules()
|
||||
* @see module_enable()
|
||||
*/
|
||||
function module_disable($module_list, $disable_dependents = TRUE) {
|
||||
if ($disable_dependents) {
|
||||
@@ -676,12 +696,16 @@ function module_hook($module, $hook) {
|
||||
/**
|
||||
* Determines which modules are implementing a hook.
|
||||
*
|
||||
* @param $hook
|
||||
* Lazy-loaded include files specified with "group" via hook_hook_info() or
|
||||
* hook_module_implements_alter() will be automatically included by this
|
||||
* function when necessary.
|
||||
*
|
||||
* @param string $hook
|
||||
* The name of the hook (e.g. "help" or "menu").
|
||||
* @param $sort
|
||||
* @param bool $sort
|
||||
* By default, modules are ordered by weight and filename, settings this option
|
||||
* to TRUE, module list will be ordered by module name.
|
||||
* @param $reset
|
||||
* @param bool $reset
|
||||
* For internal use only: Whether to force the stored list of hook
|
||||
* implementations to be regenerated (such as after enabling a new module,
|
||||
* before processing hook_enable).
|
||||
@@ -696,8 +720,10 @@ function module_implements($hook, $sort = FALSE, $reset = FALSE) {
|
||||
static $drupal_static_fast;
|
||||
if (!isset($drupal_static_fast)) {
|
||||
$drupal_static_fast['implementations'] = &drupal_static(__FUNCTION__);
|
||||
$drupal_static_fast['verified'] = &drupal_static(__FUNCTION__ . ':verified');
|
||||
}
|
||||
$implementations = &$drupal_static_fast['implementations'];
|
||||
$verified = &$drupal_static_fast['verified'];
|
||||
|
||||
// We maintain a persistent cache of hook implementations in addition to the
|
||||
// static cache to avoid looping through every module and every hook on each
|
||||
@@ -711,14 +737,19 @@ function module_implements($hook, $sort = FALSE, $reset = FALSE) {
|
||||
// per request.
|
||||
if ($reset) {
|
||||
$implementations = array();
|
||||
$verified = array();
|
||||
cache_set('module_implements', array(), 'cache_bootstrap');
|
||||
drupal_static_reset('module_hook_info');
|
||||
drupal_static_reset('drupal_alter');
|
||||
cache_clear_all('hook_info', 'cache_bootstrap');
|
||||
cache_clear_all('system_cache_tables', 'cache');
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch implementations from cache.
|
||||
// This happens on the first call to module_implements(*, *, FALSE) during a
|
||||
// request, but also when $implementations have been reset, e.g. after
|
||||
// module_enable().
|
||||
if (empty($implementations)) {
|
||||
$implementations = cache_get('module_implements', 'cache_bootstrap');
|
||||
if ($implementations === FALSE) {
|
||||
@@ -727,12 +758,17 @@ function module_implements($hook, $sort = FALSE, $reset = FALSE) {
|
||||
else {
|
||||
$implementations = $implementations->data;
|
||||
}
|
||||
// Forget all previously "verified" hooks, in case that $implementations
|
||||
// were cleared via drupal_static_reset('module_implements') instead of
|
||||
// module_implements(*, *, TRUE).
|
||||
$verified = array();
|
||||
}
|
||||
|
||||
if (!isset($implementations[$hook])) {
|
||||
// The hook is not cached, so ensure that whether or not it has
|
||||
// implementations, that the cache is updated at the end of the request.
|
||||
$implementations['#write_cache'] = TRUE;
|
||||
// Discover implementations for this hook.
|
||||
$hook_info = module_hook_info();
|
||||
$implementations[$hook] = array();
|
||||
$list = module_list(FALSE, FALSE, $sort);
|
||||
@@ -744,13 +780,31 @@ function module_implements($hook, $sort = FALSE, $reset = FALSE) {
|
||||
$implementations[$hook][$module] = $include_file ? $hook_info[$hook]['group'] : FALSE;
|
||||
}
|
||||
}
|
||||
// Allow modules to change the weight of specific implementations but avoid
|
||||
// Allow modules to change the weight of specific implementations, but avoid
|
||||
// an infinite loop.
|
||||
if ($hook != 'module_implements_alter') {
|
||||
// Remember the implementations before hook_module_implements_alter().
|
||||
$implementations_before = $implementations[$hook];
|
||||
drupal_alter('module_implements', $implementations[$hook], $hook);
|
||||
// Verify implementations that were added or modified.
|
||||
foreach (array_diff_assoc($implementations[$hook], $implementations_before) as $module => $group) {
|
||||
// If drupal_alter('module_implements') changed or added a $group, the
|
||||
// respective file needs to be included.
|
||||
if ($group) {
|
||||
module_load_include('inc', $module, "$module.$group");
|
||||
}
|
||||
// If a new implementation was added, verify that the function exists.
|
||||
if (!function_exists($module . '_' . $hook)) {
|
||||
unset($implementations[$hook][$module]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Implementations for this hook are now "verified".
|
||||
$verified[$hook] = TRUE;
|
||||
}
|
||||
else {
|
||||
elseif (!isset($verified[$hook])) {
|
||||
// Implementations for this hook were in the cache, but they are not
|
||||
// "verified" yet.
|
||||
foreach ($implementations[$hook] as $module => $group) {
|
||||
// If this hook implementation is stored in a lazy-loaded file, so include
|
||||
// that file first.
|
||||
@@ -769,6 +823,7 @@ function module_implements($hook, $sort = FALSE, $reset = FALSE) {
|
||||
$implementations['#write_cache'] = TRUE;
|
||||
}
|
||||
}
|
||||
$verified[$hook] = TRUE;
|
||||
}
|
||||
|
||||
return array_keys($implementations[$hook]);
|
||||
@@ -833,6 +888,11 @@ function module_hook_info() {
|
||||
* @see module_implements()
|
||||
*/
|
||||
function module_implements_write_cache() {
|
||||
// The list of implementations includes vital modules only before full
|
||||
// bootstrap, so do not write cache if we are not fully bootstrapped yet.
|
||||
if (drupal_get_bootstrap_phase() != DRUPAL_BOOTSTRAP_FULL) {
|
||||
return;
|
||||
}
|
||||
$implementations = &drupal_static('module_implements');
|
||||
if (isset($implementations['#write_cache'])) {
|
||||
unset($implementations['#write_cache']);
|
||||
@@ -880,7 +940,9 @@ function module_invoke($module, $hook) {
|
||||
*
|
||||
* @return
|
||||
* An array of return values of the hook implementations. If modules return
|
||||
* arrays from their implementations, those are merged into one array.
|
||||
* arrays from their implementations, those are merged into one array
|
||||
* recursively. Note: integer keys in arrays will be lost, as the merge is
|
||||
* done using array_merge_recursive().
|
||||
*
|
||||
* @see drupal_alter()
|
||||
*/
|
||||
|
||||
+2
-1
@@ -347,7 +347,8 @@ function drupal_match_path($path, $patterns) {
|
||||
* drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL) makes this function available.
|
||||
*
|
||||
* @return
|
||||
* The current Drupal URL path.
|
||||
* The current Drupal URL path. The path is untrusted user input and must be
|
||||
* treated as such.
|
||||
*
|
||||
* @see request_path()
|
||||
*/
|
||||
|
||||
@@ -164,7 +164,7 @@ function _registry_parse_files($files) {
|
||||
* (optional) Weight of the module.
|
||||
*/
|
||||
function _registry_parse_file($filename, $contents, $module = '', $weight = 0) {
|
||||
if (preg_match_all('/^\s*(?:abstract|final)?\s*(class|interface)\s+([a-zA-Z0-9_]+)/m', $contents, $matches)) {
|
||||
if (preg_match_all('/^\s*(?:abstract|final)?\s*(class|interface|trait)\s+([a-zA-Z0-9_]+)/m', $contents, $matches)) {
|
||||
foreach ($matches[2] as $key => $name) {
|
||||
db_merge('registry')
|
||||
->key(array(
|
||||
|
||||
@@ -163,7 +163,7 @@ function _drupal_session_write($sid, $value) {
|
||||
try {
|
||||
if (!drupal_save_session()) {
|
||||
// We don't have anything to do if we are not allowed to save the session.
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Check whether $_SESSION has been changed in this request.
|
||||
@@ -425,7 +425,7 @@ function _drupal_session_destroy($sid) {
|
||||
|
||||
// Nothing to do if we are not allowed to change the session.
|
||||
if (!drupal_save_session()) {
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Delete session data.
|
||||
@@ -446,6 +446,8 @@ function _drupal_session_destroy($sid) {
|
||||
elseif (variable_get('https', FALSE)) {
|
||||
_drupal_session_delete_cookie('S' . session_name(), TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -133,7 +133,7 @@ interface DrupalStreamWrapperInterface extends StreamWrapperInterface {
|
||||
* @param $uri
|
||||
* A string containing the URI that should be used for this instance.
|
||||
*/
|
||||
function setUri($uri);
|
||||
public function setUri($uri);
|
||||
|
||||
/**
|
||||
* Returns the stream resource URI.
|
||||
@@ -219,7 +219,6 @@ interface DrupalStreamWrapperInterface extends StreamWrapperInterface {
|
||||
public function dirname($uri = NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drupal stream wrapper base class for local files.
|
||||
*
|
||||
@@ -549,6 +548,155 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
return fclose($this->handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets metadata on the stream.
|
||||
*
|
||||
* WARNING: Do not call this method directly! It will be called internally by
|
||||
* PHP itself when one of the following functions is called on a stream URL:
|
||||
*
|
||||
* @param string $uri
|
||||
* A string containing the URI to the file to set metadata on.
|
||||
* @param int $option
|
||||
* One of:
|
||||
* - STREAM_META_TOUCH: The method was called in response to touch().
|
||||
* - STREAM_META_OWNER_NAME: The method was called in response to chown()
|
||||
* with string parameter.
|
||||
* - STREAM_META_OWNER: The method was called in response to chown().
|
||||
* - STREAM_META_GROUP_NAME: The method was called in response to chgrp().
|
||||
* - STREAM_META_GROUP: The method was called in response to chgrp().
|
||||
* - STREAM_META_ACCESS: The method was called in response to chmod().
|
||||
* @param mixed $value
|
||||
* If option is:
|
||||
* - STREAM_META_TOUCH: Array consisting of two arguments of the touch()
|
||||
* function.
|
||||
* - STREAM_META_OWNER_NAME or STREAM_META_GROUP_NAME: The name of the owner
|
||||
* user/group as string.
|
||||
* - STREAM_META_OWNER or STREAM_META_GROUP: The value of the owner
|
||||
* user/group as integer.
|
||||
* - STREAM_META_ACCESS: The argument of the chmod() as integer.
|
||||
*
|
||||
* @return bool
|
||||
* Returns TRUE on success or FALSE on failure. If $option is not
|
||||
* implemented, FALSE should be returned.
|
||||
*
|
||||
* @see touch()
|
||||
* @see chmod()
|
||||
* @see chown()
|
||||
* @see chgrp()
|
||||
* @link http://php.net/manual/streamwrapper.stream-metadata.php
|
||||
*/
|
||||
public function stream_metadata($uri, $option, $value) {
|
||||
$target = $this->getLocalPath($uri);
|
||||
$return = FALSE;
|
||||
switch ($option) {
|
||||
case STREAM_META_TOUCH:
|
||||
if (!empty($value)) {
|
||||
$return = touch($target, $value[0], $value[1]);
|
||||
}
|
||||
else {
|
||||
$return = touch($target);
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_META_OWNER_NAME:
|
||||
case STREAM_META_OWNER:
|
||||
$return = chown($target, $value);
|
||||
break;
|
||||
|
||||
case STREAM_META_GROUP_NAME:
|
||||
case STREAM_META_GROUP:
|
||||
$return = chgrp($target, $value);
|
||||
break;
|
||||
|
||||
case STREAM_META_ACCESS:
|
||||
$return = chmod($target, $value);
|
||||
break;
|
||||
}
|
||||
if ($return) {
|
||||
// For convenience clear the file status cache of the underlying file,
|
||||
// since metadata operations are often followed by file status checks.
|
||||
clearstatcache(TRUE, $target);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate stream.
|
||||
*
|
||||
* Will respond to truncation; e.g., through ftruncate().
|
||||
*
|
||||
* @param int $new_size
|
||||
* The new size.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE on success, FALSE otherwise.
|
||||
*/
|
||||
public function stream_truncate($new_size) {
|
||||
return ftruncate($this->handle, $new_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the underlying stream resource.
|
||||
*
|
||||
* This method is called in response to stream_select().
|
||||
*
|
||||
* @param int $cast_as
|
||||
* Can be STREAM_CAST_FOR_SELECT when stream_select() is calling
|
||||
* stream_cast() or STREAM_CAST_AS_STREAM when stream_cast() is called for
|
||||
* other uses.
|
||||
*
|
||||
* @return resource|false
|
||||
* The underlying stream resource or FALSE if stream_select() is not
|
||||
* supported.
|
||||
*
|
||||
* @see stream_select()
|
||||
* @link http://php.net/manual/streamwrapper.stream-cast.php
|
||||
*/
|
||||
public function stream_cast($cast_as) {
|
||||
return $this->handle ? $this->handle : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change stream options.
|
||||
*
|
||||
* This method is called to set options on the stream.
|
||||
*
|
||||
* Since Windows systems do not allow it and it is not needed for most use
|
||||
* cases anyway, this method is not supported on local files and will trigger
|
||||
* an error and return false. If needed, custom subclasses can provide
|
||||
* OS-specific implementations for advanced use cases.
|
||||
*
|
||||
* @param int $option
|
||||
* One of:
|
||||
* - STREAM_OPTION_BLOCKING: The method was called in response to
|
||||
* stream_set_blocking().
|
||||
* - STREAM_OPTION_READ_TIMEOUT: The method was called in response to
|
||||
* stream_set_timeout().
|
||||
* - STREAM_OPTION_WRITE_BUFFER: The method was called in response to
|
||||
* stream_set_write_buffer().
|
||||
* @param int $arg1
|
||||
* If option is:
|
||||
* - STREAM_OPTION_BLOCKING: The requested blocking mode:
|
||||
* - 1 means blocking.
|
||||
* - 0 means not blocking.
|
||||
* - STREAM_OPTION_READ_TIMEOUT: The timeout in seconds.
|
||||
* - STREAM_OPTION_WRITE_BUFFER: The buffer mode, STREAM_BUFFER_NONE or
|
||||
* STREAM_BUFFER_FULL.
|
||||
* @param int $arg2
|
||||
* If option is:
|
||||
* - STREAM_OPTION_BLOCKING: This option is not set.
|
||||
* - STREAM_OPTION_READ_TIMEOUT: The timeout in microseconds.
|
||||
* - STREAM_OPTION_WRITE_BUFFER: The requested buffer size.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE on success, FALSE otherwise. If $option is not implemented, FALSE
|
||||
* should be returned.
|
||||
*/
|
||||
public function stream_set_option($option, $arg1, $arg2) {
|
||||
trigger_error('stream_set_option() not supported for local file based stream wrappers', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support for unlink().
|
||||
*
|
||||
|
||||
+28
-7
@@ -1248,6 +1248,7 @@ function path_to_theme() {
|
||||
function drupal_find_theme_functions($cache, $prefixes) {
|
||||
$implementations = array();
|
||||
$functions = get_defined_functions();
|
||||
$theme_functions = preg_grep('/^(' . implode(')|(', $prefixes) . ')_/', $functions['user']);
|
||||
|
||||
foreach ($cache as $hook => $info) {
|
||||
foreach ($prefixes as $prefix) {
|
||||
@@ -1264,7 +1265,7 @@ function drupal_find_theme_functions($cache, $prefixes) {
|
||||
// intermediary suggestion.
|
||||
$pattern = isset($info['pattern']) ? $info['pattern'] : ($hook . '__');
|
||||
if (!isset($info['base hook']) && !empty($pattern)) {
|
||||
$matches = preg_grep('/^' . $prefix . '_' . $pattern . '/', $functions['user']);
|
||||
$matches = preg_grep('/^' . $prefix . '_' . $pattern . '/', $theme_functions);
|
||||
if ($matches) {
|
||||
foreach ($matches as $match) {
|
||||
$new_hook = substr($match, strlen($prefix) + 1);
|
||||
@@ -1710,11 +1711,29 @@ function theme_status_messages($variables) {
|
||||
* copy if none of the enabled modules or the active theme implement any
|
||||
* preprocess or process functions or override this theme implementation.
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing the keys 'text', 'path', and 'options'.
|
||||
* See the l() function for information about these variables.
|
||||
* @param array $variables
|
||||
* An associative array containing the keys:
|
||||
* - text: The text of the link.
|
||||
* - path: The internal path or external URL being linked to. It is used as
|
||||
* the $path parameter of the url() function.
|
||||
* - options: (optional) An array that defaults to empty, but can contain:
|
||||
* - attributes: Can contain optional attributes:
|
||||
* - class: must be declared in an array. Example: 'class' =>
|
||||
* array('class_name1','class_name2').
|
||||
* - title: must be a string. Example: 'title' => 'Example title'
|
||||
* - Others are more flexible as long as they work with
|
||||
* drupal_attributes($variables['options']['attributes]).
|
||||
* - html: Boolean flag that tells whether text contains HTML or plain
|
||||
* text. If set to TRUE, the text value will not be sanitized so the
|
||||
calling function must ensure that it already contains safe HTML.
|
||||
* The elements $variables['options']['attributes'] and
|
||||
* $variables['options']['html'] are used in this function similarly to the
|
||||
* way that $options['attributes'] and $options['html'] are used in l().
|
||||
* The link itself is built by the url() function, which takes
|
||||
* $variables['path'] and $variables['options'] as arguments.
|
||||
*
|
||||
* @see l()
|
||||
* @see url()
|
||||
*/
|
||||
function theme_link($variables) {
|
||||
return '<a href="' . check_plain(url($variables['path'], $variables['options'])) . '"' . drupal_attributes($variables['options']['attributes']) . '>' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '</a>';
|
||||
@@ -1791,7 +1810,8 @@ function theme_links($variables) {
|
||||
foreach ($links as $key => $link) {
|
||||
$class = array($key);
|
||||
|
||||
// Add first, last and active classes to the list of links to help out themers.
|
||||
// Add first, last and active classes to the list of links to help out
|
||||
// themers.
|
||||
if ($i == 1) {
|
||||
$class[] = 'first';
|
||||
}
|
||||
@@ -1809,7 +1829,8 @@ function theme_links($variables) {
|
||||
$output .= l($link['title'], $link['href'], $link);
|
||||
}
|
||||
elseif (!empty($link['title'])) {
|
||||
// Some links are actually not links, but we wrap these in <span> for adding title and class attributes.
|
||||
// Some links are actually not links, but we wrap these in <span> for
|
||||
// adding title and class attributes.
|
||||
if (empty($link['html'])) {
|
||||
$link['title'] = check_plain($link['title']);
|
||||
}
|
||||
@@ -2618,7 +2639,7 @@ function template_preprocess_page(&$variables) {
|
||||
// Move some variables to the top level for themer convenience and template cleanliness.
|
||||
$variables['show_messages'] = $variables['page']['#show_messages'];
|
||||
|
||||
foreach (system_region_list($GLOBALS['theme']) as $region_key => $region_name) {
|
||||
foreach (system_region_list($GLOBALS['theme'], REGIONS_ALL, FALSE) as $region_key) {
|
||||
if (!isset($variables['page'][$region_key])) {
|
||||
$variables['page'][$region_key] = array();
|
||||
}
|
||||
|
||||
@@ -795,6 +795,14 @@ function update_fix_d7_requirements() {
|
||||
function update_fix_d7_install_profile() {
|
||||
$profile = drupal_get_profile();
|
||||
|
||||
// 'Default' profile has been renamed to 'Standard' in D7.
|
||||
// We change the profile here to prevent a broken record in the system table.
|
||||
// See system_update_7049().
|
||||
if ($profile == 'default') {
|
||||
$profile = 'standard';
|
||||
variable_set('install_profile', $profile);
|
||||
}
|
||||
|
||||
$results = db_select('system', 's')
|
||||
->fields('s', array('name', 'schema_version'))
|
||||
->condition('name', $profile)
|
||||
@@ -908,6 +916,8 @@ function update_get_d6_session_name() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_operation().
|
||||
*
|
||||
* Performs one update and stores the results for display on the results page.
|
||||
*
|
||||
* If an update function completes successfully, it should return a message
|
||||
@@ -1078,6 +1088,8 @@ function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements callback_batch_finished().
|
||||
*
|
||||
* Finishes the update process and stores the results for eventual display.
|
||||
*
|
||||
* After the updates run, all caches are flushed. The update results are
|
||||
|
||||
@@ -264,6 +264,10 @@ function xmlrpc_server_call($xmlrpc_server, $methodname, $args) {
|
||||
*/
|
||||
function xmlrpc_server_multicall($methodcalls) {
|
||||
// See http://www.xmlrpc.com/discuss/msgReader$1208
|
||||
// To avoid multicall expansion attacks, limit the number of duplicate method
|
||||
// calls allowed with a default of 1. Set to -1 for unlimited.
|
||||
$duplicate_method_limit = variable_get('xmlrpc_multicall_duplicate_method_limit', 1);
|
||||
$method_count = array();
|
||||
$return = array();
|
||||
$xmlrpc_server = xmlrpc_server_get();
|
||||
foreach ($methodcalls as $call) {
|
||||
@@ -273,10 +277,14 @@ function xmlrpc_server_multicall($methodcalls) {
|
||||
$ok = FALSE;
|
||||
}
|
||||
$method = $call['methodName'];
|
||||
$method_count[$method] = isset($method_count[$method]) ? $method_count[$method] + 1 : 1;
|
||||
$params = $call['params'];
|
||||
if ($method == 'system.multicall') {
|
||||
$result = xmlrpc_error(-32600, t('Recursive calls to system.multicall are forbidden.'));
|
||||
}
|
||||
elseif ($duplicate_method_limit > 0 && $method_count[$method] > $duplicate_method_limit) {
|
||||
$result = xmlrpc_error(-156579, t('Too many duplicate method calls in system.multicall.'));
|
||||
}
|
||||
elseif ($ok) {
|
||||
$result = xmlrpc_server_call($xmlrpc_server, $method, $params);
|
||||
}
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Initiates a browser-based installation of Drupal.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines the root directory of the Drupal installation.
|
||||
*/
|
||||
define('DRUPAL_ROOT', getcwd());
|
||||
|
||||
/**
|
||||
* Global flag to indicate the site is in installation mode.
|
||||
*/
|
||||
define('MAINTENANCE_MODE', 'install');
|
||||
|
||||
// Exit early if running an incompatible PHP version to avoid fatal errors.
|
||||
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
|
||||
print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the <a href="http://drupal.org/requirements">system requirements</a> page for more information.';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Start the installer.
|
||||
require_once DRUPAL_ROOT . '/includes/install.core.inc';
|
||||
install_drupal();
|
||||
@@ -0,0 +1,14 @@
|
||||
diff --git a/logintoboggan.permissions.js b/logintoboggan.permissions.js
|
||||
index d463d29..492b64c 100644
|
||||
--- a/logintoboggan.permissions.js
|
||||
+++ b/logintoboggan.permissions.js
|
||||
@@ -14,6 +14,9 @@ Drupal.behaviors.LoginTobogganPermissions = {
|
||||
$('table#permissions', context).once('tobogganPermissions', function () {
|
||||
$('input[type=checkbox]', this).filter('.rid-' + settings.LoginToboggan.preAuthID).removeClass('real-checkbox').each(function () {
|
||||
$(this).next().filter('.dummy-checkbox').remove();
|
||||
+ $('input.rid-' + settings.LoginToboggan.preAuthID).each(function () {
|
||||
+ this.style.display = '';
|
||||
+ });
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -0,0 +1,136 @@
|
||||
diff --git a/logintoboggan.module b/logintoboggan.module
|
||||
index 55b93fe..4e4e0fc 100644
|
||||
--- a/logintoboggan.module
|
||||
+++ b/logintoboggan.module
|
||||
@@ -306,26 +306,6 @@ function logintoboggan_form_user_pass_reset_alter(&$form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
- * Implement hook_form_user_admin_permissions_alter().
|
||||
- *
|
||||
- * @ingroup logintoboggan_core
|
||||
- */
|
||||
-function logintoboggan_form_user_admin_permissions_alter(&$form, &$form_state) {
|
||||
- // If the pre-auth role isn't the auth user, then add it as a setting.
|
||||
- $id = logintoboggan_validating_id();
|
||||
- if ($id != DRUPAL_AUTHENTICATED_RID) {
|
||||
- $form['#attached']['js'][] = array(
|
||||
- 'data' => array(
|
||||
- 'LoginToboggan' => array(
|
||||
- 'preAuthID' => $id,
|
||||
- ),
|
||||
- ),
|
||||
- 'type' => 'setting',
|
||||
- );
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
* Implement hook_form_alter().
|
||||
*
|
||||
* @ingroup logintoboggan_core
|
||||
@@ -410,7 +390,10 @@ function logintoboggan_js_alter(&$javascript) {
|
||||
// prevent the pre-auth role's checkboxes from being automatically disabled
|
||||
// when the auth user's checkboxes are checked.
|
||||
if ($id != DRUPAL_AUTHENTICATED_RID) {
|
||||
- $javascript['modules/user/user.permissions.js']['data'] = drupal_get_path('module', 'logintoboggan') . '/logintoboggan.permissions.js';
|
||||
+ $javascript['settings']['data'][] = array('LoginToboggan' => array('preAuthID' => $id));
|
||||
+ $file = drupal_get_path('module', 'logintoboggan') . '/logintoboggan.permissions.js';
|
||||
+ $javascript[$file] = drupal_js_defaults($file);
|
||||
+ $javascript[$file]['weight'] = 999;
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/logintoboggan.permissions.js b/logintoboggan.permissions.js
|
||||
index 1d406cc..492b64c 100644
|
||||
--- a/logintoboggan.permissions.js
|
||||
+++ b/logintoboggan.permissions.js
|
||||
@@ -1,77 +1,25 @@
|
||||
|
||||
/**
|
||||
- * This is a custom implementation of user.permissions.js, which is necessary
|
||||
- * because LoginToboggan needs its pre-auth role to not be explicitly tied to
|
||||
- * the auth role. The change is minor -- simply exclude the pre-auth role from
|
||||
- * all the auto-checking as the anon and auth user roles are.
|
||||
+ * LoginToboggan needs its pre-auth role to not be explicitly tied to
|
||||
+ * the auth role.
|
||||
*/
|
||||
-
|
||||
(function ($) {
|
||||
|
||||
/**
|
||||
* Shows checked and disabled checkboxes for inherited permissions.
|
||||
*/
|
||||
-Drupal.behaviors.permissions = {
|
||||
- attach: function (context) {
|
||||
- var self = this;
|
||||
- $('table#permissions').once('permissions', function () {
|
||||
- // On a site with many roles and permissions, this behavior initially has
|
||||
- // to perform thousands of DOM manipulations to inject checkboxes and hide
|
||||
- // them. By detaching the table from the DOM, all operations can be
|
||||
- // performed without triggering internal layout and re-rendering processes
|
||||
- // in the browser.
|
||||
- var $table = $(this);
|
||||
- if ($table.prev().length) {
|
||||
- var $ancestor = $table.prev(), method = 'after';
|
||||
- }
|
||||
- else {
|
||||
- var $ancestor = $table.parent(), method = 'append';
|
||||
- }
|
||||
- $table.detach();
|
||||
-
|
||||
- // Create dummy checkboxes. We use dummy checkboxes instead of reusing
|
||||
- // the existing checkboxes here because new checkboxes don't alter the
|
||||
- // submitted form. If we'd automatically check existing checkboxes, the
|
||||
- // permission table would be polluted with redundant entries. This
|
||||
- // is deliberate, but desirable when we automatically check them.
|
||||
- var $dummy = $('<input type="checkbox" class="dummy-checkbox" disabled="disabled" checked="checked" />')
|
||||
- .attr('title', Drupal.t("This permission is inherited from the authenticated user role."))
|
||||
- .hide();
|
||||
-
|
||||
- $('input[type=checkbox]', this).not('.rid-2, .rid-1, .rid-' + Drupal.settings.LoginToboggan.preAuthID).addClass('real-checkbox').each(function () {
|
||||
- $dummy.clone().insertAfter(this);
|
||||
+Drupal.behaviors.LoginTobogganPermissions = {
|
||||
+ attach: function (context, settings) {
|
||||
+ // Revert changes made by modules/user/user.permissions.js
|
||||
+ $('table#permissions', context).once('tobogganPermissions', function () {
|
||||
+ $('input[type=checkbox]', this).filter('.rid-' + settings.LoginToboggan.preAuthID).removeClass('real-checkbox').each(function () {
|
||||
+ $(this).next().filter('.dummy-checkbox').remove();
|
||||
+ $('input.rid-' + settings.LoginToboggan.preAuthID).each(function () {
|
||||
+ this.style.display = '';
|
||||
+ });
|
||||
});
|
||||
-
|
||||
- // Initialize the authenticated user checkbox.
|
||||
- $('input[type=checkbox].rid-2', this)
|
||||
- .bind('click.permissions', self.toggle)
|
||||
- // .triggerHandler() cannot be used here, as it only affects the first
|
||||
- // element.
|
||||
- .each(self.toggle);
|
||||
-
|
||||
- // Re-insert the table into the DOM.
|
||||
- $ancestor[method]($table);
|
||||
});
|
||||
},
|
||||
-
|
||||
- /**
|
||||
- * Toggles all dummy checkboxes based on the checkboxes' state.
|
||||
- *
|
||||
- * If the "authenticated user" checkbox is checked, the checked and disabled
|
||||
- * checkboxes are shown, the real checkboxes otherwise.
|
||||
- */
|
||||
- toggle: function () {
|
||||
- var authCheckbox = this, $row = $(this).closest('tr');
|
||||
- // jQuery performs too many layout calculations for .hide() and .show(),
|
||||
- // leading to a major page rendering lag on sites with many roles and
|
||||
- // permissions. Therefore, we toggle visibility directly.
|
||||
- $row.find('.real-checkbox').each(function () {
|
||||
- this.style.display = (authCheckbox.checked ? 'none' : '');
|
||||
- });
|
||||
- $row.find('.dummy-checkbox').each(function () {
|
||||
- this.style.display = (authCheckbox.checked ? '' : 'none');
|
||||
- });
|
||||
- }
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
+34
-6
@@ -14,6 +14,8 @@
|
||||
|
||||
Drupal.ajax = Drupal.ajax || {};
|
||||
|
||||
Drupal.settings.urlIsAjaxTrusted = Drupal.settings.urlIsAjaxTrusted || {};
|
||||
|
||||
/**
|
||||
* Attaches the Ajax behavior to each Ajax form element.
|
||||
*/
|
||||
@@ -130,6 +132,11 @@ Drupal.ajax = function (base, element, element_settings) {
|
||||
// 5. /nojs# - Followed by a fragment.
|
||||
// E.g.: path/nojs#myfragment
|
||||
this.url = element_settings.url.replace(/\/nojs(\/|$|\?|&|#)/g, '/ajax$1');
|
||||
// If the 'nojs' version of the URL is trusted, also trust the 'ajax' version.
|
||||
if (Drupal.settings.urlIsAjaxTrusted[element_settings.url]) {
|
||||
Drupal.settings.urlIsAjaxTrusted[this.url] = true;
|
||||
}
|
||||
|
||||
this.wrapper = '#' + element_settings.wrapper;
|
||||
|
||||
// If there isn't a form, jQuery.ajax() will be used instead, allowing us to
|
||||
@@ -155,18 +162,36 @@ Drupal.ajax = function (base, element, element_settings) {
|
||||
ajax.ajaxing = true;
|
||||
return ajax.beforeSend(xmlhttprequest, options);
|
||||
},
|
||||
success: function (response, status) {
|
||||
success: function (response, status, xmlhttprequest) {
|
||||
// Sanity check for browser support (object expected).
|
||||
// When using iFrame uploads, responses must be returned as a string.
|
||||
if (typeof response == 'string') {
|
||||
response = $.parseJSON(response);
|
||||
}
|
||||
|
||||
// Prior to invoking the response's commands, verify that they can be
|
||||
// trusted by checking for a response header. See
|
||||
// ajax_set_verification_header() for details.
|
||||
// - Empty responses are harmless so can bypass verification. This avoids
|
||||
// an alert message for server-generated no-op responses that skip Ajax
|
||||
// rendering.
|
||||
// - Ajax objects with trusted URLs (e.g., ones defined server-side via
|
||||
// #ajax) can bypass header verification. This is especially useful for
|
||||
// Ajax with multipart forms. Because IFRAME transport is used, the
|
||||
// response headers cannot be accessed for verification.
|
||||
if (response !== null && !Drupal.settings.urlIsAjaxTrusted[ajax.url]) {
|
||||
if (xmlhttprequest.getResponseHeader('X-Drupal-Ajax-Token') !== '1') {
|
||||
var customMessage = Drupal.t("The response failed verification so will not be processed.");
|
||||
return ajax.error(xmlhttprequest, ajax.url, customMessage);
|
||||
}
|
||||
}
|
||||
|
||||
return ajax.success(response, status);
|
||||
},
|
||||
complete: function (response, status) {
|
||||
complete: function (xmlhttprequest, status) {
|
||||
ajax.ajaxing = false;
|
||||
if (status == 'error' || status == 'parsererror') {
|
||||
return ajax.error(response, ajax.url);
|
||||
return ajax.error(xmlhttprequest, ajax.url);
|
||||
}
|
||||
},
|
||||
dataType: 'json',
|
||||
@@ -175,6 +200,9 @@ Drupal.ajax = function (base, element, element_settings) {
|
||||
|
||||
// Bind the ajaxSubmit function to the element event.
|
||||
$(ajax.element).bind(element_settings.event, function (event) {
|
||||
if (!Drupal.settings.urlIsAjaxTrusted[ajax.url] && !Drupal.urlIsLocal(ajax.url)) {
|
||||
throw new Error(Drupal.t('The callback URL is not local and not trusted: !url', {'!url': ajax.url}));
|
||||
}
|
||||
return ajax.eventResponse(this, event);
|
||||
});
|
||||
|
||||
@@ -447,8 +475,8 @@ Drupal.ajax.prototype.getEffect = function (response) {
|
||||
/**
|
||||
* Handler for the form redirection error.
|
||||
*/
|
||||
Drupal.ajax.prototype.error = function (response, uri) {
|
||||
alert(Drupal.ajaxError(response, uri));
|
||||
Drupal.ajax.prototype.error = function (xmlhttprequest, uri, customMessage) {
|
||||
Drupal.displayAjaxError(Drupal.ajaxError(xmlhttprequest, uri, customMessage));
|
||||
// Remove the progress element.
|
||||
if (this.progress.element) {
|
||||
$(this.progress.element).remove();
|
||||
@@ -462,7 +490,7 @@ Drupal.ajax.prototype.error = function (response, uri) {
|
||||
$(this.element).removeClass('progress-disabled').removeAttr('disabled');
|
||||
// Reattach behaviors, if they were detached in beforeSerialize().
|
||||
if (this.form) {
|
||||
var settings = response.settings || this.settings || Drupal.settings;
|
||||
var settings = this.settings || Drupal.settings;
|
||||
Drupal.attachBehaviors(this.form, settings);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -271,8 +271,11 @@ Drupal.ACDB.prototype.search = function (searchString) {
|
||||
var db = this;
|
||||
this.searchString = searchString;
|
||||
|
||||
// See if this string needs to be searched for anyway.
|
||||
searchString = searchString.replace(/^\s+|\s+$/, '');
|
||||
// See if this string needs to be searched for anyway. The pattern ../ is
|
||||
// stripped since it may be misinterpreted by the browser.
|
||||
searchString = searchString.replace(/^\s+|\.{2,}\/|\s+$/g, '');
|
||||
// Skip empty search strings, or search strings ending with a comma, since
|
||||
// that is the separator between search terms.
|
||||
if (searchString.length <= 0 ||
|
||||
searchString.charAt(searchString.length - 1) == ',') {
|
||||
return;
|
||||
@@ -307,7 +310,7 @@ Drupal.ACDB.prototype.search = function (searchString) {
|
||||
}
|
||||
},
|
||||
error: function (xmlhttp) {
|
||||
alert(Drupal.ajaxError(xmlhttp, db.uri));
|
||||
Drupal.displayAjaxError(Drupal.ajaxError(xmlhttp, db.uri));
|
||||
}
|
||||
});
|
||||
}, this.delay);
|
||||
|
||||
+163
-18
@@ -168,23 +168,76 @@ Drupal.checkPlain = function (str) {
|
||||
Drupal.formatString = function(str, args) {
|
||||
// Transform arguments before inserting them.
|
||||
for (var key in args) {
|
||||
switch (key.charAt(0)) {
|
||||
// Escaped only.
|
||||
case '@':
|
||||
args[key] = Drupal.checkPlain(args[key]);
|
||||
break;
|
||||
// Pass-through.
|
||||
case '!':
|
||||
break;
|
||||
// Escaped and placeholder.
|
||||
case '%':
|
||||
default:
|
||||
args[key] = Drupal.theme('placeholder', args[key]);
|
||||
break;
|
||||
if (args.hasOwnProperty(key)) {
|
||||
switch (key.charAt(0)) {
|
||||
// Escaped only.
|
||||
case '@':
|
||||
args[key] = Drupal.checkPlain(args[key]);
|
||||
break;
|
||||
// Pass-through.
|
||||
case '!':
|
||||
break;
|
||||
// Escaped and placeholder.
|
||||
default:
|
||||
args[key] = Drupal.theme('placeholder', args[key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
str = str.replace(key, args[key]);
|
||||
}
|
||||
return str;
|
||||
|
||||
return Drupal.stringReplace(str, args, null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace substring.
|
||||
*
|
||||
* The longest keys will be tried first. Once a substring has been replaced,
|
||||
* its new value will not be searched again.
|
||||
*
|
||||
* @param {String} str
|
||||
* A string with placeholders.
|
||||
* @param {Object} args
|
||||
* Key-value pairs.
|
||||
* @param {Array|null} keys
|
||||
* Array of keys from the "args". Internal use only.
|
||||
*
|
||||
* @return {String}
|
||||
* Returns the replaced string.
|
||||
*/
|
||||
Drupal.stringReplace = function (str, args, keys) {
|
||||
if (str.length === 0) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// If the array of keys is not passed then collect the keys from the args.
|
||||
if (!$.isArray(keys)) {
|
||||
keys = [];
|
||||
for (var k in args) {
|
||||
if (args.hasOwnProperty(k)) {
|
||||
keys.push(k);
|
||||
}
|
||||
}
|
||||
|
||||
// Order the keys by the character length. The shortest one is the first.
|
||||
keys.sort(function (a, b) { return a.length - b.length; });
|
||||
}
|
||||
|
||||
if (keys.length === 0) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// Take next longest one from the end.
|
||||
var key = keys.pop();
|
||||
var fragments = str.split(key);
|
||||
|
||||
if (keys.length) {
|
||||
for (var i = 0; i < fragments.length; i++) {
|
||||
// Process each fragment with a copy of remaining keys.
|
||||
fragments[i] = Drupal.stringReplace(fragments[i], args, keys.slice(0));
|
||||
}
|
||||
}
|
||||
|
||||
return fragments.join(args[key]);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -251,7 +304,7 @@ Drupal.t = function (str, args, options) {
|
||||
* A translated string.
|
||||
*/
|
||||
Drupal.formatPlural = function (count, singular, plural, args, options) {
|
||||
var args = args || {};
|
||||
args = args || {};
|
||||
args['@count'] = count;
|
||||
// Determine the index of the plural form.
|
||||
var index = Drupal.locale.pluralFormula ? Drupal.locale.pluralFormula(args['@count']) : ((args['@count'] == 1) ? 0 : 1);
|
||||
@@ -269,6 +322,72 @@ Drupal.formatPlural = function (count, singular, plural, args, options) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the passed in URL as an absolute URL.
|
||||
*
|
||||
* @param url
|
||||
* The URL string to be normalized to an absolute URL.
|
||||
*
|
||||
* @return
|
||||
* The normalized, absolute URL.
|
||||
*
|
||||
* @see https://github.com/angular/angular.js/blob/v1.4.4/src/ng/urlUtils.js
|
||||
* @see https://grack.com/blog/2009/11/17/absolutizing-url-in-javascript
|
||||
* @see https://github.com/jquery/jquery-ui/blob/1.11.4/ui/tabs.js#L53
|
||||
*/
|
||||
Drupal.absoluteUrl = function (url) {
|
||||
var urlParsingNode = document.createElement('a');
|
||||
|
||||
// Decode the URL first; this is required by IE <= 6. Decoding non-UTF-8
|
||||
// strings may throw an exception.
|
||||
try {
|
||||
url = decodeURIComponent(url);
|
||||
} catch (e) {}
|
||||
|
||||
urlParsingNode.setAttribute('href', url);
|
||||
|
||||
// IE <= 7 normalizes the URL when assigned to the anchor node similar to
|
||||
// the other browsers.
|
||||
return urlParsingNode.cloneNode(false).href;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the URL is within Drupal's base path.
|
||||
*
|
||||
* @param url
|
||||
* The URL string to be tested.
|
||||
*
|
||||
* @return
|
||||
* Boolean true if local.
|
||||
*
|
||||
* @see https://github.com/jquery/jquery-ui/blob/1.11.4/ui/tabs.js#L58
|
||||
*/
|
||||
Drupal.urlIsLocal = function (url) {
|
||||
// Always use browser-derived absolute URLs in the comparison, to avoid
|
||||
// attempts to break out of the base path using directory traversal.
|
||||
var absoluteUrl = Drupal.absoluteUrl(url);
|
||||
var protocol = location.protocol;
|
||||
|
||||
// Consider URLs that match this site's base URL but use HTTPS instead of HTTP
|
||||
// as local as well.
|
||||
if (protocol === 'http:' && absoluteUrl.indexOf('https:') === 0) {
|
||||
protocol = 'https:';
|
||||
}
|
||||
var baseUrl = protocol + '//' + location.host + Drupal.settings.basePath.slice(0, -1);
|
||||
|
||||
// Decoding non-UTF-8 strings may throw an exception.
|
||||
try {
|
||||
absoluteUrl = decodeURIComponent(absoluteUrl);
|
||||
} catch (e) {}
|
||||
try {
|
||||
baseUrl = decodeURIComponent(baseUrl);
|
||||
} catch (e) {}
|
||||
|
||||
// The given URL matches the site's base URL, or has a path under the site's
|
||||
// base URL.
|
||||
return absoluteUrl === baseUrl || absoluteUrl.indexOf(baseUrl + '/') === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate the themed representation of a Drupal object.
|
||||
*
|
||||
@@ -347,10 +466,33 @@ Drupal.getSelection = function (element) {
|
||||
return { 'start': element.selectionStart, 'end': element.selectionEnd };
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a global variable which determines if the window is being unloaded.
|
||||
*
|
||||
* This is primarily used by Drupal.displayAjaxError().
|
||||
*/
|
||||
Drupal.beforeUnloadCalled = false;
|
||||
$(window).bind('beforeunload pagehide', function () {
|
||||
Drupal.beforeUnloadCalled = true;
|
||||
});
|
||||
|
||||
/**
|
||||
* Displays a JavaScript error from an Ajax response when appropriate to do so.
|
||||
*/
|
||||
Drupal.displayAjaxError = function (message) {
|
||||
// Skip displaying the message if the user deliberately aborted (for example,
|
||||
// by reloading the page or navigating to a different page) while the Ajax
|
||||
// request was still ongoing. See, for example, the discussion at
|
||||
// http://stackoverflow.com/questions/699941/handle-ajax-error-when-a-user-clicks-refresh.
|
||||
if (!Drupal.beforeUnloadCalled) {
|
||||
alert(message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Build an error message from an Ajax response.
|
||||
*/
|
||||
Drupal.ajaxError = function (xmlhttp, uri) {
|
||||
Drupal.ajaxError = function (xmlhttp, uri, customMessage) {
|
||||
var statusCode, statusText, pathText, responseText, readyStateText, message;
|
||||
if (xmlhttp.status) {
|
||||
statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") + "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status});
|
||||
@@ -383,7 +525,10 @@ Drupal.ajaxError = function (xmlhttp, uri) {
|
||||
// We don't need readyState except for status == 0.
|
||||
readyStateText = xmlhttp.status == 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
|
||||
|
||||
message = statusCode + pathText + statusText + responseText + readyStateText;
|
||||
// Additional message beyond what the xmlhttp object provides.
|
||||
customMessage = customMessage ? ("\n" + Drupal.t("CustomMessage: !customMessage", {'!customMessage': customMessage})) : "";
|
||||
|
||||
message = statusCode + pathText + statusText + customMessage + responseText + readyStateText;
|
||||
return message;
|
||||
};
|
||||
|
||||
|
||||
+5
-1
@@ -493,7 +493,11 @@ $(document).bind('state:disabled', function(e) {
|
||||
$(document).bind('state:required', function(e) {
|
||||
if (e.trigger) {
|
||||
if (e.value) {
|
||||
$(e.target).closest('.form-item, .form-wrapper').find('label').append('<span class="form-required">*</span>');
|
||||
var $label = $(e.target).closest('.form-item, .form-wrapper').find('label');
|
||||
// Avoids duplicate required markers on initialization.
|
||||
if (!$label.find('.form-required').length) {
|
||||
$label.append('<span class="form-required">*</span>');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$(e.target).closest('.form-item, .form-wrapper').find('label .form-required').remove();
|
||||
|
||||
+18
-5
@@ -106,8 +106,10 @@ Drupal.tableDrag = function (table, tableSettings) {
|
||||
|
||||
// Add mouse bindings to the document. The self variable is passed along
|
||||
// as event handlers do not have direct access to the tableDrag object.
|
||||
$(document).bind('mousemove', function (event) { return self.dragRow(event, self); });
|
||||
$(document).bind('mouseup', function (event) { return self.dropRow(event, self); });
|
||||
$(document).bind('mousemove pointermove', function (event) { return self.dragRow(event, self); });
|
||||
$(document).bind('mouseup pointerup', function (event) { return self.dropRow(event, self); });
|
||||
$(document).bind('touchmove', function (event) { return self.dragRow(event.originalEvent.touches[0], self); });
|
||||
$(document).bind('touchend', function (event) { return self.dropRow(event.originalEvent.touches[0], self); });
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -274,7 +276,10 @@ Drupal.tableDrag.prototype.makeDraggable = function (item) {
|
||||
});
|
||||
|
||||
// Add the mousedown action for the handle.
|
||||
handle.mousedown(function (event) {
|
||||
handle.bind('mousedown touchstart pointerdown', function (event) {
|
||||
if (event.originalEvent.type == "touchstart") {
|
||||
event = event.originalEvent.touches[0];
|
||||
}
|
||||
// Create a new dragObject recording the event information.
|
||||
self.dragObject = {};
|
||||
self.dragObject.initMouseOffset = self.getMouseOffset(item, event);
|
||||
@@ -575,12 +580,20 @@ Drupal.tableDrag.prototype.dropRow = function (event, self) {
|
||||
* Get the mouse coordinates from the event (allowing for browser differences).
|
||||
*/
|
||||
Drupal.tableDrag.prototype.mouseCoords = function (event) {
|
||||
// Complete support for pointer events was only introduced to jQuery in
|
||||
// version 1.11.1; between versions 1.7 and 1.11.0 pointer events have the
|
||||
// clientX and clientY properties undefined. In those cases, the properties
|
||||
// must be retrieved from the event.originalEvent object instead.
|
||||
var clientX = event.clientX || event.originalEvent.clientX;
|
||||
var clientY = event.clientY || event.originalEvent.clientY;
|
||||
|
||||
if (event.pageX || event.pageY) {
|
||||
return { x: event.pageX, y: event.pageY };
|
||||
}
|
||||
|
||||
return {
|
||||
x: event.clientX + document.body.scrollLeft - document.body.clientLeft,
|
||||
y: event.clientY + document.body.scrollTop - document.body.clientTop
|
||||
x: clientX + document.body.scrollLeft - document.body.clientLeft,
|
||||
y: clientY + document.body.scrollTop - document.body.clientTop
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -455,6 +455,14 @@ function aggregator_save_category($edit) {
|
||||
db_delete('aggregator_category')
|
||||
->condition('cid', $edit['cid'])
|
||||
->execute();
|
||||
// Remove category from feeds.
|
||||
db_delete('aggregator_category_feed')
|
||||
->condition('cid', $edit['cid'])
|
||||
->execute();
|
||||
// Remove category from feed items.
|
||||
db_delete('aggregator_category_item')
|
||||
->condition('cid', $edit['cid'])
|
||||
->execute();
|
||||
// Make sure there is no active block for this category.
|
||||
if (module_exists('block')) {
|
||||
db_delete('block')
|
||||
|
||||
@@ -72,7 +72,7 @@ function aggregator_aggregator_remove($feed) {
|
||||
*/
|
||||
function aggregator_form_aggregator_admin_form_alter(&$form, $form_state) {
|
||||
if (in_array('aggregator', variable_get('aggregator_processors', array('aggregator')))) {
|
||||
$info = module_invoke('aggregator', 'aggregator_process', 'info');
|
||||
$info = module_invoke('aggregator', 'aggregator_process_info');
|
||||
$items = drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items');
|
||||
$period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
|
||||
$period[AGGREGATOR_CLEAR_NEVER] = t('Never');
|
||||
|
||||
@@ -418,7 +418,7 @@ class CategorizeFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a feed and makes sure you can add more than one category to it.
|
||||
* Creates a feed and makes sure you can add/delete categories to it.
|
||||
*/
|
||||
function testCategorizeFeed() {
|
||||
|
||||
@@ -448,7 +448,31 @@ class CategorizeFeedTestCase extends AggregatorTestCase {
|
||||
// Assert the feed has two categories.
|
||||
$this->getFeedCategories($db_feed);
|
||||
$this->assertEqual(count($db_feed->categories), 2, 'Feed has 2 categories');
|
||||
|
||||
// Use aggregator_save_feed() to delete a category.
|
||||
$category = reset($categories);
|
||||
aggregator_save_category(array('cid' => $category->cid));
|
||||
|
||||
// Assert that category is deleted.
|
||||
$db_category = db_query("SELECT COUNT(*) FROM {aggregator_category} WHERE cid = :cid", array(':cid' => $category->cid))->fetchField();
|
||||
$this->assertFalse($db_category, format_string('The category %title has been deleted.', array('%title' => $category->title)));
|
||||
|
||||
// Assert that category has been removed from feed.
|
||||
$categorized_feeds = db_query("SELECT COUNT(*) FROM {aggregator_category_feed} WHERE cid = :cid", array(':cid' => $category->cid))->fetchField();
|
||||
$this->assertFalse($categorized_feeds, format_string('The category %title has been removed from feed %feed_title.', array('%title' => $category->title, '%feed_title' => $feed['title'])));
|
||||
|
||||
// Assert that no broken links (associated with the deleted category)
|
||||
// appear on one of the other category pages.
|
||||
$this->createSampleNodes();
|
||||
$this->drupalGet('admin/config/services/aggregator');
|
||||
$this->clickLink('update items');
|
||||
$categories = $this->getCategories();
|
||||
$category = reset($categories);
|
||||
$this->drupalGet('aggregator/categories/' . $category->cid);
|
||||
global $base_path;
|
||||
$this->assertNoRaw('<a href="' . $base_path . 'aggregator/categories/"></a>,');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -685,9 +709,21 @@ class CategorizeFeedItemTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete category from feed items when category is deleted.
|
||||
$cid = reset($feed->categories);
|
||||
$categories = $this->getCategories();
|
||||
$category_title = $categories[$cid]->title;
|
||||
|
||||
// Delete category.
|
||||
aggregator_save_category(array('cid' => $cid));
|
||||
|
||||
// Assert category has been removed from feed items.
|
||||
$categorized_count = db_query("SELECT COUNT(*) FROM {aggregator_category_item} WHERE cid = :cid", array(':cid' => $cid))->fetchField();
|
||||
$this->assertFalse($categorized_count, format_string('The category %title has been removed from feed items.', array('%title' => $category_title)));
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -363,6 +363,31 @@ function hook_block_list_alter(&$blocks) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Act on block cache ID (cid) parts before the cid is generated.
|
||||
*
|
||||
* This hook allows you to add, remove or modify the custom keys used to
|
||||
* generate a block cache ID (by default, these keys are set to the block
|
||||
* module and delta). These keys will be combined with the standard ones
|
||||
* provided by drupal_render_cid_parts() to generate the final block cache ID.
|
||||
*
|
||||
* To change the cache granularity used by drupal_render_cid_parts(), this hook
|
||||
* cannot be used; instead, set the 'cache' key in the block's definition in
|
||||
* hook_block_info().
|
||||
*
|
||||
* @params $cid_parts
|
||||
* An array of elements used to build the cid.
|
||||
* @param $block
|
||||
* The block object being acted on.
|
||||
*
|
||||
* @see _block_get_cache_id()
|
||||
*/
|
||||
function hook_block_cid_parts_alter(&$cid_parts, $block) {
|
||||
global $user;
|
||||
// This example shows how to cache a block based on the user's timezone.
|
||||
$cid_parts[] = $user->timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup hooks".
|
||||
*/
|
||||
|
||||
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = block.test
|
||||
configure = admin/structure/block
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Drupal.behaviors.blockSettingsSummary = {
|
||||
$('fieldset#edit-node-type', context).drupalSetSummary(function (context) {
|
||||
var vals = [];
|
||||
$('input[type="checkbox"]:checked', context).each(function () {
|
||||
vals.push($.trim($(this).next('label').text()));
|
||||
vals.push($.trim($(this).next('label').html()));
|
||||
});
|
||||
if (!vals.length) {
|
||||
vals.push(Drupal.t('Not restricted'));
|
||||
@@ -35,7 +35,7 @@ Drupal.behaviors.blockSettingsSummary = {
|
||||
$('fieldset#edit-role', context).drupalSetSummary(function (context) {
|
||||
var vals = [];
|
||||
$('input[type="checkbox"]:checked', context).each(function () {
|
||||
vals.push($.trim($(this).next('label').text()));
|
||||
vals.push($.trim($(this).next('label').html()));
|
||||
});
|
||||
if (!vals.length) {
|
||||
vals.push(Drupal.t('Not restricted'));
|
||||
@@ -49,7 +49,7 @@ Drupal.behaviors.blockSettingsSummary = {
|
||||
return Drupal.t('Not customizable');
|
||||
}
|
||||
else {
|
||||
return $radio.next('label').text();
|
||||
return $radio.next('label').html();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+38
-29
@@ -16,7 +16,7 @@ define('BLOCK_REGION_NONE', -1);
|
||||
define('BLOCK_CUSTOM_FIXED', 0);
|
||||
|
||||
/**
|
||||
* Shows this block by default, but lets individual users hide it.
|
||||
* Shows this block by default, but lets individual users hide it.
|
||||
*/
|
||||
define('BLOCK_CUSTOM_ENABLED', 1);
|
||||
|
||||
@@ -59,6 +59,7 @@ function block_help($path, $arg) {
|
||||
$output .= '<dd>' . t('Users with the <em>Administer blocks</em> permission can <a href="@block-add">add custom blocks</a>, which are then listed on the <a href="@blocks">Blocks administration page</a>. Once created, custom blocks behave just like default and module-generated blocks.', array('@blocks' => url('admin/structure/block'), '@block-add' => url('admin/structure/block/add'))) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
case 'admin/structure/block/add':
|
||||
return '<p>' . t('Use this page to create a new custom block.') . '</p>';
|
||||
}
|
||||
@@ -189,6 +190,7 @@ function _block_themes_access($theme) {
|
||||
* @param $theme
|
||||
* The theme whose blocks are being configured. If not set, the default theme
|
||||
* is assumed.
|
||||
*
|
||||
* @return
|
||||
* The theme that should be used for the block configuration page, or NULL
|
||||
* to indicate that the default theme should be used.
|
||||
@@ -283,8 +285,7 @@ function block_page_build(&$page) {
|
||||
// Append region description if we are rendering the regions demo page.
|
||||
$item = menu_get_item();
|
||||
if ($item['path'] == 'admin/structure/block/demo/' . $theme) {
|
||||
$visible_regions = array_keys(system_region_list($theme, REGIONS_VISIBLE));
|
||||
foreach ($visible_regions as $region) {
|
||||
foreach (system_region_list($theme, REGIONS_VISIBLE, FALSE) as $region) {
|
||||
$description = '<div class="block-region">' . $all_regions[$region] . '</div>';
|
||||
$page[$region]['block_description'] = array(
|
||||
'#markup' => $description,
|
||||
@@ -343,14 +344,17 @@ function _block_get_renderable_array($list = array()) {
|
||||
// to perform contextual actions on the help block, and the links needlessly
|
||||
// draw attention on it.
|
||||
if ($key != 'system_main' && $key != 'system_help') {
|
||||
$build[$key]['#contextual_links']['block'] = array('admin/structure/block/manage', array($block->module, $block->delta));
|
||||
$build[$key]['#contextual_links']['block'] = array(
|
||||
'admin/structure/block/manage',
|
||||
array($block->module, $block->delta),
|
||||
);
|
||||
}
|
||||
|
||||
$build[$key] += array(
|
||||
'#block' => $block,
|
||||
'#weight' => ++$weight,
|
||||
);
|
||||
$build[$key]['#theme_wrappers'][] ='block';
|
||||
$build[$key]['#theme_wrappers'][] = 'block';
|
||||
}
|
||||
$build['#sorted'] = TRUE;
|
||||
return $build;
|
||||
@@ -386,18 +390,20 @@ function _block_rehash($theme = NULL) {
|
||||
// Gather the blocks defined by modules.
|
||||
foreach (module_implements('block_info') as $module) {
|
||||
$module_blocks = module_invoke($module, 'block_info');
|
||||
$delta_list = array();
|
||||
foreach ($module_blocks as $delta => $block) {
|
||||
// Compile a condition to retrieve this block from the database.
|
||||
$condition = db_and()
|
||||
->condition('module', $module)
|
||||
->condition('delta', $delta);
|
||||
$or->condition($condition);
|
||||
// Add identifiers.
|
||||
$delta_list[] = $delta;
|
||||
$block['module'] = $module;
|
||||
$block['delta'] = $delta;
|
||||
$block['theme'] = $theme;
|
||||
$block['delta'] = $delta;
|
||||
$block['theme'] = $theme;
|
||||
$current_blocks[$module][$delta] = $block;
|
||||
}
|
||||
if (!empty($delta_list)) {
|
||||
$condition = db_and()->condition('module', $module)->condition('delta', $delta_list);
|
||||
$or->condition($condition);
|
||||
}
|
||||
}
|
||||
// Save the blocks defined in code for alter context.
|
||||
$code_blocks = $current_blocks;
|
||||
@@ -426,23 +432,20 @@ function _block_rehash($theme = NULL) {
|
||||
drupal_alter('block_info', $current_blocks, $theme, $code_blocks);
|
||||
foreach ($current_blocks as $module => $module_blocks) {
|
||||
foreach ($module_blocks as $delta => $block) {
|
||||
if (!isset($block['pages'])) {
|
||||
// {block}.pages is type 'text', so it cannot have a
|
||||
// default value, and not null, so we need to provide
|
||||
// value if the module did not.
|
||||
$block['pages'] = '';
|
||||
}
|
||||
// Make sure weight is set.
|
||||
if (!isset($block['weight'])) {
|
||||
$block['weight'] = 0;
|
||||
}
|
||||
// Make sure certain attributes are set.
|
||||
$block += array(
|
||||
'pages' => '',
|
||||
'weight' => 0,
|
||||
'status' => 0,
|
||||
);
|
||||
// Check for active blocks in regions that are not available.
|
||||
if (!empty($block['region']) && $block['region'] != BLOCK_REGION_NONE && !isset($regions[$block['region']]) && $block['status'] == 1) {
|
||||
drupal_set_message(t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => $block['info'], '%region' => $block['region'])), 'warning');
|
||||
// Disabled modules are moved into the BLOCK_REGION_NONE later so no
|
||||
// need to move the block to another region.
|
||||
$block['status'] = 0;
|
||||
}
|
||||
// Set region to none if not enabled and make sure status is set.
|
||||
// Set region to none if not enabled.
|
||||
if (empty($block['status'])) {
|
||||
$block['status'] = 0;
|
||||
$block['region'] = BLOCK_REGION_NONE;
|
||||
@@ -644,7 +647,8 @@ function block_theme_initialize($theme) {
|
||||
$regions = system_region_list($theme, REGIONS_VISIBLE);
|
||||
$result = db_query("SELECT * FROM {block} WHERE theme = :theme", array(':theme' => $default_theme), array('fetch' => PDO::FETCH_ASSOC));
|
||||
foreach ($result as $block) {
|
||||
// If the region isn't supported by the theme, assign the block to the theme's default region.
|
||||
// If the region isn't supported by the theme, assign the block to the
|
||||
// theme's default region.
|
||||
if ($block['status'] && !isset($regions[$block['region']])) {
|
||||
$block['region'] = system_default_region($theme);
|
||||
}
|
||||
@@ -812,17 +816,18 @@ function block_block_list_alter(&$blocks) {
|
||||
// with different case. Ex: /Page, /page, /PAGE.
|
||||
$pages = drupal_strtolower($block->pages);
|
||||
if ($block->visibility < BLOCK_VISIBILITY_PHP) {
|
||||
// Convert the Drupal path to lowercase
|
||||
// Convert the Drupal path to lowercase.
|
||||
$path = drupal_strtolower(drupal_get_path_alias($_GET['q']));
|
||||
// Compare the lowercase internal and lowercase path alias (if any).
|
||||
$page_match = drupal_match_path($path, $pages);
|
||||
if ($path != $_GET['q']) {
|
||||
$page_match = $page_match || drupal_match_path($_GET['q'], $pages);
|
||||
}
|
||||
// When $block->visibility has a value of 0 (BLOCK_VISIBILITY_NOTLISTED),
|
||||
// the block is displayed on all pages except those listed in $block->pages.
|
||||
// When set to 1 (BLOCK_VISIBILITY_LISTED), it is displayed only on those
|
||||
// pages listed in $block->pages.
|
||||
// When $block->visibility has a value of 0
|
||||
// (BLOCK_VISIBILITY_NOTLISTED), the block is displayed on all pages
|
||||
// except those listed in $block->pages. When set to 1
|
||||
// (BLOCK_VISIBILITY_LISTED), it is displayed only on those pages
|
||||
// listed in $block->pages.
|
||||
$page_match = !($block->visibility xor $page_match);
|
||||
}
|
||||
elseif (module_exists('php')) {
|
||||
@@ -845,7 +850,8 @@ function block_block_list_alter(&$blocks) {
|
||||
* Render the content and subject for a set of blocks.
|
||||
*
|
||||
* @param $region_blocks
|
||||
* An array of block objects such as returned for one region by _block_load_blocks().
|
||||
* An array of block objects such as returned for one region by
|
||||
* _block_load_blocks().
|
||||
*
|
||||
* @return
|
||||
* An array of visible blocks as expected by drupal_render().
|
||||
@@ -953,6 +959,8 @@ function _block_render_blocks($region_blocks) {
|
||||
* Theme and language contexts are automatically differentiated.
|
||||
*
|
||||
* @param $block
|
||||
* The block to get the cache_id from.
|
||||
*
|
||||
* @return
|
||||
* The string used as cache_id for the block.
|
||||
*/
|
||||
@@ -967,6 +975,7 @@ function _block_get_cache_id($block) {
|
||||
// Start with common sub-patterns: block identification, theme, language.
|
||||
$cid_parts[] = $block->module;
|
||||
$cid_parts[] = $block->delta;
|
||||
drupal_alter('block_cid_parts', $cid_parts, $block);
|
||||
$cid_parts = array_merge($cid_parts, drupal_render_cid_parts($block->cache));
|
||||
|
||||
return implode(':', $cid_parts);
|
||||
|
||||
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ regions[footer] = Footer
|
||||
regions[highlighted] = Highlighted
|
||||
regions[help] = Help
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = blog.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ function blog_menu_local_tasks_alter(&$data, $router_item, $root_path) {
|
||||
}
|
||||
}
|
||||
// Provide a helper action link to the author on the 'blog/%' page.
|
||||
elseif ($root_path == 'blog/%' && $router_item['page_arguments'][0]->uid == $user->uid) {
|
||||
elseif ($root_path == 'blog/%' && isset($router_item['page_arguments'][0]->uid) && $router_item['page_arguments'][0]->uid == $user->uid) {
|
||||
$data['actions']['output']['blog'] = array(
|
||||
'#theme' => 'menu_local_action',
|
||||
);
|
||||
|
||||
@@ -7,8 +7,8 @@ files[] = book.test
|
||||
configure = admin/content/book/settings
|
||||
stylesheets[all][] = book.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = color.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ class ColorTestCase extends DrupalWebTestCase {
|
||||
$edit['palette[bg]'] = $color;
|
||||
$this->drupalPost($settings_path, $edit, t('Save configuration'));
|
||||
|
||||
if($is_valid) {
|
||||
if ($is_valid) {
|
||||
$this->assertText('The configuration options have been saved.');
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -9,8 +9,8 @@ files[] = comment.test
|
||||
configure = admin/content/comment
|
||||
stylesheets[all][] = comment.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -11,9 +11,15 @@ class CommentHelperCase extends DrupalWebTestCase {
|
||||
protected $node;
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('comment', 'search');
|
||||
$modules = func_get_args();
|
||||
if (isset($modules[0]) && is_array($modules[0])) {
|
||||
$modules = $modules[0];
|
||||
}
|
||||
$modules[] = 'comment';
|
||||
parent::setUp($modules);
|
||||
|
||||
// Create users and test node.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks', 'administer actions'));
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks', 'administer actions', 'administer fields'));
|
||||
$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));
|
||||
}
|
||||
@@ -1490,7 +1496,7 @@ class CommentNodeAccessTest extends CommentHelperCase {
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
DrupalWebTestCase::setUp('comment', 'search', 'node_access_test');
|
||||
parent::setUp('search', 'node_access_test');
|
||||
node_access_rebuild();
|
||||
|
||||
// Create users and test node.
|
||||
|
||||
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = contact.test
|
||||
configure = admin/structure/contact
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -234,7 +234,14 @@ function contact_form_user_profile_form_alter(&$form, &$form_state) {
|
||||
* Implements hook_user_presave().
|
||||
*/
|
||||
function contact_user_presave(&$edit, $account, $category) {
|
||||
$edit['data']['contact'] = isset($edit['contact']) ? $edit['contact'] : variable_get('contact_default_status', 1);
|
||||
if (isset($edit['contact'])) {
|
||||
// Set new value.
|
||||
$edit['data']['contact'] = $edit['contact'];
|
||||
}
|
||||
elseif (!isset($account->data['contact'])) {
|
||||
// Use default if none has been set.
|
||||
$edit['data']['contact'] = variable_get('contact_default_status', 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -346,6 +346,28 @@ class ContactPersonalTestCase extends DrupalWebTestCase {
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Test that users can disable their contact form.
|
||||
$this->drupalLogin($this->contact_user);
|
||||
$edit = array('contact' => FALSE);
|
||||
$this->drupalPost('user/' . $this->contact_user->uid . '/edit', $edit, 'Save');
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test that user's contact status stays disabled when saving.
|
||||
$contact_user_temp = user_load($this->contact_user->uid, TRUE);
|
||||
user_save($contact_user_temp);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test that users can enable their contact form.
|
||||
$this->drupalLogin($this->contact_user);
|
||||
$edit = array('contact' => TRUE);
|
||||
$this->drupalPost('user/' . $this->contact_user->uid . '/edit', $edit, 'Save');
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Revoke the personal contact permission for the anonymous user.
|
||||
user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array('access user contact forms'));
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
|
||||
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = contextual.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ files[] = dashboard.test
|
||||
dependencies[] = block
|
||||
configure = admin/dashboard/customize
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -294,11 +294,18 @@ function theme_dblog_message($variables) {
|
||||
else {
|
||||
$output = t($event->message, unserialize($event->variables));
|
||||
}
|
||||
// If the output is expected to be a link, strip all the tags and
|
||||
// special characters by using filter_xss() without any allowed tags.
|
||||
// If not, use filter_xss_admin() to allow some tags.
|
||||
if ($variables['link'] && isset($event->wid)) {
|
||||
// Truncate message to 56 chars.
|
||||
// Truncate message to 56 chars after stripping all the tags.
|
||||
$output = truncate_utf8(filter_xss($output, array()), 56, TRUE, TRUE);
|
||||
$output = l($output, 'admin/reports/event/' . $event->wid, array('html' => TRUE));
|
||||
}
|
||||
else {
|
||||
// Prevent XSS in log detail pages.
|
||||
$output = filter_xss_admin($output);
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
@@ -413,6 +420,6 @@ function dblog_clear_log_form($form) {
|
||||
*/
|
||||
function dblog_clear_log_submit() {
|
||||
$_SESSION['dblog_overview_filter'] = array();
|
||||
db_delete('watchdog')->execute();
|
||||
db_truncate('watchdog')->execute();
|
||||
drupal_set_message(t('Database log cleared.'));
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = dblog.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -154,6 +154,15 @@ function dblog_update_7002() {
|
||||
db_add_index('watchdog', 'severity', array('severity'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Account for possible legacy systems where dblog was not installed.
|
||||
*/
|
||||
function dblog_update_7003() {
|
||||
if (!db_table_exists('watchdog')) {
|
||||
db_create_table('watchdog', drupal_get_schema_unprocessed('dblog', 'watchdog'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-7.x-extra".
|
||||
*/
|
||||
|
||||
+24
-14
@@ -144,20 +144,30 @@ function _dblog_get_message_types() {
|
||||
* Note: Some values may be truncated to meet database column size restrictions.
|
||||
*/
|
||||
function dblog_watchdog(array $log_entry) {
|
||||
Database::getConnection('default', 'default')->insert('watchdog')
|
||||
->fields(array(
|
||||
'uid' => $log_entry['uid'],
|
||||
'type' => substr($log_entry['type'], 0, 64),
|
||||
'message' => $log_entry['message'],
|
||||
'variables' => serialize($log_entry['variables']),
|
||||
'severity' => $log_entry['severity'],
|
||||
'link' => substr($log_entry['link'], 0, 255),
|
||||
'location' => $log_entry['request_uri'],
|
||||
'referer' => $log_entry['referer'],
|
||||
'hostname' => substr($log_entry['ip'], 0, 128),
|
||||
'timestamp' => $log_entry['timestamp'],
|
||||
))
|
||||
->execute();
|
||||
if (!function_exists('drupal_substr')) {
|
||||
require_once DRUPAL_ROOT . '/includes/unicode.inc';
|
||||
}
|
||||
try {
|
||||
Database::getConnection('default', 'default')->insert('watchdog')
|
||||
->fields(array(
|
||||
'uid' => $log_entry['uid'],
|
||||
'type' => drupal_substr($log_entry['type'], 0, 64),
|
||||
'message' => $log_entry['message'],
|
||||
'variables' => serialize($log_entry['variables']),
|
||||
'severity' => $log_entry['severity'],
|
||||
'link' => drupal_substr($log_entry['link'], 0, 255),
|
||||
'location' => $log_entry['request_uri'],
|
||||
'referer' => $log_entry['referer'],
|
||||
'hostname' => drupal_substr($log_entry['ip'], 0, 128),
|
||||
'timestamp' => $log_entry['timestamp'],
|
||||
))
|
||||
->execute();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Exception is ignored so that watchdog does not break pages during the
|
||||
// installation process or is not able to create the watchdog table during
|
||||
// installation.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -119,13 +119,18 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
private function generateLogEntries($count, $type = 'custom', $severity = WATCHDOG_NOTICE) {
|
||||
global $base_root;
|
||||
|
||||
// This long URL makes it just a little bit harder to pass the link part of
|
||||
// the test with a mix of English words and a repeating series of random
|
||||
// percent-encoded Chinese characters.
|
||||
$link = urldecode('/content/xo%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A%E9%85%B1%E5%87%89%E6%8B%8C%E7%B4%A0%E9%B8%A1%E7%85%A7%E7%83%A7%E9%B8%A1%E9%BB%84%E7%8E%AB%E7%91%B0-%E7%A7%91%E5%B7%9E%E7%9A%84%E5%B0%8F%E4%B9%9D%E5%AF%A8%E6%B2%9F%E7%BB%9D%E7%BE%8E%E9%AB%98%E5%B1%B1%E6%B9%96%E6%B3%8A-lake-isabelle');
|
||||
|
||||
// Prepare the fields to be logged
|
||||
$log = array(
|
||||
'type' => $type,
|
||||
'message' => 'Log entry added to test the dblog row limit.',
|
||||
'variables' => array(),
|
||||
'severity' => $severity,
|
||||
'link' => NULL,
|
||||
'link' => $link,
|
||||
'user' => $this->big_user,
|
||||
'uid' => isset($this->big_user->uid) ? $this->big_user->uid : 0,
|
||||
'request_uri' => $base_root . request_uri(),
|
||||
@@ -515,6 +520,33 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
$this->assertText(t('Database log cleared.'), 'Confirmation message found');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that exceptions are caught in dblog_watchdog().
|
||||
*/
|
||||
protected function testDBLogException() {
|
||||
$log = array(
|
||||
'type' => 'custom',
|
||||
'message' => 'Log entry added to test watchdog handling of Exceptions.',
|
||||
'variables' => array(),
|
||||
'severity' => WATCHDOG_NOTICE,
|
||||
'link' => NULL,
|
||||
'user' => $this->big_user,
|
||||
'uid' => isset($this->big_user->uid) ? $this->big_user->uid : 0,
|
||||
'request_uri' => request_uri(),
|
||||
'referer' => $_SERVER['HTTP_REFERER'],
|
||||
'ip' => ip_address(),
|
||||
'timestamp' => REQUEST_TIME,
|
||||
);
|
||||
|
||||
// Remove watchdog table temporarily to simulate it missing during
|
||||
// installation.
|
||||
db_query("DROP TABLE {watchdog}");
|
||||
|
||||
// Add a watchdog entry.
|
||||
// This should not throw an Exception, but fail silently.
|
||||
dblog_watchdog($log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the database log event information from the browser page.
|
||||
*
|
||||
@@ -633,5 +665,32 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
// Document Object Model (DOM).
|
||||
$this->assertLink(html_entity_decode($message_text), 0, $message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure HTML tags are filtered out in the log detail page.
|
||||
*/
|
||||
public function testLogMessageSanitized() {
|
||||
$this->drupalLogin($this->big_user);
|
||||
|
||||
// Make sure dangerous HTML tags are filtered out in log detail page.
|
||||
$log = array(
|
||||
'uid' => 0,
|
||||
'type' => 'custom',
|
||||
'message' => "<script>alert('foo');</script> <strong>Lorem ipsum</strong>",
|
||||
'variables' => NULL,
|
||||
'severity' => WATCHDOG_NOTICE,
|
||||
'link' => 'foo/bar',
|
||||
'request_uri' => 'http://example.com?dblog=1',
|
||||
'referer' => 'http://example.org?dblog=2',
|
||||
'ip' => '0.0.1.0',
|
||||
'timestamp' => REQUEST_TIME,
|
||||
);
|
||||
dblog_watchdog($log);
|
||||
|
||||
$wid = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField();
|
||||
$this->drupalGet('admin/reports/event/' . $wid);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoRaw("<script>alert('foo');</script>");
|
||||
$this->assertRaw("alert('foo'); <strong>Lorem ipsum</strong>");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ function field_create_field($field) {
|
||||
}
|
||||
|
||||
// Clear caches
|
||||
field_cache_clear(TRUE);
|
||||
field_cache_clear();
|
||||
|
||||
// Invoke external hooks after the cache is cleared for API consistency.
|
||||
module_invoke_all('field_create_field', $field);
|
||||
@@ -288,7 +288,7 @@ function field_update_field($field) {
|
||||
drupal_write_record('field_config', $field, $primary_key);
|
||||
|
||||
// Clear caches
|
||||
field_cache_clear(TRUE);
|
||||
field_cache_clear();
|
||||
|
||||
// Invoke external hooks after the cache is cleared for API consistency.
|
||||
module_invoke_all('field_update_field', $field, $prior_field, $has_data);
|
||||
@@ -430,7 +430,7 @@ function field_delete_field($field_name) {
|
||||
->execute();
|
||||
|
||||
// Clear the cache.
|
||||
field_cache_clear(TRUE);
|
||||
field_cache_clear();
|
||||
|
||||
module_invoke_all('field_delete_field', $field);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ dependencies[] = field_sql_storage
|
||||
required = TRUE
|
||||
stylesheets[all][] = theme/field.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -612,10 +612,12 @@ class FieldInfo {
|
||||
// Fill in default values.
|
||||
$display += array(
|
||||
'label' => 'above',
|
||||
'type' => $field_type_info['default_formatter'],
|
||||
'settings' => array(),
|
||||
'weight' => 0,
|
||||
);
|
||||
if (empty($display['type'])) {
|
||||
$display['type'] = $field_type_info['default_formatter'];
|
||||
}
|
||||
if ($display['type'] != 'hidden') {
|
||||
$formatter_type_info = field_info_formatter_types($display['type']);
|
||||
// Fall back to default formatter if formatter type is not available.
|
||||
|
||||
@@ -467,6 +467,27 @@ function field_update_7003() {
|
||||
// Empty update to force a rebuild of the registry.
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant the new "administer fields" permission to trusted users.
|
||||
*/
|
||||
function field_update_7004() {
|
||||
// Assign the permission to anyone that already has a trusted core permission
|
||||
// that would have previously let them administer fields on an entity type.
|
||||
$rids = array();
|
||||
$permissions = array(
|
||||
'administer site configuration',
|
||||
'administer content types',
|
||||
'administer users',
|
||||
);
|
||||
foreach ($permissions as $permission) {
|
||||
$rids = array_merge($rids, array_keys(user_roles(FALSE, $permission)));
|
||||
}
|
||||
$rids = array_unique($rids);
|
||||
foreach ($rids as $rid) {
|
||||
_update_7000_user_role_grant_permissions($rid, array('administer fields'), 'field');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-7.x-extra".
|
||||
*/
|
||||
|
||||
@@ -316,6 +316,21 @@ function field_help($path, $arg) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function field_permission() {
|
||||
return array(
|
||||
'administer fields' => array(
|
||||
'title' => t('Administer fields'),
|
||||
'description' => t('Additional permissions are required based on what the fields are attached to (for example, <a href="@url">administer content types</a> to manage fields attached to content).', array(
|
||||
'@url' => '#module-node',
|
||||
)),
|
||||
'restrict access' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
|
||||
@@ -7,8 +7,8 @@ dependencies[] = field
|
||||
files[] = field_sql_storage.test
|
||||
required = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -223,7 +223,17 @@ function _field_sql_storage_schema($field) {
|
||||
foreach ($field['indexes'] as $index_name => $columns) {
|
||||
$real_name = _field_sql_storage_indexname($field['field_name'], $index_name);
|
||||
foreach ($columns as $column_name) {
|
||||
$current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
|
||||
// Indexes can be specified as either a column name or an array with
|
||||
// column name and length. Allow for either case.
|
||||
if (is_array($column_name)) {
|
||||
$current['indexes'][$real_name][] = array(
|
||||
_field_sql_storage_columnname($field['field_name'], $column_name[0]),
|
||||
$column_name[1],
|
||||
);
|
||||
}
|
||||
else {
|
||||
$current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +342,17 @@ function field_sql_storage_field_storage_update_field($field, $prior_field, $has
|
||||
$real_name = _field_sql_storage_indexname($field['field_name'], $name);
|
||||
$real_columns = array();
|
||||
foreach ($columns as $column_name) {
|
||||
$real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
|
||||
// Indexes can be specified as either a column name or an array with
|
||||
// column name and length. Allow for either case.
|
||||
if (is_array($column_name)) {
|
||||
$real_columns[] = array(
|
||||
_field_sql_storage_columnname($field['field_name'], $column_name[0]),
|
||||
$column_name[1],
|
||||
);
|
||||
}
|
||||
else {
|
||||
$real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
|
||||
}
|
||||
}
|
||||
db_add_index($table, $real_name, $real_columns);
|
||||
db_add_index($revision_table, $real_name, $real_columns);
|
||||
|
||||
@@ -355,14 +355,14 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
|
||||
field_attach_insert('test_entity', $entity);
|
||||
|
||||
// Add an index
|
||||
$field = array('field_name' => $field_name, 'indexes' => array('value' => array('value')));
|
||||
$field = array('field_name' => $field_name, 'indexes' => array('value' => array(array('value', 255))));
|
||||
field_update_field($field);
|
||||
foreach ($tables as $table) {
|
||||
$this->assertTrue(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value"), format_string("Index on value created in %table", array('%table' => $table)));
|
||||
}
|
||||
|
||||
// Add a different index, removing the existing custom one.
|
||||
$field = array('field_name' => $field_name, 'indexes' => array('value_format' => array('value', 'format')));
|
||||
$field = array('field_name' => $field_name, 'indexes' => array('value_format' => array(array('value', 127), array('format', 127))));
|
||||
field_update_field($field);
|
||||
foreach ($tables as $table) {
|
||||
$this->assertTrue(Database::getConnection()->schema()->indexExists($table, "{$field_name}_value_format"), format_string("Index on value_format created in %table", array('%table' => $table)));
|
||||
|
||||
@@ -7,8 +7,8 @@ dependencies[] = field
|
||||
dependencies[] = options
|
||||
files[] = tests/list.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ class ListFieldUITestCase extends FieldTestCase {
|
||||
parent::setUp('field_test', 'field_ui');
|
||||
|
||||
// Create test user.
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Create content type, with underscores.
|
||||
|
||||
@@ -5,8 +5,8 @@ package = Testing
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = number.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
@@ -164,6 +164,15 @@ function number_field_presave($entity_type, $entity, $field, $instance, $langcod
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($field['type'] == 'number_float') {
|
||||
// Remove the decimal point from float values with decimal
|
||||
// point but no decimal numbers.
|
||||
foreach ($items as $delta => $item) {
|
||||
if (isset($item['value'])) {
|
||||
$items[$delta]['value'] = floatval($item['value']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +197,7 @@ function number_field_formatter_info() {
|
||||
'label' => t('Default'),
|
||||
'field types' => array('number_integer'),
|
||||
'settings' => array(
|
||||
'thousand_separator' => ' ',
|
||||
'thousand_separator' => '',
|
||||
// The 'decimal_separator' and 'scale' settings are not configurable
|
||||
// through the UI, and will therefore keep their default values. They
|
||||
// are only present so that the 'number_integer' and 'number_decimal'
|
||||
@@ -202,7 +211,7 @@ function number_field_formatter_info() {
|
||||
'label' => t('Default'),
|
||||
'field types' => array('number_decimal', 'number_float'),
|
||||
'settings' => array(
|
||||
'thousand_separator' => ' ',
|
||||
'thousand_separator' => '',
|
||||
'decimal_separator' => '.',
|
||||
'scale' => 2,
|
||||
'prefix_suffix' => TRUE,
|
||||
@@ -222,6 +231,8 @@ function number_field_formatter_settings_form($field, $instance, $view_mode, $fo
|
||||
$display = $instance['display'][$view_mode];
|
||||
$settings = $display['settings'];
|
||||
|
||||
$element = array();
|
||||
|
||||
if ($display['type'] == 'number_decimal' || $display['type'] == 'number_integer') {
|
||||
$options = array(
|
||||
'' => t('<none>'),
|
||||
|
||||
@@ -23,7 +23,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('field_test');
|
||||
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types'));
|
||||
$this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types', 'administer fields'));
|
||||
$this->drupalLogin($this->web_user);
|
||||
}
|
||||
|
||||
@@ -152,4 +152,50 @@ class NumberFieldTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test number_float field.
|
||||
*/
|
||||
function testNumberFloatField() {
|
||||
$this->field = array(
|
||||
'field_name' => drupal_strtolower($this->randomName()),
|
||||
'type' => 'number_float',
|
||||
'settings' => array(
|
||||
'precision' => 8, 'scale' => 4, 'decimal_separator' => '.',
|
||||
)
|
||||
);
|
||||
field_create_field($this->field);
|
||||
$this->instance = array(
|
||||
'field_name' => $this->field['field_name'],
|
||||
'entity_type' => 'test_entity',
|
||||
'bundle' => 'test_bundle',
|
||||
'widget' => array(
|
||||
'type' => 'number',
|
||||
),
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'type' => 'number_float',
|
||||
),
|
||||
),
|
||||
);
|
||||
field_create_instance($this->instance);
|
||||
|
||||
$langcode = LANGUAGE_NONE;
|
||||
$value = array(
|
||||
'9.' => '9',
|
||||
'.' => '0',
|
||||
'123.55' => '123.55',
|
||||
'.55' => '0.55',
|
||||
'-0.55' => '-0.55',
|
||||
);
|
||||
foreach($value as $key => $value) {
|
||||
$edit = array(
|
||||
"{$this->field['field_name']}[$langcode][0][value]" => $key,
|
||||
);
|
||||
$this->drupalPost('test-entity/add/test-bundle', $edit, t('Save'));
|
||||
$this->assertNoText("PDOException");
|
||||
$this->assertRaw($value, 'Correct value is displayed.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = options.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-04-02
|
||||
version = "7.36"
|
||||
; Information added by Drupal.org packaging script on 2017-06-21
|
||||
version = "7.56"
|
||||
project = "drupal"
|
||||
datestamp = "1427943826"
|
||||
datestamp = "1498069849"
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user