Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7580376050 | ||
|
|
acaa381d3d | ||
|
|
c3011cef61 | ||
|
|
10de06dd70 | ||
|
|
572f88b950 | ||
|
|
cb791f03ff | ||
|
|
33ce5d0e40 | ||
|
|
8e478340a2 | ||
|
|
78fa0756a9 | ||
|
|
176b1c05d9 | ||
|
|
acbf965c77 | ||
|
|
bd98c3d7f6 | ||
|
|
1c56076189 | ||
|
|
e0ab0fd0d5 | ||
|
|
b58a00a4c8 | ||
|
|
4d81ea318d | ||
|
|
77cb87b49d | ||
|
|
5203118606 | ||
|
|
9faad4a27d | ||
|
|
32e4448773 | ||
|
|
e539e701f8 | ||
|
|
db5f70501a | ||
|
|
f1c9615e4a | ||
|
|
84542b241d | ||
|
|
e99ac67b73 | ||
|
|
5a4cadabf6 | ||
|
|
5658794f17 | ||
|
|
d5097a4bc6 | ||
|
|
661765bde9 | ||
|
|
fde4f26165 | ||
|
|
8763bf01dd | ||
|
|
49fb38b169 | ||
|
|
de022d62e2 | ||
|
|
d9d092295b |
@@ -116,6 +116,24 @@ 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>
|
||||
|
||||
@@ -1,4 +1,240 @@
|
||||
|
||||
Drupal 7.28, 2014-05-08
|
||||
-----------------------
|
||||
- Fixed a regression introduced in Drupal 7.27 that caused JavaScript to break
|
||||
on older browsers (such as Internet Explorer 8 and earlier) when Ajax was
|
||||
used.
|
||||
- Increased the timeout used by the Update Manager module when it fetches data
|
||||
from drupal.org (from 5 seconds to 30 seconds), to work around a problem
|
||||
which causes incomplete information about security updates to be presented to
|
||||
site administrators. This fix may lead to a performance slowdown on the
|
||||
Update Manager administration pages, when installing Drupal distributions,
|
||||
and (for sites that use the automated cron feature) on occasional page loads
|
||||
by site visitors.
|
||||
- Fixed the behavior of the token system's "[node:summary]" token when the body
|
||||
field does not have a manual summary.
|
||||
- Changed the behavior of db_query_temporary() so that it works on SELECT
|
||||
queries even when they have leading comments/whitespace. A side effect of
|
||||
this fix is that db_query_temporary() will now fail with an error if it is
|
||||
ever used on non-SELECT queries.
|
||||
- Added a "node_admin_filter" tag to the database query used to build the list
|
||||
of nodes on the content administration page, to make it easier to alter.
|
||||
- Made the cron queue system log any exceptions that are thrown while an item
|
||||
in the queue is being processed, rather than stopping the entire PHP request.
|
||||
- Improved screen reader support by adding an aria-live HTML attribute to file
|
||||
upload fields when there is an error uploading the file (minor markup
|
||||
change).
|
||||
- Made the pager on the Tracker module listing pages show the same number of
|
||||
items as other pagers throughout Drupal core (minor UI change).
|
||||
- Fixed a bug which caused caches not to be properly cleared when a file entity
|
||||
was saved or deleted.
|
||||
- Added several missing countries to the default list returned by
|
||||
country_get_list() (string change).
|
||||
- Replaced the term "weight" with "influence" in the content ranking settings
|
||||
for search, and added help text for administrators (string change).
|
||||
- Fixed untranslatable text strings in the administrative interface for the
|
||||
"Crop" effect provided by the Image module (minor string change).
|
||||
- Fixed a bug in the Taxonomy module update function introduced in Drupal 7.26
|
||||
that caused memory and CPU problems on sites with very large numbers of
|
||||
unpublished nodes.
|
||||
- Numerous small bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- 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
|
||||
-----------------------
|
||||
- Fixed a bug in node_save() which prevented the saved node from being updated
|
||||
in hook_node_insert() and other similar hooks.
|
||||
- Added a meta tag to install.php to prevent it from being indexed by search
|
||||
engines even when Drupal is installed in a subfolder (minor markup change).
|
||||
- Fixed a bug in the database API that caused frequent deadlock errors when
|
||||
running merge queries on some servers.
|
||||
- Performance improvement: Prevented block rehashing from writing blocks to the
|
||||
database on every cache clear and cron run when the blocks have not changed.
|
||||
This fix results in an extra 'saved' key which is added and set to TRUE for
|
||||
each block returned by _block_rehash() that actually is saved to the database
|
||||
(data structure change).
|
||||
- Added an optional 'skip on cron' parameter to hook_cron_queue_info() to allow
|
||||
queues to avoid being automatically processed on cron runs (API addition).
|
||||
- Fixed a bug which caused hook_block_view_MODULE_DELTA_alter() to never be
|
||||
invoked if the block delta had a hyphen in it. To implement the hook when the
|
||||
block delta has a hyphen, modules should now replace hyphens with underscores
|
||||
when constructing the function name for the hook implementation.
|
||||
- Fixed a bug which caused cached pages to sometimes be sent to the browser
|
||||
with incorrect compression. The fix adds a new 'page_compressed' key to the
|
||||
$cache->data array returned by drupal_page_get_cache() (minor data structure
|
||||
change).
|
||||
- Fixed broken tests on PHP 5.5.
|
||||
- Made the File and Image modules more robust when saving entities that have
|
||||
deleted files attached. The code in file_field_presave() will now remove the
|
||||
record of the deleted file from the entity before saving (minor data
|
||||
structure change).
|
||||
- Standardized menu callback functions throughout Drupal core to return
|
||||
MENU_NOT_FOUND and MENU_ACCESS_DENIED rather than printing their own "page
|
||||
not found" or "access denied" pages (minor API change in the return value of
|
||||
these functions under some circumstances).
|
||||
- Fixed a bug in which caches were not properly cleared when a node was deleted
|
||||
via the administrative interface.
|
||||
- Changed the Bartik theme to render content contained in <pre>, <code> and
|
||||
similar tags in a larger font size, so it is easier to read.
|
||||
- Fixed a bug in the Search module that caused exceptions to be thrown during
|
||||
searches if the server was not configured to represent decimal points as a
|
||||
period.
|
||||
- Fixed a regression in the Image module that made image_style_url() not work
|
||||
when a relative path (rather than a complete file URI) was passed to it.
|
||||
- Added an optional feature to the Statistics module to allow node views to be
|
||||
tracked by Ajax requests rather than during the server-side generation of the
|
||||
page. This allows the node counter to work on sites that use external page
|
||||
caches (string change and new administrative option:
|
||||
https://drupal.org/node/2164069).
|
||||
- Added a link to the drupal.org documentation page for cron to the Cron
|
||||
settings page (string change).
|
||||
- Added a 'drupal_anonymous_user_object' variable to allow the anonymous user
|
||||
object returned by drupal_anonymous_user() to be overridden with a classed
|
||||
object (API addition).
|
||||
- Changed the database API to allow inserts based on a SELECT * query to work
|
||||
correctly.
|
||||
- Changed the database schema of the {file_managed} table to allow Drupal to
|
||||
manage files larger than 4 GB.
|
||||
- Changed the File module's hook_field_load() implementation to prevent file
|
||||
entity properties which have the same name as file or image field properties
|
||||
from overwriting the field properties (minor API change).
|
||||
- Numerous small bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- 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
|
||||
-----------------------
|
||||
- Fixed a fatal error on PostgreSQL databases when updating the Taxonomy module
|
||||
from Drupal 6 to Drupal 7.
|
||||
- Fixed the default ordering of CSS files for sites using right-to-left
|
||||
languages, to consistently place the right-to-left override file immediately
|
||||
after the CSS it is overriding (API change: https://drupal.org/node/2058463).
|
||||
- Added a drupal_check_memory_limit() API function to allow the memory limit to
|
||||
be checked consistently (API addition).
|
||||
- Changed the default web.config file for IIS servers to allow favicon.ico
|
||||
files which are present in the filesystem to be accessed.
|
||||
- Fixed inconsistent support for the 'tel' protocol in Drupal's URL filtering
|
||||
functions.
|
||||
- Performance improvement: Allowed all hooks to be included in the
|
||||
module_implements() cache, even those that are only invoked on HTTP POST
|
||||
requests.
|
||||
- Made the database system replace truncate queries with delete queries when
|
||||
inside a transaction, to fix issues with PostgreSQL and other databases.
|
||||
- Fixed a bug which caused nested contextual links to display improperly.
|
||||
- Fixed a bug which prevented cached image derivatives from being flushed for
|
||||
private files and other non-default file schemes.
|
||||
- Fixed drupal_render() to always return an empty string when there is no
|
||||
output, rather than sometimes returning NULL (minor API change).
|
||||
- Added protection to cache_clear_all() to ensure that non-cache tables cannot
|
||||
be truncated (API addition: a new isValidBin() method has been added to the
|
||||
default database cache implementation).
|
||||
- Changed the default .htaccess file to support HTTP authorization in CGI
|
||||
environments.
|
||||
- Changed the password reset form to pre-fill the username when requested via a
|
||||
URL query parameter, and used this in the error message that appears after a
|
||||
failed login attempt (minor data structure and behavior change).
|
||||
- Fixed broken support for foreign keys in the field API.
|
||||
- Fixed "No active batch" error when a user cancels their own account.
|
||||
- Added a description to the "access content overview" permission on the
|
||||
permissions page (string change).
|
||||
- Added a drupal_array_diff_assoc_recursive() function to allow associative
|
||||
arrays to be compared recursively (API addition).
|
||||
- Added human-readable labels to image styles, in addition to the existing
|
||||
machine-readable name (API change: https://drupal.org/node/2058503).
|
||||
- Moved the drupal_get_hash_salt() function to bootstrap.inc and used it in
|
||||
additional places in the code, for added security in the case where there is
|
||||
no hash salt in settings.php.
|
||||
- Fixed a regression in Drupal 7.22 that caused internal server errors for
|
||||
sites running on very old Apache 1.x web servers.
|
||||
- Numerous small bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.22, 2013-04-03
|
||||
-----------------------
|
||||
- Allowed the drupal_http_request() function to be overridden so that
|
||||
additional HTTP request capabilities can be added by contributed modules.
|
||||
- Changed the Simpletest module to allow PSR-0 test classes to be used in
|
||||
Drupal 7.
|
||||
- Removed an unnecessary "Content-Disposition" header from private file
|
||||
downloads; it prevented many private files from being viewed inline in a web
|
||||
browser.
|
||||
- Changed various field API functions to allow them to optionally act on a
|
||||
single field within an entity (API addition: http://drupal.org/node/1825844).
|
||||
- Fixed a bug which prevented Drupal's file transfer functionality from working
|
||||
on some PHP 5.4 systems.
|
||||
- Fixed incorrect log message when theme() is called for a theme hook that does
|
||||
not exist (minor string change).
|
||||
- Fixed Drupal's token-replacement system to allow spaces in the token value.
|
||||
- Changed the default behavior after a user creates a node they do not have
|
||||
access to view. The user will now be redirected to the front page rather than
|
||||
an access denied page.
|
||||
- Fixed a bug which prevented empty HTTP headers (such as "0") from being set.
|
||||
(Minor behavior change: Callers of drupal_add_http_header() must now set
|
||||
FALSE explicitly to prevent a header from being sent at all; this was already
|
||||
indicated in the function's documentation.)
|
||||
- Fixed OpenID errors when more than one module implements hook_openid(). The
|
||||
behavior is now changed so that if more than one module tries to set the same
|
||||
parameter, the last module's change takes effect.
|
||||
- Fixed a serious documentation bug: The $name variable in the
|
||||
taxonomy-term.tpl.php theme template was incorrectly documented as being
|
||||
sanitized when in fact it is not.
|
||||
- Fixed a bug which prevented Drupal 6 to Drupal 7 upgrades on sites which had
|
||||
duplicate permission names in the User module's database tables.
|
||||
- Added an empty "datatype" attribute to taxonomy term and username links to
|
||||
make the RDFa markup upward compatible with RDFa 1.1 (minor markup addition).
|
||||
- Fixed a bug which caused the denial-of-service protection added in Drupal
|
||||
7.20 to break certain valid image URLs that had an extra slash in them.
|
||||
- Fixed a bug with update queries in the SQLite database driver that prevented
|
||||
Drupal from being installed with SQLite on PHP 5.4.
|
||||
- Fixed enforced dependencies errors updating to recent versions of Drupal 7 on
|
||||
certain non-MySQL databases.
|
||||
- Refactored the Field module's caching behavior to obtain large improvements
|
||||
in memory usage for sites with many fields and instances (API addition:
|
||||
http://drupal.org/node/1915646).
|
||||
- Fixed entity argument not being passed to implementations of
|
||||
hook_file_download_access_alter(). The fix adds an additional context
|
||||
parameter that can be passed when calling drupal_alter() for any hook (API
|
||||
change: http://drupal.org/node/1882722).
|
||||
- Fixed broken support for translatable comment fields (API change:
|
||||
http://drupal.org/node/1874724).
|
||||
- Added an assertThemeOutput() method to Simpletest to allow tests to check
|
||||
that themed output matches an expected HTML string (API addition).
|
||||
- Added a link to "Install another module" after a module has been successfully
|
||||
downloaded via the Update Manager (UI change).
|
||||
- Added an optional "exclusive" flag to installation profile .info files which
|
||||
allows Drupal distributions to force a profile to be selected during
|
||||
installation (API addition: http://drupal.org/node/1961012).
|
||||
- Fixed a bug which caused the database API to not properly close database
|
||||
connections.
|
||||
- Added a link to the URL for running cron from outside the site to the Cron
|
||||
settings page (UI change).
|
||||
- Fixed a bug which prevented image styles from being reverted on PHP 5.4.
|
||||
- Made the default .htaccess rules protocol sensitive to improve security for
|
||||
sites which use HTTPS and redirect between "www" and non-"www" versions of
|
||||
the page.
|
||||
- Numerous small bug fixes.
|
||||
- Numerous API documentation improvements.
|
||||
- Additional automated test coverage.
|
||||
|
||||
Drupal 7.21, 2013-03-06
|
||||
-----------------------
|
||||
- Allowed sites using the 'image_allow_insecure_derivatives' variable to still
|
||||
have partial protection from the security issues fixed in Drupal 7.20.
|
||||
|
||||
Drupal 7.20, 2013-02-20
|
||||
-----------------------
|
||||
- Fixed security issues (denial of service). See SA-CORE-2013-002.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
All Drupal code is Copyright 2001 - 2012 by the original authors.
|
||||
All Drupal code is Copyright 2001 - 2013 by the original authors.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
|
||||
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
|
||||
ON databasename.*
|
||||
TO 'username'@'localhost' IDENTIFIED BY 'password';
|
||||
|
||||
where
|
||||
|
||||
'databasename' is the name of your database
|
||||
'username@localhost' is the username of your MySQL account
|
||||
'password' is the password required for that username
|
||||
|
||||
Note: Unless your database user has all of the privileges listed above, you will
|
||||
not be able to 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.
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
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.
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
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.
|
||||
@@ -1,398 +0,0 @@
|
||||
|
||||
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.
|
||||
- PostgreSQL 8.3 (or greater) (http://www.postgresql.org/).
|
||||
- SQLite 3.4.2 (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.
|
||||
@@ -71,12 +71,12 @@ profiles/your_site_profile/themes respectively to restrict their usage to only
|
||||
sites that were installed with that specific profile.
|
||||
|
||||
More about installation profiles and distributions:
|
||||
* Read about the difference between installation profiles and distributions:
|
||||
http://drupal.org/node/1089736
|
||||
* Download contributed installation profiles and distributions:
|
||||
http://drupal.org/project/distributions
|
||||
* Develop your own installation profile or distribution:
|
||||
http://drupal.org/developing/distributions
|
||||
* Read about the difference between installation profiles and distributions:
|
||||
http://drupal.org/node/1089736
|
||||
* Download contributed installation profiles and distributions:
|
||||
http://drupal.org/project/distributions
|
||||
* Develop your own installation profile or distribution:
|
||||
http://drupal.org/developing/distributions
|
||||
|
||||
APPEARANCE
|
||||
----------
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
* @file
|
||||
* Administrative script for running authorized file operations.
|
||||
*
|
||||
* Using this script, the site owner (the user actually owning the files on
|
||||
* the webserver) can authorize certain file-related operations to proceed
|
||||
* with elevated privileges, for example to deploy and upgrade modules or
|
||||
* themes. Users should not visit this page directly, but instead use an
|
||||
* administrative user interface which knows how to redirect the user to this
|
||||
* script as part of a multistep process. This script actually performs the
|
||||
* selected operations without loading all of Drupal, to be able to more
|
||||
* gracefully recover from errors. Access to the script is controlled by a
|
||||
* global killswitch in settings.php ('allow_authorize_operations') and via
|
||||
* the 'administer software updates' permission.
|
||||
* Using this script, the site owner (the user actually owning the files on the
|
||||
* webserver) can authorize certain file-related operations to proceed with
|
||||
* elevated privileges, for example to deploy and upgrade modules or themes.
|
||||
* Users should not visit this page directly, but instead use an administrative
|
||||
* user interface which knows how to redirect the user to this script as part of
|
||||
* a multistep process. This script actually performs the selected operations
|
||||
* without loading all of Drupal, to be able to more gracefully recover from
|
||||
* errors. Access to the script is controlled by a global killswitch in
|
||||
* settings.php ('allow_authorize_operations') and via the 'administer software
|
||||
* updates' permission.
|
||||
*
|
||||
* There are helper functions for setting up an operation to run via this
|
||||
* system in modules/system/system.module. For more information, see:
|
||||
@@ -21,16 +21,17 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Root directory of Drupal installation.
|
||||
* Defines the root directory of the Drupal installation.
|
||||
*/
|
||||
define('DRUPAL_ROOT', getcwd());
|
||||
|
||||
/**
|
||||
* Global flag to identify update.php and authorize.php runs, and so
|
||||
* avoid various unwanted operations, such as hook_init() and
|
||||
* hook_exit() invokes, css/js preprocessing and translation, and
|
||||
* solve some theming issues. This flag is checked on several places
|
||||
* in Drupal code (not just authorize.php).
|
||||
* Global flag to identify update.php and authorize.php runs.
|
||||
*
|
||||
* Identifies update.php and authorize.php runs, avoiding unwanted operations
|
||||
* such as hook_init() and hook_exit() invokes, css/js preprocessing and
|
||||
* translation, and solves some theming issues. The flag is checked in other
|
||||
* places in Drupal code (not just authorize.php).
|
||||
*/
|
||||
define('MAINTENANCE_MODE', 'update');
|
||||
|
||||
@@ -51,7 +52,7 @@ function authorize_access_denied_page() {
|
||||
* have access to the 'administer software updates' permission.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the current user can run authorize.php, otherwise FALSE.
|
||||
* TRUE if the current user can run authorize.php, and FALSE if not.
|
||||
*/
|
||||
function authorize_access_allowed() {
|
||||
return variable_get('allow_authorize_operations', TRUE) && user_access('administer software updates');
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
diff --git a/includes/entity.inc b/includes/entity.inc
|
||||
index 2fefd59..0b80d53 100644
|
||||
--- a/includes/entity.inc
|
||||
+++ b/includes/entity.inc
|
||||
@@ -159,6 +159,18 @@ 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.
|
||||
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 862 B |
@@ -251,8 +251,8 @@ function ajax_render($commands = array()) {
|
||||
// reliably diffed with array_diff_key(), since the number can change
|
||||
// due to factors unrelated to the inline content, so for now, we strip
|
||||
// the inline items from Ajax responses, and can add support for them
|
||||
// when drupal_add_css() and drupal_add_js() are changed to using md5()
|
||||
// or some other hash of the inline content.
|
||||
// when drupal_add_css() and drupal_add_js() are changed to use a hash
|
||||
// of the inline content as the array key.
|
||||
foreach ($items[$type] as $key => $item) {
|
||||
if (is_numeric($key)) {
|
||||
unset($items[$type][$key]);
|
||||
@@ -308,10 +308,11 @@ function ajax_render($commands = array()) {
|
||||
* pulls the form info from $_POST.
|
||||
*
|
||||
* @return
|
||||
* An array containing the $form and $form_state. Use the list() function
|
||||
* to break these apart:
|
||||
* An array containing the $form, $form_state, $form_id, $form_build_id and an
|
||||
* initial list of Ajax $commands. Use the list() function to break these
|
||||
* apart:
|
||||
* @code
|
||||
* list($form, $form_state, $form_id, $form_build_id) = ajax_get_form();
|
||||
* list($form, $form_state, $form_id, $form_build_id, $commands) = ajax_get_form();
|
||||
* @endcode
|
||||
*/
|
||||
function ajax_get_form() {
|
||||
@@ -331,6 +332,17 @@ function ajax_get_form() {
|
||||
drupal_exit();
|
||||
}
|
||||
|
||||
// When a page level cache is enabled, the form-build id might have been
|
||||
// replaced from within form_get_cache. If this is the case, it is also
|
||||
// necessary to update it in the browser by issuing an appropriate Ajax
|
||||
// command.
|
||||
$commands = array();
|
||||
if (isset($form['#build_id_old']) && $form['#build_id_old'] != $form['#build_id']) {
|
||||
// If the form build ID has changed, issue an Ajax command to update it.
|
||||
$commands[] = ajax_command_update_build_id($form);
|
||||
$form_build_id = $form['#build_id'];
|
||||
}
|
||||
|
||||
// Since some of the submit handlers are run, redirects need to be disabled.
|
||||
$form_state['no_redirect'] = TRUE;
|
||||
|
||||
@@ -345,7 +357,7 @@ function ajax_get_form() {
|
||||
$form_state['input'] = $_POST;
|
||||
$form_id = $form['#form_id'];
|
||||
|
||||
return array($form, $form_state, $form_id, $form_build_id);
|
||||
return array($form, $form_state, $form_id, $form_build_id, $commands);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -366,7 +378,7 @@ function ajax_get_form() {
|
||||
* @see system_menu()
|
||||
*/
|
||||
function ajax_form_callback() {
|
||||
list($form, $form_state) = ajax_get_form();
|
||||
list($form, $form_state, $form_id, $form_build_id, $commands) = ajax_get_form();
|
||||
drupal_process_form($form['#form_id'], $form, $form_state);
|
||||
|
||||
// We need to return the part of the form (or some other content) that needs
|
||||
@@ -379,7 +391,19 @@ function ajax_form_callback() {
|
||||
$callback = $form_state['triggering_element']['#ajax']['callback'];
|
||||
}
|
||||
if (!empty($callback) && function_exists($callback)) {
|
||||
return $callback($form, $form_state);
|
||||
$result = $callback($form, $form_state);
|
||||
|
||||
if (!(is_array($result) && isset($result['#type']) && $result['#type'] == 'ajax')) {
|
||||
// Turn the response into a #type=ajax array if it isn't one already.
|
||||
$result = array(
|
||||
'#type' => 'ajax',
|
||||
'#commands' => ajax_prepare_response($result),
|
||||
);
|
||||
}
|
||||
|
||||
$result['#commands'] = array_merge($commands, $result['#commands']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -836,7 +860,8 @@ function ajax_command_insert($selector, $html, $settings = NULL) {
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*
|
||||
* See @link http://docs.jquery.com/Manipulation/replaceWith#content jQuery replaceWith command @endlink
|
||||
* See
|
||||
* @link http://docs.jquery.com/Manipulation/replaceWith#content jQuery replaceWith command @endlink
|
||||
*/
|
||||
function ajax_command_replace($selector, $html, $settings = NULL) {
|
||||
return array(
|
||||
@@ -1209,3 +1234,26 @@ function ajax_command_restripe($selector) {
|
||||
'selector' => $selector,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Drupal Ajax 'update_build_id' command.
|
||||
*
|
||||
* This command updates the value of a hidden form_build_id input element on a
|
||||
* form. It requires the form passed in to have keys for both the old build ID
|
||||
* in #build_id_old and the new build ID in #build_id.
|
||||
*
|
||||
* The primary use case for this Ajax command is to serve a new build ID to a
|
||||
* form served from the cache to an anonymous user, preventing one anonymous
|
||||
* user from accessing the form state of another anonymous users on Ajax enabled
|
||||
* forms.
|
||||
*
|
||||
* @param $form
|
||||
* The form array representing the form whose build ID should be updated.
|
||||
*/
|
||||
function ajax_command_update_build_id($form) {
|
||||
return array(
|
||||
'command' => 'updateBuildId',
|
||||
'old' => $form['#build_id_old'],
|
||||
'new' => $form['#build_id'],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/**
|
||||
* The current system version.
|
||||
*/
|
||||
define('VERSION', '7.20');
|
||||
define('VERSION', '7.28');
|
||||
|
||||
/**
|
||||
* Core API compatibility.
|
||||
@@ -218,12 +218,16 @@ define('LANGUAGE_RTL', 1);
|
||||
define('REQUEST_TIME', (int) $_SERVER['REQUEST_TIME']);
|
||||
|
||||
/**
|
||||
* Flag for drupal_set_title(); text is not sanitized, so run check_plain().
|
||||
* Flag used to indicate that text is not sanitized, so run check_plain().
|
||||
*
|
||||
* @see drupal_set_title()
|
||||
*/
|
||||
define('CHECK_PLAIN', 0);
|
||||
|
||||
/**
|
||||
* Flag for drupal_set_title(); text has already been sanitized.
|
||||
* Flag used to indicate that text has already been sanitized.
|
||||
*
|
||||
* @see drupal_set_title()
|
||||
*/
|
||||
define('PASS_THROUGH', -1);
|
||||
|
||||
@@ -240,7 +244,7 @@ define('REGISTRY_WRITE_LOOKUP_CACHE', 2);
|
||||
/**
|
||||
* Regular expression to match PHP function names.
|
||||
*
|
||||
* @see http://php.net/manual/en/language.functions.php
|
||||
* @see http://php.net/manual/language.functions.php
|
||||
*/
|
||||
define('DRUPAL_PHP_FUNCTION_PATTERN', '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*');
|
||||
|
||||
@@ -274,7 +278,7 @@ define('DRUPAL_PHP_FUNCTION_PATTERN', '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
|
||||
* error, and $var will be populated with the contents of $object['foo'], but
|
||||
* that data will be passed by value, not reference. For more information on
|
||||
* the PHP limitation, see the note in the official PHP documentation at·
|
||||
* http://php.net/manual/en/arrayaccess.offsetget.php on
|
||||
* http://php.net/manual/arrayaccess.offsetget.php on
|
||||
* ArrayAccess::offsetGet().
|
||||
*
|
||||
* By default, the class accounts for caches where calling functions might
|
||||
@@ -380,11 +384,11 @@ abstract class DrupalCacheArray implements ArrayAccess {
|
||||
* without necessarily writing back to the persistent cache at the end.
|
||||
*
|
||||
* @param $offset
|
||||
* The array offset that was request.
|
||||
* The array offset that was requested.
|
||||
* @param $persist
|
||||
* Optional boolean to specify whether the offset should be persisted or
|
||||
* not, defaults to TRUE. When called with $persist = FALSE the offset will
|
||||
* be unflagged so that it will not written at the end of the request.
|
||||
* be unflagged so that it will not be written at the end of the request.
|
||||
*/
|
||||
protected function persist($offset, $persist = TRUE) {
|
||||
$this->keysToPersist[$offset] = $persist;
|
||||
@@ -679,7 +683,8 @@ function drupal_environment_initialize() {
|
||||
ini_set('session.use_only_cookies', '1');
|
||||
ini_set('session.use_trans_sid', '0');
|
||||
// Don't send HTTP headers using PHP's session handler.
|
||||
ini_set('session.cache_limiter', 'none');
|
||||
// An empty string is used here to disable the cache limiter.
|
||||
ini_set('session.cache_limiter', '');
|
||||
// Use httponly session cookies.
|
||||
ini_set('session.cookie_httponly', '1');
|
||||
|
||||
@@ -716,7 +721,6 @@ function drupal_settings_initialize() {
|
||||
if (isset($base_url)) {
|
||||
// Parse fixed base URL from settings.php.
|
||||
$parts = parse_url($base_url);
|
||||
$http_protocol = $parts['scheme'];
|
||||
if (!isset($parts['path'])) {
|
||||
$parts['path'] = '';
|
||||
}
|
||||
@@ -792,7 +796,7 @@ function drupal_settings_initialize() {
|
||||
*
|
||||
* This function plays a key role in allowing Drupal's resources (modules
|
||||
* and themes) to be located in different places depending on a site's
|
||||
* configuration. For example, a module 'foo' may legally be be located
|
||||
* configuration. For example, a module 'foo' may legally be located
|
||||
* in any of these three places:
|
||||
*
|
||||
* modules/foo/foo.module
|
||||
@@ -803,7 +807,7 @@ function drupal_settings_initialize() {
|
||||
* the above, depending on where the module is located.
|
||||
*
|
||||
* @param $type
|
||||
* The type of the item (i.e. theme, theme_engine, module, profile).
|
||||
* The type of the item (theme, theme_engine, module, profile).
|
||||
* @param $name
|
||||
* The name of the item for which the filename is requested.
|
||||
* @param $filename
|
||||
@@ -811,7 +815,7 @@ function drupal_settings_initialize() {
|
||||
* than by consulting the database.
|
||||
*
|
||||
* @return
|
||||
* The filename of the requested item.
|
||||
* The filename of the requested item or NULL if the item is not found.
|
||||
*/
|
||||
function drupal_get_filename($type, $name, $filename = NULL) {
|
||||
// The location of files will not change during the request, so do not use
|
||||
@@ -1186,10 +1190,11 @@ function _drupal_set_preferred_header_name($name = NULL) {
|
||||
* Headers are set in drupal_add_http_header(). Default headers are not set
|
||||
* if they have been replaced or unset using drupal_add_http_header().
|
||||
*
|
||||
* @param $default_headers
|
||||
* An array of headers as name/value pairs.
|
||||
* @param $single
|
||||
* If TRUE and headers have already be sent, send only the specified header.
|
||||
* @param array $default_headers
|
||||
* (optional) An array of headers as name/value pairs.
|
||||
* @param bool $only_default
|
||||
* (optional) If TRUE and headers have already been sent, send only the
|
||||
* specified headers.
|
||||
*/
|
||||
function drupal_send_headers($default_headers = array(), $only_default = FALSE) {
|
||||
$headers_sent = &drupal_static(__FUNCTION__, FALSE);
|
||||
@@ -1212,7 +1217,7 @@ function drupal_send_headers($default_headers = array(), $only_default = FALSE)
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' ' . $value);
|
||||
}
|
||||
// Skip headers that have been unset.
|
||||
elseif ($value) {
|
||||
elseif ($value !== FALSE) {
|
||||
header($header_names[$name_lower] . ': ' . $value);
|
||||
}
|
||||
}
|
||||
@@ -1274,7 +1279,7 @@ function drupal_page_header() {
|
||||
*/
|
||||
function drupal_serve_page_from_cache(stdClass $cache) {
|
||||
// Negotiate whether to use compression.
|
||||
$page_compression = variable_get('page_compression', TRUE) && extension_loaded('zlib');
|
||||
$page_compression = !empty($cache->data['page_compressed']);
|
||||
$return_compressed = $page_compression && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE;
|
||||
|
||||
// Get headers set in hook_boot(). Keys are lower-case.
|
||||
@@ -1405,6 +1410,7 @@ function drupal_unpack($obj, $field = 'data') {
|
||||
* more information, including recommendations on how to break up or not
|
||||
* break up strings for translation.
|
||||
*
|
||||
* @section sec_translating_vars Translating Variables
|
||||
* You should never use t() to translate variables, such as calling
|
||||
* @code t($text); @endcode, unless the text that the variable holds has been
|
||||
* passed through t() elsewhere (e.g., $text is one of several translated
|
||||
@@ -1420,9 +1426,11 @@ function drupal_unpack($obj, $field = 'data') {
|
||||
* Basically, you can put variables like @name into your string, and t() will
|
||||
* substitute their sanitized values at translation time. (See the
|
||||
* Localization API pages referenced above and the documentation of
|
||||
* format_string() for details.) Translators can then rearrange the string as
|
||||
* necessary for the language (e.g., in Spanish, it might be "blog de @name").
|
||||
* format_string() for details about how to define variables in your string.)
|
||||
* Translators can then rearrange the string as necessary for the language
|
||||
* (e.g., in Spanish, it might be "blog de @name").
|
||||
*
|
||||
* @section sec_alt_funcs_install Use During Installation Phase
|
||||
* During the Drupal installation phase, some resources used by t() wil not be
|
||||
* available to code that needs localization. See st() and get_t() for
|
||||
* alternatives.
|
||||
@@ -1484,21 +1492,34 @@ function t($string, array $args = array(), array $options = array()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces placeholders with sanitized values in a string.
|
||||
* Formats a string for HTML display by replacing variable placeholders.
|
||||
*
|
||||
* This function replaces variable placeholders in a string with the requested
|
||||
* values and escapes the values so they can be safely displayed as HTML. It
|
||||
* should be used on any unknown text that is intended to be printed to an HTML
|
||||
* page (especially text that may have come from untrusted users, since in that
|
||||
* case it prevents cross-site scripting and other security problems).
|
||||
*
|
||||
* In most cases, you should use t() rather than calling this function
|
||||
* directly, since it will translate the text (on non-English-only sites) in
|
||||
* addition to formatting it.
|
||||
*
|
||||
* @param $string
|
||||
* A string containing placeholders.
|
||||
* @param $args
|
||||
* An associative array of replacements to make. Occurrences in $string of
|
||||
* any key in $args are replaced with the corresponding value, after
|
||||
* sanitization. The sanitization function depends on the first character of
|
||||
* the key:
|
||||
* - !variable: Inserted as is. Use this for text that has already been
|
||||
* sanitized.
|
||||
* - @variable: Escaped to HTML using check_plain(). Use this for anything
|
||||
* displayed on a page on the site.
|
||||
* - %variable: Escaped as a placeholder for user-submitted content using
|
||||
* drupal_placeholder(), which shows up as <em>emphasized</em> text.
|
||||
* any key in $args are replaced with the corresponding value, after optional
|
||||
* sanitization and formatting. The type of sanitization and formatting
|
||||
* depends on the first character of the key:
|
||||
* - @variable: Escaped to HTML using check_plain(). Use this as the default
|
||||
* choice for anything displayed on a page on the site.
|
||||
* - %variable: Escaped to HTML and formatted using drupal_placeholder(),
|
||||
* which makes it display as <em>emphasized</em> text.
|
||||
* - !variable: Inserted as is, with no sanitization or formatting. Only use
|
||||
* this for text that has already been prepared for HTML display (for
|
||||
* example, user-supplied text that has already been run through
|
||||
* check_plain() previously, or is expected to contain some limited HTML
|
||||
* tags and has already been run through filter_xss() previously).
|
||||
*
|
||||
* @see t()
|
||||
* @ingroup sanitization
|
||||
@@ -1912,6 +1933,33 @@ function drupal_block_denied($ip) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL-safe, base64 encoded string of highly randomized bytes (over the full 8-bit range).
|
||||
*
|
||||
* @param $byte_count
|
||||
* The number of random bytes to fetch and base64 encode.
|
||||
*
|
||||
* @return string
|
||||
* The base64 encoded result will have a length of up to 4 * $byte_count.
|
||||
*/
|
||||
function drupal_random_key($byte_count = 32) {
|
||||
return drupal_base64_encode(drupal_random_bytes($byte_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL-safe, base64 encoded version of the supplied string.
|
||||
*
|
||||
* @param $string
|
||||
* The string to convert to base64.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function drupal_base64_encode($string) {
|
||||
$data = base64_encode($string);
|
||||
// Modify the output so it's safe to use in URLs.
|
||||
return strtr($data, array('+' => '-', '/' => '_', '=' => ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string of highly randomized bytes (over the full 8-bit range).
|
||||
*
|
||||
@@ -1925,38 +1973,34 @@ function drupal_block_denied($ip) {
|
||||
*/
|
||||
function drupal_random_bytes($count) {
|
||||
// $random_state does not use drupal_static as it stores random bytes.
|
||||
static $random_state, $bytes, $php_compatible;
|
||||
// Initialize on the first call. The contents of $_SERVER includes a mix of
|
||||
// user-specific and system information that varies a little with each page.
|
||||
if (!isset($random_state)) {
|
||||
$random_state = print_r($_SERVER, TRUE);
|
||||
if (function_exists('getmypid')) {
|
||||
// Further initialize with the somewhat random PHP process ID.
|
||||
$random_state .= getmypid();
|
||||
}
|
||||
$bytes = '';
|
||||
}
|
||||
if (strlen($bytes) < $count) {
|
||||
static $random_state, $bytes, $has_openssl;
|
||||
|
||||
$missing_bytes = $count - strlen($bytes);
|
||||
|
||||
if ($missing_bytes > 0) {
|
||||
// PHP versions prior 5.3.4 experienced openssl_random_pseudo_bytes()
|
||||
// locking on Windows and rendered it unusable.
|
||||
if (!isset($php_compatible)) {
|
||||
$php_compatible = version_compare(PHP_VERSION, '5.3.4', '>=');
|
||||
if (!isset($has_openssl)) {
|
||||
$has_openssl = version_compare(PHP_VERSION, '5.3.4', '>=') && function_exists('openssl_random_pseudo_bytes');
|
||||
}
|
||||
// /dev/urandom is available on many *nix systems and is considered the
|
||||
// best commonly available pseudo-random source.
|
||||
if ($fh = @fopen('/dev/urandom', 'rb')) {
|
||||
|
||||
// openssl_random_pseudo_bytes() will find entropy in a system-dependent
|
||||
// way.
|
||||
if ($has_openssl) {
|
||||
$bytes .= openssl_random_pseudo_bytes($missing_bytes);
|
||||
}
|
||||
|
||||
// Else, read directly from /dev/urandom, which is available on many *nix
|
||||
// systems and is considered cryptographically secure.
|
||||
elseif ($fh = @fopen('/dev/urandom', 'rb')) {
|
||||
// PHP only performs buffered reads, so in reality it will always read
|
||||
// at least 4096 bytes. Thus, it costs nothing extra to read and store
|
||||
// that much so as to speed any additional invocations.
|
||||
$bytes .= fread($fh, max(4096, $count));
|
||||
$bytes .= fread($fh, max(4096, $missing_bytes));
|
||||
fclose($fh);
|
||||
}
|
||||
// openssl_random_pseudo_bytes() will find entropy in a system-dependent
|
||||
// way.
|
||||
elseif ($php_compatible && function_exists('openssl_random_pseudo_bytes')) {
|
||||
$bytes .= openssl_random_pseudo_bytes($count - strlen($bytes));
|
||||
}
|
||||
// If /dev/urandom is not available or returns no bytes, this loop will
|
||||
|
||||
// If we couldn't get enough entropy, this simple hash-based PRNG will
|
||||
// generate a good set of pseudo-random bytes on any system.
|
||||
// Note that it may be important that our $random_state is passed
|
||||
// through hash() prior to being rolled into $output, that the two hash()
|
||||
@@ -1964,9 +2008,23 @@ function drupal_random_bytes($count) {
|
||||
// the microtime() - is prepended rather than appended. This is to avoid
|
||||
// directly leaking $random_state via the $output stream, which could
|
||||
// allow for trivial prediction of further "random" numbers.
|
||||
while (strlen($bytes) < $count) {
|
||||
$random_state = hash('sha256', microtime() . mt_rand() . $random_state);
|
||||
$bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
|
||||
if (strlen($bytes) < $count) {
|
||||
// Initialize on the first call. The contents of $_SERVER includes a mix of
|
||||
// user-specific and system information that varies a little with each page.
|
||||
if (!isset($random_state)) {
|
||||
$random_state = print_r($_SERVER, TRUE);
|
||||
if (function_exists('getmypid')) {
|
||||
// Further initialize with the somewhat random PHP process ID.
|
||||
$random_state .= getmypid();
|
||||
}
|
||||
$bytes = '';
|
||||
}
|
||||
|
||||
do {
|
||||
$random_state = hash('sha256', microtime() . mt_rand() . $random_state);
|
||||
$bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
|
||||
}
|
||||
while (strlen($bytes) < $count);
|
||||
}
|
||||
}
|
||||
$output = substr($bytes, 0, $count);
|
||||
@@ -1977,17 +2035,21 @@ function drupal_random_bytes($count) {
|
||||
/**
|
||||
* Calculates a base-64 encoded, URL-safe sha-256 hmac.
|
||||
*
|
||||
* @param $data
|
||||
* @param string $data
|
||||
* String to be validated with the hmac.
|
||||
* @param $key
|
||||
* @param string $key
|
||||
* A secret string key.
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* A base-64 encoded sha-256 hmac, with + replaced with -, / with _ and
|
||||
* any = padding characters removed.
|
||||
*/
|
||||
function drupal_hmac_base64($data, $key) {
|
||||
$hmac = base64_encode(hash_hmac('sha256', $data, $key, TRUE));
|
||||
// Casting $data and $key to strings here is necessary to avoid empty string
|
||||
// results of the hash function if they are not scalar values. As this
|
||||
// function is used in security-critical contexts like token validation it is
|
||||
// important that it never returns an empty string.
|
||||
$hmac = base64_encode(hash_hmac('sha256', (string) $data, (string) $key, TRUE));
|
||||
// Modify the hmac so it's safe to use in URLs.
|
||||
return strtr($hmac, array('+' => '-', '/' => '_', '=' => ''));
|
||||
}
|
||||
@@ -2088,7 +2150,7 @@ function drupal_array_merge_deep_array($arrays) {
|
||||
* @return Object - the user object.
|
||||
*/
|
||||
function drupal_anonymous_user() {
|
||||
$user = new stdClass();
|
||||
$user = variable_get('drupal_anonymous_user_object', new stdClass);
|
||||
$user->uid = 0;
|
||||
$user->hostname = ip_address();
|
||||
$user->roles = array();
|
||||
@@ -2218,6 +2280,19 @@ function drupal_get_user_timezone() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a salt useful for hardening against SQL injection.
|
||||
*
|
||||
* @return
|
||||
* A salt based on information in settings.php, not in the database.
|
||||
*/
|
||||
function drupal_get_hash_salt() {
|
||||
global $drupal_hash_salt, $databases;
|
||||
// If the $drupal_hash_salt variable is empty, a hash of the serialized
|
||||
// database credentials is used as a fallback salt.
|
||||
return empty($drupal_hash_salt) ? hash('sha256', serialize($databases)) : $drupal_hash_salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides custom PHP error handling.
|
||||
*
|
||||
@@ -2438,7 +2513,6 @@ function drupal_get_bootstrap_phase() {
|
||||
* HMAC and timestamp.
|
||||
*/
|
||||
function drupal_valid_test_ua() {
|
||||
global $drupal_hash_salt;
|
||||
// No reason to reset this.
|
||||
static $test_prefix;
|
||||
|
||||
@@ -2452,7 +2526,7 @@ function drupal_valid_test_ua() {
|
||||
// We use the salt from settings.php to make the HMAC key, since
|
||||
// the database is not yet initialized and we can't access any Drupal variables.
|
||||
// The file properties add more entropy not easily accessible to others.
|
||||
$key = $drupal_hash_salt . filectime(__FILE__) . fileinode(__FILE__);
|
||||
$key = drupal_get_hash_salt() . filectime(__FILE__) . fileinode(__FILE__);
|
||||
$time_diff = REQUEST_TIME - $time;
|
||||
// Since we are making a local request a 5 second time window is allowed,
|
||||
// and the HMAC must match.
|
||||
@@ -2470,14 +2544,13 @@ function drupal_valid_test_ua() {
|
||||
* Generates a user agent string with a HMAC and timestamp for simpletest.
|
||||
*/
|
||||
function drupal_generate_test_ua($prefix) {
|
||||
global $drupal_hash_salt;
|
||||
static $key;
|
||||
|
||||
if (!isset($key)) {
|
||||
// We use the salt from settings.php to make the HMAC key, since
|
||||
// the database is not yet initialized and we can't access any Drupal variables.
|
||||
// The file properties add more entropy not easily accessible to others.
|
||||
$key = $drupal_hash_salt . filectime(__FILE__) . fileinode(__FILE__);
|
||||
$key = drupal_get_hash_salt() . filectime(__FILE__) . fileinode(__FILE__);
|
||||
}
|
||||
// Generate a moderately secure HMAC based on the database credentials.
|
||||
$salt = uniqid('', TRUE);
|
||||
@@ -3222,8 +3295,8 @@ function registry_update() {
|
||||
* However, the above line of code does not work, because PHP only allows static
|
||||
* variables to be initializied by literal values, and does not allow static
|
||||
* variables to be assigned to references.
|
||||
* - http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static
|
||||
* - http://php.net/manual/en/language.variables.scope.php#language.variables.scope.references
|
||||
* - http://php.net/manual/language.variables.scope.php#language.variables.scope.static
|
||||
* - http://php.net/manual/language.variables.scope.php#language.variables.scope.references
|
||||
* The example below shows the syntax needed to work around both limitations.
|
||||
* For benchmarks and more information, see http://drupal.org/node/619666.
|
||||
*
|
||||
@@ -3383,3 +3456,32 @@ function _drupal_shutdown_function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the memory required for an operation to the available memory.
|
||||
*
|
||||
* @param $required
|
||||
* The memory required for the operation, expressed as a number of bytes with
|
||||
* optional SI or IEC binary unit prefix (e.g. 2, 3K, 5MB, 10G, 6GiB, 8bytes,
|
||||
* 9mbytes).
|
||||
* @param $memory_limit
|
||||
* (optional) The memory limit for the operation, expressed as a number of
|
||||
* bytes with optional SI or IEC binary unit prefix (e.g. 2, 3K, 5MB, 10G,
|
||||
* 6GiB, 8bytes, 9mbytes). If no value is passed, the current PHP
|
||||
* memory_limit will be used. Defaults to NULL.
|
||||
*
|
||||
* @return
|
||||
* TRUE if there is sufficient memory to allow the operation, or FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
function drupal_check_memory_limit($required, $memory_limit = NULL) {
|
||||
if (!isset($memory_limit)) {
|
||||
$memory_limit = ini_get('memory_limit');
|
||||
}
|
||||
|
||||
// There is sufficient memory if:
|
||||
// - No memory limit is set.
|
||||
// - The memory limit is set to unlimited (-1).
|
||||
// - The memory limit is greater than the memory required for the operation.
|
||||
return ((!$memory_limit) || ($memory_limit == -1) || (parse_size($memory_limit) >= parse_size($required)));
|
||||
}
|
||||
|
||||
@@ -80,43 +80,15 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
|
||||
* same name. Other implementations might want to store several bins in data
|
||||
* structures that get flushed together. While it is not a problem for most
|
||||
* cache bins if the entries in them are flushed before their expire time, some
|
||||
* might break functionality or are extremely expensive to recalculate. These
|
||||
* will be marked with a (*). The other bins expired automatically by core.
|
||||
* Contributed modules can add additional bins and get them expired
|
||||
* automatically by implementing hook_flush_caches().
|
||||
*
|
||||
* - cache: Generic cache storage bin (used for variables, theme registry,
|
||||
* locale date, list of simpletest tests etc).
|
||||
*
|
||||
* - cache_block: Stores the content of various blocks.
|
||||
*
|
||||
* - cache field: Stores the field data belonging to a given object.
|
||||
*
|
||||
* - cache_filter: Stores filtered pieces of content.
|
||||
*
|
||||
* - cache_form(*): Stores multistep forms. Flushing this bin means that some
|
||||
* forms displayed to users lose their state and the data already submitted
|
||||
* to them.
|
||||
*
|
||||
* - cache_menu: Stores the structure of visible navigation menus per page.
|
||||
*
|
||||
* - cache_page: Stores generated pages for anonymous users. It is flushed
|
||||
* very often, whenever a page changes, at least for every ode and comment
|
||||
* submission. This is the only bin affected by the page cache setting on
|
||||
* the administrator panel.
|
||||
*
|
||||
* - cache path: Stores the system paths that have an alias.
|
||||
*
|
||||
* - cache update(*): Stores available releases. The update server (for
|
||||
* example, drupal.org) needs to produce the relevant XML for every project
|
||||
* installed on the current site. As this is different for (almost) every
|
||||
* site, it's very expensive to recalculate for the update server.
|
||||
* might break functionality or are extremely expensive to recalculate. The
|
||||
* other bins are expired automatically by core. Contributed modules can add
|
||||
* additional bins and get them expired automatically by implementing
|
||||
* hook_flush_caches().
|
||||
*
|
||||
* The reasons for having several bins are as follows:
|
||||
*
|
||||
* - smaller bins mean smaller database tables and allow for faster selects and
|
||||
* inserts
|
||||
* - we try to put fast changing cache items and rather static ones into
|
||||
* - Smaller bins mean smaller database tables and allow for faster selects and
|
||||
* inserts.
|
||||
* - We try to put fast changing cache items and rather static ones into
|
||||
* different bins. The effect is that only the fast changing bins will need a
|
||||
* lot of writes to disk. The more static bins will also be better cacheable
|
||||
* with MySQL's query cache.
|
||||
@@ -125,13 +97,27 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
|
||||
* The cache ID of the data to store.
|
||||
* @param $data
|
||||
* The data to store in the cache. Complex data types will be automatically
|
||||
* serialized before insertion.
|
||||
* Strings will be stored as plain text and not serialized.
|
||||
* serialized before insertion. Strings will be stored as plain text and are
|
||||
* not serialized.
|
||||
* @param $bin
|
||||
* The cache bin to store the data in. Valid core values are 'cache_block',
|
||||
* 'cache_bootstrap', 'cache_field', 'cache_filter', 'cache_form',
|
||||
* 'cache_menu', 'cache_page', 'cache_update' or 'cache' for the default
|
||||
* cache.
|
||||
* The cache bin to store the data in. Valid core values are:
|
||||
* - cache: (default) Generic cache storage bin (used for theme registry,
|
||||
* locale date, list of simpletest tests, etc.).
|
||||
* - cache_block: Stores the content of various blocks.
|
||||
* - cache_bootstrap: Stores the class registry, the system list of modules,
|
||||
* the list of which modules implement which hooks, and the Drupal variable
|
||||
* list.
|
||||
* - cache_field: Stores the field data belonging to a given object.
|
||||
* - cache_filter: Stores filtered pieces of content.
|
||||
* - cache_form: Stores multistep forms. Flushing this bin means that some
|
||||
* forms displayed to users lose their state and the data already submitted
|
||||
* to them. This bin should not be flushed before its expired time.
|
||||
* - cache_menu: Stores the structure of visible navigation menus per page.
|
||||
* - cache_page: Stores generated pages for anonymous users. It is flushed
|
||||
* very often, whenever a page changes, at least for every node and comment
|
||||
* submission. This is the only bin affected by the page cache setting on
|
||||
* the administrator panel.
|
||||
* - cache_path: Stores the system paths that have an alias.
|
||||
* @param $expire
|
||||
* One of the following values:
|
||||
* - CACHE_PERMANENT: Indicates that the item should never be removed unless
|
||||
@@ -141,6 +127,7 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
|
||||
* - A Unix timestamp: Indicates that the item should be kept at least until
|
||||
* the given time, after which it behaves like CACHE_TEMPORARY.
|
||||
*
|
||||
* @see _update_cache_set()
|
||||
* @see cache_get()
|
||||
*/
|
||||
function cache_set($cid, $data, $bin = 'cache', $expire = CACHE_PERMANENT) {
|
||||
@@ -150,18 +137,20 @@ function cache_set($cid, $data, $bin = 'cache', $expire = CACHE_PERMANENT) {
|
||||
/**
|
||||
* Expires data from the cache.
|
||||
*
|
||||
* If called without arguments, expirable entries will be cleared from the
|
||||
* cache_page and cache_block bins.
|
||||
* If called with the arguments $cid and $bin set to NULL or omitted, then
|
||||
* expirable entries will be cleared from the cache_page and cache_block bins,
|
||||
* and the $wildcard argument is ignored.
|
||||
*
|
||||
* @param $cid
|
||||
* If set, the cache ID to delete. Otherwise, all cache entries that can
|
||||
* expire are deleted.
|
||||
* If set, the cache ID or an array of cache IDs. Otherwise, all cache entries
|
||||
* that can expire are deleted. The $wildcard argument will be ignored if set
|
||||
* to NULL.
|
||||
* @param $bin
|
||||
* If set, the cache bin to delete from. Mandatory argument if $cid is set.
|
||||
* @param $wildcard
|
||||
* If TRUE, cache IDs starting with $cid are deleted in addition to the
|
||||
* exact cache ID specified by $cid. If $wildcard is TRUE and $cid is '*',
|
||||
* the entire cache bin is emptied.
|
||||
* If TRUE, the $cid argument must contain a string value and cache IDs
|
||||
* starting with $cid are deleted in addition to the exact cache ID specified
|
||||
* by $cid. If $wildcard is TRUE and $cid is '*', the entire cache is emptied.
|
||||
*/
|
||||
function cache_clear_all($cid = NULL, $bin = NULL, $wildcard = FALSE) {
|
||||
if (!isset($cid) && !isset($bin)) {
|
||||
@@ -230,13 +219,6 @@ function cache_is_empty($bin) {
|
||||
* @see DrupalDatabaseCache
|
||||
*/
|
||||
interface DrupalCacheInterface {
|
||||
/**
|
||||
* Constructs a new cache interface.
|
||||
*
|
||||
* @param $bin
|
||||
* The cache bin for which the object is created.
|
||||
*/
|
||||
function __construct($bin);
|
||||
|
||||
/**
|
||||
* Returns data from the persistent cache.
|
||||
@@ -293,12 +275,14 @@ interface DrupalCacheInterface {
|
||||
* cache_page and cache_block bins.
|
||||
*
|
||||
* @param $cid
|
||||
* If set, the cache ID to delete. Otherwise, all cache entries that can
|
||||
* expire are deleted.
|
||||
* If set, the cache ID or an array of cache IDs. Otherwise, all cache
|
||||
* entries that can expire are deleted. The $wildcard argument will be
|
||||
* ignored if set to NULL.
|
||||
* @param $wildcard
|
||||
* If set to TRUE, the $cid is treated as a substring
|
||||
* to match rather than a complete ID. The match is a right hand
|
||||
* match. If '*' is given as $cid, the bin $bin will be emptied.
|
||||
* If TRUE, the $cid argument must contain a string value and cache IDs
|
||||
* starting with $cid are deleted in addition to the exact cache ID
|
||||
* specified by $cid. If $wildcard is TRUE and $cid is '*', the entire
|
||||
* cache is emptied.
|
||||
*/
|
||||
function clear($cid = NULL, $wildcard = FALSE);
|
||||
|
||||
@@ -324,7 +308,10 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
|
||||
protected $bin;
|
||||
|
||||
/**
|
||||
* Constructs a new DrupalDatabaseCache object.
|
||||
* Constructs a DrupalDatabaseCache object.
|
||||
*
|
||||
* @param $bin
|
||||
* The cache bin for which the object is created.
|
||||
*/
|
||||
function __construct($bin) {
|
||||
$this->bin = $bin;
|
||||
@@ -518,7 +505,16 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
|
||||
else {
|
||||
if ($wildcard) {
|
||||
if ($cid == '*') {
|
||||
db_truncate($this->bin)->execute();
|
||||
// Check if $this->bin is a cache table before truncating. Other
|
||||
// cache_clear_all() operations throw a PDO error in this situation,
|
||||
// so we don't need to verify them first. This ensures that non-cache
|
||||
// tables cannot be truncated accidentally.
|
||||
if ($this->isValidBin()) {
|
||||
db_truncate($this->bin)->execute();
|
||||
}
|
||||
else {
|
||||
throw new Exception(t('Invalid or missing cache bin specified: %bin', array('%bin' => $this->bin)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
db_delete($this->bin)
|
||||
@@ -555,4 +551,25 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
|
||||
->fetchField();
|
||||
return empty($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if $this->bin represents a valid cache table.
|
||||
*
|
||||
* This check is required to ensure that non-cache tables are not truncated
|
||||
* accidentally when calling cache_clear_all().
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function isValidBin() {
|
||||
if ($this->bin == 'cache' || substr($this->bin, 0, 6) == 'cache_') {
|
||||
// Skip schema check for bins with standard table names.
|
||||
return TRUE;
|
||||
}
|
||||
// These fields are required for any cache table.
|
||||
$fields = array('cid', 'data', 'expire', 'created', 'serialized');
|
||||
// Load the table schema.
|
||||
$schema = drupal_get_schema($this->bin);
|
||||
// Confirm that all fields are present.
|
||||
return isset($schema['fields']) && !array_diff($fields, array_keys($schema['fields']));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ function drupal_get_rdf_namespaces() {
|
||||
/**
|
||||
* Adds output to the HEAD tag of the HTML page.
|
||||
*
|
||||
* This function can be called as long the headers aren't sent. Pass no
|
||||
* This function can be called as long as the headers aren't sent. Pass no
|
||||
* arguments (or NULL for both) to retrieve the currently stored elements.
|
||||
*
|
||||
* @param $data
|
||||
@@ -458,7 +458,7 @@ function drupal_get_query_array($query) {
|
||||
$result = array();
|
||||
if (!empty($query)) {
|
||||
foreach (explode('&', $query) as $param) {
|
||||
$param = explode('=', $param);
|
||||
$param = explode('=', $param, 2);
|
||||
$result[$param[0]] = isset($param[1]) ? rawurldecode($param[1]) : '';
|
||||
}
|
||||
}
|
||||
@@ -641,7 +641,7 @@ function drupal_encode_path($path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the user to a different Drupal page.
|
||||
* Sends the user to a different page.
|
||||
*
|
||||
* This issues an on-site HTTP redirect. The function makes sure the redirected
|
||||
* URL is formatted correctly.
|
||||
@@ -785,6 +785,13 @@ function drupal_access_denied() {
|
||||
* - data: A string containing the response body that was received.
|
||||
*/
|
||||
function drupal_http_request($url, array $options = array()) {
|
||||
// Allow an alternate HTTP client library to replace Drupal's default
|
||||
// implementation.
|
||||
$override_function = variable_get('drupal_http_request_function', FALSE);
|
||||
if (!empty($override_function) && function_exists($override_function)) {
|
||||
return $override_function($url, $options);
|
||||
}
|
||||
|
||||
$result = new stdClass();
|
||||
|
||||
// Parse the URL and make sure we can handle the schema.
|
||||
@@ -922,7 +929,7 @@ function drupal_http_request($url, array $options = array()) {
|
||||
|
||||
// If the server URL has a user then attempt to use basic authentication.
|
||||
if (isset($uri['user'])) {
|
||||
$options['headers']['Authorization'] = 'Basic ' . base64_encode($uri['user'] . (isset($uri['pass']) ? ':' . $uri['pass'] : ''));
|
||||
$options['headers']['Authorization'] = 'Basic ' . base64_encode($uri['user'] . (isset($uri['pass']) ? ':' . $uri['pass'] : ':'));
|
||||
}
|
||||
|
||||
// If the database prefix is being used by SimpleTest to run the tests in a copied
|
||||
@@ -1127,7 +1134,7 @@ function _fix_gpc_magic(&$item) {
|
||||
* @param $key
|
||||
* The key for the item within $_FILES.
|
||||
*
|
||||
* @see http://php.net/manual/en/features.file-upload.php#42280
|
||||
* @see http://php.net/manual/features.file-upload.php#42280
|
||||
*/
|
||||
function _fix_gpc_magic_files(&$item, $key) {
|
||||
if ($key != 'tmp_name') {
|
||||
@@ -1167,7 +1174,8 @@ function fix_gpc_magic() {
|
||||
/**
|
||||
* Verifies the syntax of the given e-mail address.
|
||||
*
|
||||
* See @link http://tools.ietf.org/html/rfc5321 RFC 5321 @endlink for details.
|
||||
* This uses the
|
||||
* @link http://php.net/manual/filter.filters.validate.php PHP e-mail validation filter. @endlink
|
||||
*
|
||||
* @param $mail
|
||||
* A string containing an e-mail address.
|
||||
@@ -1418,7 +1426,6 @@ function filter_xss_admin($string) {
|
||||
* valid UTF-8.
|
||||
*
|
||||
* @see drupal_validate_utf8()
|
||||
* @ingroup sanitization
|
||||
*/
|
||||
function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd')) {
|
||||
// Only operate on valid UTF-8 strings. This is necessary to prevent cross
|
||||
@@ -1942,7 +1949,7 @@ function format_interval($interval, $granularity = 2, $langcode = NULL) {
|
||||
* get interpreted as date format characters.
|
||||
* @param $timezone
|
||||
* (optional) Time zone identifier, as described at
|
||||
* http://php.net/manual/en/timezones.php Defaults to the time zone used to
|
||||
* http://php.net/manual/timezones.php Defaults to the time zone used to
|
||||
* display the page.
|
||||
* @param $langcode
|
||||
* (optional) Language code to translate to. Defaults to the language used to
|
||||
@@ -2078,6 +2085,9 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) {
|
||||
/**
|
||||
* Format a username.
|
||||
*
|
||||
* This is also the label callback implementation of
|
||||
* callback_entity_info_label() for user_entity_info().
|
||||
*
|
||||
* By default, the passed-in object's 'name' property is used if it exists, or
|
||||
* else, the site-defined value for the 'anonymous' variable. However, a module
|
||||
* may override this by implementing hook_username_alter(&$name, $account).
|
||||
@@ -2379,6 +2389,14 @@ function drupal_attributes(array $attributes = array()) {
|
||||
* internal links output by modules should be generated by this function if
|
||||
* possible.
|
||||
*
|
||||
* However, for links enclosed in translatable text you should use t() and
|
||||
* embed the HTML anchor tag directly in the translated string. For example:
|
||||
* @code
|
||||
* t('Visit the <a href="@url">settings</a> page', array('@url' => url('admin')));
|
||||
* @endcode
|
||||
* This keeps the context of the link title ('settings' in the example) for
|
||||
* translators.
|
||||
*
|
||||
* @param string $text
|
||||
* The translated link text for the anchor tag.
|
||||
* @param string $path
|
||||
@@ -2779,7 +2797,7 @@ function drupal_set_time_limit($time_limit) {
|
||||
* The name of the item for which the path is requested.
|
||||
*
|
||||
* @return
|
||||
* The path to the requested item.
|
||||
* The path to the requested item or an empty string if the item is not found.
|
||||
*/
|
||||
function drupal_get_path($type, $name) {
|
||||
return dirname(drupal_get_filename($type, $name));
|
||||
@@ -3654,17 +3672,23 @@ function drupal_load_stylesheet($file, $optimize = NULL, $reset_basepath = TRUE)
|
||||
if ($basepath && !file_uri_scheme($file)) {
|
||||
$file = $basepath . '/' . $file;
|
||||
}
|
||||
// Store the parent base path to restore it later.
|
||||
$parent_base_path = $basepath;
|
||||
// Set the current base path to process possible child imports.
|
||||
$basepath = dirname($file);
|
||||
|
||||
// Load the CSS stylesheet. We suppress errors because themes may specify
|
||||
// stylesheets in their .info file that don't exist in the theme's path,
|
||||
// but are merely there to disable certain module CSS files.
|
||||
$content = '';
|
||||
if ($contents = @file_get_contents($file)) {
|
||||
// Return the processed stylesheet.
|
||||
return drupal_load_stylesheet_content($contents, $_optimize);
|
||||
$content = drupal_load_stylesheet_content($contents, $_optimize);
|
||||
}
|
||||
|
||||
return '';
|
||||
// Restore the parent base path as the file and its childen are processed.
|
||||
$basepath = $parent_base_path;
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3681,7 +3705,7 @@ function drupal_load_stylesheet($file, $optimize = NULL, $reset_basepath = TRUE)
|
||||
*/
|
||||
function drupal_load_stylesheet_content($contents, $optimize = FALSE) {
|
||||
// Remove multiple charset declarations for standards compliance (and fixing Safari problems).
|
||||
$contents = preg_replace('/^@charset\s+[\'"](\S*)\b[\'"];/i', '', $contents);
|
||||
$contents = preg_replace('/^@charset\s+[\'"](\S*?)\b[\'"];/i', '', $contents);
|
||||
|
||||
if ($optimize) {
|
||||
// Perform some safe CSS optimizations.
|
||||
@@ -3700,7 +3724,7 @@ function drupal_load_stylesheet_content($contents, $optimize = FALSE) {
|
||||
// Remove certain whitespace.
|
||||
// There are different conditions for removing leading and trailing
|
||||
// whitespace.
|
||||
// @see http://php.net/manual/en/regexp.reference.subpatterns.php
|
||||
// @see http://php.net/manual/regexp.reference.subpatterns.php
|
||||
$contents = preg_replace('<
|
||||
# Strip leading and trailing whitespace.
|
||||
\s*([@{};,])\s*
|
||||
@@ -3814,7 +3838,14 @@ function drupal_clean_css_identifier($identifier, $filter = array(' ' => '-', '_
|
||||
* The cleaned class name.
|
||||
*/
|
||||
function drupal_html_class($class) {
|
||||
return drupal_clean_css_identifier(drupal_strtolower($class));
|
||||
// The output of this function will never change, so this uses a normal
|
||||
// static instead of drupal_static().
|
||||
static $classes = array();
|
||||
|
||||
if (!isset($classes[$class])) {
|
||||
$classes[$class] = drupal_clean_css_identifier(drupal_strtolower($class));
|
||||
}
|
||||
return $classes[$class];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3869,7 +3900,16 @@ function drupal_html_id($id) {
|
||||
// requested id. $_POST['ajax_html_ids'] contains the ids as they were
|
||||
// returned by this function, potentially with the appended counter, so
|
||||
// we parse that to reconstruct the $seen_ids array.
|
||||
foreach ($_POST['ajax_html_ids'] as $seen_id) {
|
||||
if (isset($_POST['ajax_html_ids'][0]) && strpos($_POST['ajax_html_ids'][0], ',') === FALSE) {
|
||||
$ajax_html_ids = $_POST['ajax_html_ids'];
|
||||
}
|
||||
else {
|
||||
// jquery.form.js may send the server a comma-separated string as the
|
||||
// first element of an array (see http://drupal.org/node/1575060), so
|
||||
// we need to convert it to an array in that case.
|
||||
$ajax_html_ids = explode(',', $_POST['ajax_html_ids'][0]);
|
||||
}
|
||||
foreach ($ajax_html_ids as $seen_id) {
|
||||
// We rely on '--' being used solely for separating a base id from the
|
||||
// counter, which this function ensures when returning an id.
|
||||
$parts = explode('--', $seen_id, 2);
|
||||
@@ -4069,7 +4109,7 @@ function drupal_region_class($region) {
|
||||
* else being the same, JavaScript added by a call to drupal_add_js() that
|
||||
* happened later in the page request gets added to the page after one for
|
||||
* which drupal_add_js() happened earlier in the page request.
|
||||
* - defer: If set to TRUE, the defer attribute is set on the <script>
|
||||
* - defer: If set to TRUE, the defer attribute is set on the <script>
|
||||
* tag. Defaults to FALSE.
|
||||
* - cache: If set to FALSE, the JavaScript file is loaded anew on every page
|
||||
* call; in other words, it is not cached. Used only when 'type' references
|
||||
@@ -5006,19 +5046,6 @@ function drupal_json_output($var = NULL) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a salt useful for hardening against SQL injection.
|
||||
*
|
||||
* @return
|
||||
* A salt based on information in settings.php, not in the database.
|
||||
*/
|
||||
function drupal_get_hash_salt() {
|
||||
global $drupal_hash_salt, $databases;
|
||||
// If the $drupal_hash_salt variable is empty, a hash of the serialized
|
||||
// database credentials is used as a fallback salt.
|
||||
return empty($drupal_hash_salt) ? hash('sha256', serialize($databases)) : $drupal_hash_salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the private key variable used to generate tokens is set.
|
||||
*
|
||||
@@ -5027,7 +5054,7 @@ function drupal_get_hash_salt() {
|
||||
*/
|
||||
function drupal_get_private_key() {
|
||||
if (!($key = variable_get('drupal_private_key', 0))) {
|
||||
$key = drupal_hash_base64(drupal_random_bytes(55));
|
||||
$key = drupal_random_key();
|
||||
variable_set('drupal_private_key', $key);
|
||||
}
|
||||
return $key;
|
||||
@@ -5038,6 +5065,18 @@ function drupal_get_private_key() {
|
||||
*
|
||||
* @param $value
|
||||
* An additional value to base the token on.
|
||||
*
|
||||
* The generated token is based on the session ID of the current user. Normally,
|
||||
* anonymous users do not have a session, so the generated token will be
|
||||
* different on every page request. To generate a token for users without a
|
||||
* session, manually start a session prior to calling this function.
|
||||
*
|
||||
* @return string
|
||||
* A 43-character URL-safe token for validation, based on the user session ID,
|
||||
* the hash salt provided from drupal_get_hash_salt(), and the
|
||||
* 'drupal_private_key' configuration variable.
|
||||
*
|
||||
* @see drupal_get_hash_salt()
|
||||
*/
|
||||
function drupal_get_token($value = '') {
|
||||
return drupal_hmac_base64($value, session_id() . drupal_get_private_key() . drupal_get_hash_salt());
|
||||
@@ -5059,7 +5098,7 @@ function drupal_get_token($value = '') {
|
||||
*/
|
||||
function drupal_valid_token($token, $value = '', $skip_anonymous = FALSE) {
|
||||
global $user;
|
||||
return (($skip_anonymous && $user->uid == 0) || ($token == drupal_get_token($value)));
|
||||
return (($skip_anonymous && $user->uid == 0) || ($token === drupal_get_token($value)));
|
||||
}
|
||||
|
||||
function _drupal_bootstrap_full() {
|
||||
@@ -5092,6 +5131,10 @@ function _drupal_bootstrap_full() {
|
||||
module_load_all();
|
||||
// Make sure all stream wrappers are registered.
|
||||
file_get_stream_wrappers();
|
||||
// Ensure mt_rand is reseeded, to prevent random values from one page load
|
||||
// being exploited to predict random values in subsequent page loads.
|
||||
$seed = unpack("L", drupal_random_bytes(4));
|
||||
mt_srand($seed[1]);
|
||||
|
||||
$test_info = &$GLOBALS['drupal_test_info'];
|
||||
if (!empty($test_info['in_child_site'])) {
|
||||
@@ -5129,7 +5172,7 @@ function _drupal_bootstrap_full() {
|
||||
* client without gzip support.
|
||||
*
|
||||
* Page compression requires the PHP zlib extension
|
||||
* (http://php.net/manual/en/ref.zlib.php).
|
||||
* (http://php.net/manual/ref.zlib.php).
|
||||
*
|
||||
* @see drupal_page_header()
|
||||
*/
|
||||
@@ -5137,6 +5180,10 @@ function drupal_page_set_cache() {
|
||||
global $base_root;
|
||||
|
||||
if (drupal_page_is_cacheable()) {
|
||||
|
||||
// Check whether the current page might be compressed.
|
||||
$page_compressed = variable_get('page_compression', TRUE) && extension_loaded('zlib');
|
||||
|
||||
$cache = (object) array(
|
||||
'cid' => $base_root . request_uri(),
|
||||
'data' => array(
|
||||
@@ -5144,6 +5191,9 @@ function drupal_page_set_cache() {
|
||||
'body' => ob_get_clean(),
|
||||
'title' => drupal_get_title(),
|
||||
'headers' => array(),
|
||||
// We need to store whether page was compressed or not,
|
||||
// because by the time it is read, the configuration might change.
|
||||
'page_compressed' => $page_compressed,
|
||||
),
|
||||
'expire' => CACHE_TEMPORARY,
|
||||
'created' => REQUEST_TIME,
|
||||
@@ -5161,7 +5211,7 @@ function drupal_page_set_cache() {
|
||||
}
|
||||
|
||||
if ($cache->data['body']) {
|
||||
if (variable_get('page_compression', TRUE) && extension_loaded('zlib')) {
|
||||
if ($page_compressed) {
|
||||
$cache->data['body'] = gzencode($cache->data['body'], 9, FORCE_GZIP);
|
||||
}
|
||||
cache_set($cache->cid, $cache->data, 'cache_page', $cache->expire);
|
||||
@@ -5236,12 +5286,23 @@ function drupal_cron_run() {
|
||||
}
|
||||
|
||||
foreach ($queues as $queue_name => $info) {
|
||||
if (!empty($info['skip on cron'])) {
|
||||
// Do not run if queue wants to skip.
|
||||
continue;
|
||||
}
|
||||
$function = $info['worker callback'];
|
||||
$end = time() + (isset($info['time']) ? $info['time'] : 15);
|
||||
$queue = DrupalQueue::get($queue_name);
|
||||
while (time() < $end && ($item = $queue->claimItem())) {
|
||||
$function($item->data);
|
||||
$queue->deleteItem($item);
|
||||
try {
|
||||
$function($item->data);
|
||||
$queue->deleteItem($item);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// In case of exception log it and leave the item in the queue
|
||||
// to be processed again later.
|
||||
watchdog_exception('cron', $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Restore the user.
|
||||
@@ -5568,7 +5629,7 @@ function drupal_pre_render_link($element) {
|
||||
* @code
|
||||
* $node->content['links'] = array(
|
||||
* '#theme' => 'links__node',
|
||||
* '#pre_render' = array('drupal_pre_render_links'),
|
||||
* '#pre_render' => array('drupal_pre_render_links'),
|
||||
* 'comment' => array(
|
||||
* '#theme' => 'links__node__comment',
|
||||
* '#links' => array(
|
||||
@@ -5773,23 +5834,23 @@ function drupal_render_page($page) {
|
||||
* array to be rendered independently and prevents them from being rendered
|
||||
* more than once on subsequent calls to drupal_render() (e.g., as part of a
|
||||
* larger array). If the same array or array element is passed more than once
|
||||
* to drupal_render(), it simply returns a NULL value.
|
||||
* to drupal_render(), it simply returns an empty string.
|
||||
*
|
||||
* @param $elements
|
||||
* @param array $elements
|
||||
* The structured array describing the data to be rendered.
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* The rendered HTML.
|
||||
*/
|
||||
function drupal_render(&$elements) {
|
||||
// Early-return nothing if user does not have access.
|
||||
if (empty($elements) || (isset($elements['#access']) && !$elements['#access'])) {
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Do not print elements twice.
|
||||
if (!empty($elements['#printed'])) {
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Try to fetch the element's markup from cache and return.
|
||||
@@ -5825,7 +5886,7 @@ function drupal_render(&$elements) {
|
||||
|
||||
// Allow #pre_render to abort rendering.
|
||||
if (!empty($elements['#printed'])) {
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Get the children of the element, sorted by weight.
|
||||
@@ -5896,14 +5957,16 @@ function drupal_render(&$elements) {
|
||||
/**
|
||||
* Renders children of an element and concatenates them.
|
||||
*
|
||||
* This renders all children of an element using drupal_render() and then
|
||||
* joins them together into a single string.
|
||||
*
|
||||
* @param $element
|
||||
* @param array $element
|
||||
* The structured array whose children shall be rendered.
|
||||
* @param $children_keys
|
||||
* If the keys of the element's children are already known, they can be passed
|
||||
* in to save another run of element_children().
|
||||
* @param array $children_keys
|
||||
* (optional) If the keys of the element's children are already known, they
|
||||
* can be passed in to save another run of element_children().
|
||||
*
|
||||
* @return string
|
||||
* The rendered HTML of all children of the element.
|
||||
|
||||
* @see drupal_render()
|
||||
*/
|
||||
function drupal_render_children(&$element, $children_keys = NULL) {
|
||||
if ($children_keys === NULL) {
|
||||
@@ -6447,6 +6510,44 @@ function element_set_attributes(array &$element, array $map) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively computes the difference of arrays with additional index check.
|
||||
*
|
||||
* This is a version of array_diff_assoc() that supports multidimensional
|
||||
* arrays.
|
||||
*
|
||||
* @param array $array1
|
||||
* The array to compare from.
|
||||
* @param array $array2
|
||||
* The array to compare to.
|
||||
*
|
||||
* @return array
|
||||
* Returns an array containing all the values from array1 that are not present
|
||||
* in array2.
|
||||
*/
|
||||
function drupal_array_diff_assoc_recursive($array1, $array2) {
|
||||
$difference = array();
|
||||
|
||||
foreach ($array1 as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
if (!array_key_exists($key, $array2) || !is_array($array2[$key])) {
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
else {
|
||||
$new_diff = drupal_array_diff_assoc_recursive($value, $array2[$key]);
|
||||
if (!empty($new_diff)) {
|
||||
$difference[$key] = $new_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (!array_key_exists($key, $array2) || $array2[$key] !== $value) {
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $difference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in a nested array with variable depth.
|
||||
*
|
||||
@@ -7739,7 +7840,10 @@ function entity_load_unchanged($entity_type, $id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity controller class for an entity type.
|
||||
* Gets the entity controller for an entity type.
|
||||
*
|
||||
* @return DrupalEntityControllerInterface
|
||||
* The entity controller object for the specified entity type.
|
||||
*/
|
||||
function entity_get_controller($entity_type) {
|
||||
$controllers = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
@@ -28,18 +28,21 @@
|
||||
* Most Drupal database SELECT queries are performed by a call to db_query() or
|
||||
* db_query_range(). Module authors should also consider using the PagerDefault
|
||||
* Extender for queries that return results that need to be presented on
|
||||
* multiple pages, and the Tablesort Extender for generating appropriate queries
|
||||
* for sortable tables.
|
||||
* multiple pages (see https://drupal.org/node/508796), and the TableSort
|
||||
* Extender for generating appropriate queries for sortable tables
|
||||
* (see https://drupal.org/node/1848372).
|
||||
*
|
||||
* For example, one might wish to return a list of the most recent 10 nodes
|
||||
* authored by a given user. Instead of directly issuing the SQL query
|
||||
* @code
|
||||
* SELECT n.nid, n.title, n.created FROM node n WHERE n.uid = $uid LIMIT 0, 10;
|
||||
* SELECT n.nid, n.title, n.created FROM node n WHERE n.uid = $uid
|
||||
* ORDER BY n.created DESC LIMIT 0, 10;
|
||||
* @endcode
|
||||
* one would instead call the Drupal functions:
|
||||
* @code
|
||||
* $result = db_query_range('SELECT n.nid, n.title, n.created
|
||||
* FROM {node} n WHERE n.uid = :uid', 0, 10, array(':uid' => $uid));
|
||||
* FROM {node} n WHERE n.uid = :uid
|
||||
* ORDER BY n.created DESC', 0, 10, array(':uid' => $uid));
|
||||
* foreach ($result as $record) {
|
||||
* // Perform operations on $record->title, etc. here.
|
||||
* }
|
||||
@@ -167,7 +170,7 @@
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @link http://drupal.org/developing/api/database @endlink
|
||||
* @see http://drupal.org/developing/api/database
|
||||
*/
|
||||
|
||||
|
||||
@@ -179,7 +182,7 @@
|
||||
* concrete implementation of it to support special handling required by that
|
||||
* database.
|
||||
*
|
||||
* @see http://php.net/manual/en/book.pdo.php
|
||||
* @see http://php.net/manual/book.pdo.php
|
||||
*/
|
||||
abstract class DatabaseConnection extends PDO {
|
||||
|
||||
@@ -194,7 +197,7 @@ abstract class DatabaseConnection extends PDO {
|
||||
|
||||
/**
|
||||
* The key representing this connection.
|
||||
*
|
||||
*
|
||||
* The key is a unique string which identifies a database connection. A
|
||||
* connection can be a single server or a cluster of master and slaves (use
|
||||
* target to pick between master and slave).
|
||||
@@ -303,12 +306,28 @@ abstract class DatabaseConnection extends PDO {
|
||||
// Call PDO::__construct and PDO::setAttribute.
|
||||
parent::__construct($dsn, $username, $password, $driver_options);
|
||||
|
||||
// Set a specific PDOStatement class if the driver requires that.
|
||||
// Set a Statement class, unless the driver opted out.
|
||||
if (!empty($this->statementClass)) {
|
||||
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys this Connection object.
|
||||
*
|
||||
* PHP does not destruct an object if it is still referenced in other
|
||||
* variables. In case of PDO database connection objects, PHP only closes the
|
||||
* connection when the PDO object is destructed, so any references to this
|
||||
* object may cause the number of maximum allowed connections to be exceeded.
|
||||
*/
|
||||
public function destroy() {
|
||||
// Destroy all references to this connection by setting them to NULL.
|
||||
// The Statement class attribute only accepts a new value that presents a
|
||||
// proper callable, so we reset it to PDOStatement.
|
||||
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array()));
|
||||
$this->schema = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default query options for any given query.
|
||||
*
|
||||
@@ -1627,8 +1646,8 @@ abstract class Database {
|
||||
*/
|
||||
final public static function removeConnection($key) {
|
||||
if (isset(self::$databaseInfo[$key])) {
|
||||
self::closeConnection(NULL, $key);
|
||||
unset(self::$databaseInfo[$key]);
|
||||
unset(self::$connections[$key]);
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
@@ -1694,11 +1713,24 @@ abstract class Database {
|
||||
if (!isset($key)) {
|
||||
$key = self::$activeKey;
|
||||
}
|
||||
// To close the connection, we need to unset the static variable.
|
||||
// To close a connection, it needs to be set to NULL and removed from the
|
||||
// static variable. In all cases, closeConnection() might be called for a
|
||||
// connection that was not opened yet, in which case the key is not defined
|
||||
// yet and we just ensure that the connection key is undefined.
|
||||
if (isset($target)) {
|
||||
if (isset(self::$connections[$key][$target])) {
|
||||
self::$connections[$key][$target]->destroy();
|
||||
self::$connections[$key][$target] = NULL;
|
||||
}
|
||||
unset(self::$connections[$key][$target]);
|
||||
}
|
||||
else {
|
||||
if (isset(self::$connections[$key])) {
|
||||
foreach (self::$connections[$key] as $target => $connection) {
|
||||
self::$connections[$key][$target]->destroy();
|
||||
self::$connections[$key][$target] = NULL;
|
||||
}
|
||||
}
|
||||
unset(self::$connections[$key]);
|
||||
}
|
||||
}
|
||||
@@ -1852,8 +1884,8 @@ class DatabaseTransaction {
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
public function __construct(DatabaseConnection &$connection, $name = NULL) {
|
||||
$this->connection = &$connection;
|
||||
public function __construct(DatabaseConnection $connection, $name = NULL) {
|
||||
$this->connection = $connection;
|
||||
// If there is no transaction depth, then no transaction has started. Name
|
||||
// the transaction 'drupal_transaction'.
|
||||
if (!$depth = $connection->transactionDepth()) {
|
||||
@@ -1957,7 +1989,7 @@ interface DatabaseStatementInterface extends Traversable {
|
||||
/**
|
||||
* Sets the default fetch mode for this statement.
|
||||
*
|
||||
* See http://php.net/manual/en/pdo.constants.php for the definition of the
|
||||
* See http://php.net/manual/pdo.constants.php for the definition of the
|
||||
* constants used.
|
||||
*
|
||||
* @param $mode
|
||||
@@ -1976,7 +2008,7 @@ interface DatabaseStatementInterface extends Traversable {
|
||||
/**
|
||||
* Fetches the next row from a result set.
|
||||
*
|
||||
* See http://php.net/manual/en/pdo.constants.php for the definition of the
|
||||
* See http://php.net/manual/pdo.constants.php for the definition of the
|
||||
* constants used.
|
||||
*
|
||||
* @param $mode
|
||||
@@ -2351,14 +2383,14 @@ function db_query_range($query, $from, $count, array $args = array(), array $opt
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a query string and saves the result set to a temporary table.
|
||||
* Executes a SELECT query string and saves the result set to a temporary table.
|
||||
*
|
||||
* The execution of the query string happens against the active database.
|
||||
*
|
||||
* @param $query
|
||||
* The prepared statement query to run. Although it will accept both named and
|
||||
* unnamed placeholders, named placeholders are strongly preferred as they are
|
||||
* more self-documenting.
|
||||
* The prepared SELECT statement query to run. Although it will accept both
|
||||
* named and unnamed placeholders, named placeholders are strongly preferred
|
||||
* as they are more self-documenting.
|
||||
* @param $args
|
||||
* An array of values to substitute into the query. If the query uses named
|
||||
* placeholders, this is an associative array in any order. If the query uses
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
|
||||
/**
|
||||
* Flag to indicate if we have registered the nextID cleanup function.
|
||||
* Flag to indicate if the cleanup function in __destruct() should run.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $shutdownRegistered = FALSE;
|
||||
protected $needsCleanup = FALSE;
|
||||
|
||||
public function __construct(array $connection_options = array()) {
|
||||
// This driver defaults to transaction support, except if explicitly passed FALSE.
|
||||
@@ -78,13 +78,19 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
$this->exec(implode('; ', $connection_options['init_commands']));
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
if ($this->needsCleanup) {
|
||||
$this->nextIdDelete();
|
||||
}
|
||||
}
|
||||
|
||||
public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
|
||||
return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options);
|
||||
}
|
||||
|
||||
public function queryTemporary($query, array $args = array(), array $options = array()) {
|
||||
$tablename = $this->generateTemporaryTableName();
|
||||
$this->query(preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE {' . $tablename . '} Engine=MEMORY SELECT', $query), $args, $options);
|
||||
$this->query('CREATE TEMPORARY TABLE {' . $tablename . '} Engine=MEMORY ' . $query, $args, $options);
|
||||
return $tablename;
|
||||
}
|
||||
|
||||
@@ -115,12 +121,7 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
$this->query('INSERT INTO {sequences} (value) VALUES (:value) ON DUPLICATE KEY UPDATE value = value', array(':value' => $existing_id));
|
||||
$new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
|
||||
}
|
||||
if (!$this->shutdownRegistered) {
|
||||
// Use register_shutdown_function() here to keep the database system
|
||||
// independent of Drupal.
|
||||
register_shutdown_function(array($this, 'nextIdDelete'));
|
||||
$shutdownRegistered = TRUE;
|
||||
}
|
||||
$this->needsCleanup = TRUE;
|
||||
return $new_id;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ class InsertQuery_mysql extends InsertQuery {
|
||||
// If we're selecting from a SelectQuery, finish building the query and
|
||||
// pass it back, as any remaining options are irrelevant.
|
||||
if (!empty($this->fromQuery)) {
|
||||
return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
|
||||
$insert_fields_string = $insert_fields ? ' (' . implode(', ', $insert_fields) . ') ' : ' ';
|
||||
return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
|
||||
}
|
||||
|
||||
$query = $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
|
||||
@@ -86,21 +87,7 @@ class InsertQuery_mysql extends InsertQuery {
|
||||
}
|
||||
}
|
||||
|
||||
class TruncateQuery_mysql extends TruncateQuery {
|
||||
public function __toString() {
|
||||
// TRUNCATE is actually a DDL statement on MySQL, and DDL statements are
|
||||
// not transactional, and result in an implicit COMMIT. When we are in a
|
||||
// transaction, fallback to the slower, but transactional, DELETE.
|
||||
if ($this->connection->inTransaction()) {
|
||||
// Create a comment string to prepend to the query.
|
||||
$comments = $this->connection->makeComment($this->comments);
|
||||
return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '}';
|
||||
}
|
||||
else {
|
||||
return parent::__toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
class TruncateQuery_mysql extends TruncateQuery { }
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup database".
|
||||
|
||||
@@ -146,7 +146,7 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
|
||||
|
||||
public function queryTemporary($query, array $args = array(), array $options = array()) {
|
||||
$tablename = $this->generateTemporaryTableName();
|
||||
$this->query(preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE {' . $tablename . '} AS SELECT', $query), $args, $options);
|
||||
$this->query('CREATE TEMPORARY TABLE {' . $tablename . '} AS ' . $query, $args, $options);
|
||||
return $tablename;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,8 @@ class InsertQuery_pgsql extends InsertQuery {
|
||||
// If we're selecting from a SelectQuery, finish building the query and
|
||||
// pass it back, as any remaining options are irrelevant.
|
||||
if (!empty($this->fromQuery)) {
|
||||
return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
|
||||
$insert_fields_string = $insert_fields ? ' (' . implode(', ', $insert_fields) . ') ' : ' ';
|
||||
return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
|
||||
}
|
||||
|
||||
$query = $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
|
||||
|
||||
@@ -83,7 +83,7 @@ interface QueryConditionInterface {
|
||||
|
||||
/**
|
||||
* Sets a condition that the specified subquery returns values.
|
||||
*
|
||||
*
|
||||
* @param SelectQueryInterface $select
|
||||
* The subquery that must contain results.
|
||||
*
|
||||
@@ -91,10 +91,10 @@ interface QueryConditionInterface {
|
||||
* The called object.
|
||||
*/
|
||||
public function exists(SelectQueryInterface $select);
|
||||
|
||||
|
||||
/**
|
||||
* Sets a condition that the specified subquery returns no values.
|
||||
*
|
||||
*
|
||||
* @param SelectQueryInterface $select
|
||||
* The subquery that must not contain results.
|
||||
*
|
||||
@@ -102,7 +102,7 @@ interface QueryConditionInterface {
|
||||
* The called object.
|
||||
*/
|
||||
public function notExists(SelectQueryInterface $select);
|
||||
|
||||
|
||||
/**
|
||||
* Gets a complete list of all conditions in this conditional clause.
|
||||
*
|
||||
@@ -283,14 +283,14 @@ abstract class Query implements QueryPlaceholderInterface {
|
||||
|
||||
/**
|
||||
* The target of the connection object.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connectionTarget;
|
||||
|
||||
/**
|
||||
* The key of the connection object.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connectionKey;
|
||||
@@ -710,10 +710,11 @@ class InsertQuery extends Query {
|
||||
// first call to fields() does have an effect.
|
||||
$this->fields(array_merge(array_keys($this->fromQuery->getFields()), array_keys($this->fromQuery->getExpressions())));
|
||||
}
|
||||
|
||||
// Don't execute query without fields.
|
||||
if (count($this->insertFields) + count($this->defaultFields) == 0) {
|
||||
throw new NoFieldsException('There are no fields available to insert with.');
|
||||
else {
|
||||
// Don't execute query without fields.
|
||||
if (count($this->insertFields) + count($this->defaultFields) == 0) {
|
||||
throw new NoFieldsException('There are no fields available to insert with.');
|
||||
}
|
||||
}
|
||||
|
||||
// If no values have been added, silently ignore this query. This can happen
|
||||
@@ -804,7 +805,7 @@ class DeleteQuery extends Query implements QueryConditionInterface {
|
||||
$this->condition->notExists($select);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements QueryConditionInterface::conditions().
|
||||
*/
|
||||
@@ -942,7 +943,17 @@ class TruncateQuery extends Query {
|
||||
// Create a sanitized comment string to prepend to the query.
|
||||
$comments = $this->connection->makeComment($this->comments);
|
||||
|
||||
return $comments . 'TRUNCATE {' . $this->connection->escapeTable($this->table) . '} ';
|
||||
// In most cases, TRUNCATE is not a transaction safe statement as it is a
|
||||
// DDL statement which results in an implicit COMMIT. When we are in a
|
||||
// transaction, fallback to the slower, but transactional, DELETE.
|
||||
// PostgreSQL also locks the entire table for a TRUNCATE strongly reducing
|
||||
// the concurrency with other transactions.
|
||||
if ($this->connection->inTransaction()) {
|
||||
return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '}';
|
||||
}
|
||||
else {
|
||||
return $comments . 'TRUNCATE {' . $this->connection->escapeTable($this->table) . '} ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1053,7 +1064,7 @@ class UpdateQuery extends Query implements QueryConditionInterface {
|
||||
$this->condition->notExists($select);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements QueryConditionInterface::conditions().
|
||||
*/
|
||||
@@ -1545,7 +1556,7 @@ class MergeQuery extends Query implements QueryConditionInterface {
|
||||
$this->condition->notExists($select);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements QueryConditionInterface::conditions().
|
||||
*/
|
||||
@@ -1595,55 +1606,43 @@ class MergeQuery extends Query implements QueryConditionInterface {
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
// Wrap multiple queries in a transaction, if the database supports it.
|
||||
$transaction = $this->connection->startTransaction();
|
||||
try {
|
||||
if (!count($this->condition)) {
|
||||
throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
|
||||
if (!count($this->condition)) {
|
||||
throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
|
||||
}
|
||||
$select = $this->connection->select($this->conditionTable)
|
||||
->condition($this->condition);
|
||||
$select->addExpression('1');
|
||||
if (!$select->execute()->fetchField()) {
|
||||
try {
|
||||
$insert = $this->connection->insert($this->table)->fields($this->insertFields);
|
||||
if ($this->defaultFields) {
|
||||
$insert->useDefaults($this->defaultFields);
|
||||
}
|
||||
$insert->execute();
|
||||
return self::STATUS_INSERT;
|
||||
}
|
||||
$select = $this->connection->select($this->conditionTable)
|
||||
->condition($this->condition)
|
||||
->forUpdate();
|
||||
$select->addExpression('1');
|
||||
if (!$select->execute()->fetchField()) {
|
||||
try {
|
||||
$insert = $this->connection->insert($this->table)->fields($this->insertFields);
|
||||
if ($this->defaultFields) {
|
||||
$insert->useDefaults($this->defaultFields);
|
||||
}
|
||||
$insert->execute();
|
||||
return MergeQuery::STATUS_INSERT;
|
||||
catch (Exception $e) {
|
||||
// The insert query failed, maybe it's because a racing insert query
|
||||
// beat us in inserting the same row. Retry the select query, if it
|
||||
// returns a row, ignore the error and continue with the update
|
||||
// query below.
|
||||
if (!$select->execute()->fetchField()) {
|
||||
throw $e;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// The insert query failed, maybe it's because a racing insert query
|
||||
// beat us in inserting the same row. Retry the select query, if it
|
||||
// returns a row, ignore the error and continue with the update
|
||||
// query below.
|
||||
if (!$select->execute()->fetchField()) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->needsUpdate) {
|
||||
$update = $this->connection->update($this->table)
|
||||
->fields($this->updateFields)
|
||||
->condition($this->condition);
|
||||
if ($this->expressionFields) {
|
||||
foreach ($this->expressionFields as $field => $data) {
|
||||
$update->expression($field, $data['expression'], $data['arguments']);
|
||||
}
|
||||
}
|
||||
$update->execute();
|
||||
return MergeQuery::STATUS_UPDATE;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Something really wrong happened here, bubble up the exception to the
|
||||
// caller.
|
||||
$transaction->rollback();
|
||||
throw $e;
|
||||
}
|
||||
// Transaction commits here where $transaction looses scope.
|
||||
if ($this->needsUpdate) {
|
||||
$update = $this->connection->update($this->table)
|
||||
->fields($this->updateFields)
|
||||
->condition($this->condition);
|
||||
if ($this->expressionFields) {
|
||||
foreach ($this->expressionFields as $field => $data) {
|
||||
$update->expression($field, $data['expression'], $data['arguments']);
|
||||
}
|
||||
}
|
||||
$update->execute();
|
||||
return self::STATUS_UPDATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1762,14 +1761,14 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
|
||||
public function exists(SelectQueryInterface $select) {
|
||||
return $this->condition('', $select, 'EXISTS');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements QueryConditionInterface::notExists().
|
||||
*/
|
||||
public function notExists(SelectQueryInterface $select) {
|
||||
return $this->condition('', $select, 'NOT EXISTS');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements QueryConditionInterface::conditions().
|
||||
*/
|
||||
@@ -1898,8 +1897,13 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
|
||||
function __clone() {
|
||||
$this->changed = TRUE;
|
||||
foreach ($this->conditions as $key => $condition) {
|
||||
if ($key !== '#conjunction' && $condition['field'] instanceOf QueryConditionInterface) {
|
||||
$this->conditions[$key]['field'] = clone($condition['field']);
|
||||
if ($key !== '#conjunction') {
|
||||
if ($condition['field'] instanceOf QueryConditionInterface) {
|
||||
$this->conditions[$key]['field'] = clone($condition['field']);
|
||||
}
|
||||
if ($condition['value'] instanceOf SelectQueryInterface) {
|
||||
$this->conditions[$key]['value'] = clone($condition['value']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,7 +596,7 @@ class SelectQueryExtender implements SelectQueryInterface {
|
||||
|
||||
public function hasAnyTag() {
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(array($this->query, 'hasAnyTags'), $args);
|
||||
return call_user_func_array(array($this->query, 'hasAnyTag'), $args);
|
||||
}
|
||||
|
||||
public function addMetaData($key, $object) {
|
||||
|
||||
@@ -250,7 +250,7 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
|
||||
$prefixes[$tablename] = '';
|
||||
$this->setPrefix($prefixes);
|
||||
|
||||
$this->query(preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE ' . $tablename . ' AS SELECT', $query), $args, $options);
|
||||
$this->query('CREATE TEMPORARY TABLE ' . $tablename . ' AS ' . $query, $args, $options);
|
||||
return $tablename;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,8 @@ class InsertQuery_sqlite extends InsertQuery {
|
||||
// If we're selecting from a SelectQuery, finish building the query and
|
||||
// pass it back, as any remaining options are irrelevant.
|
||||
if (!empty($this->fromQuery)) {
|
||||
return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') ' . $this->fromQuery;
|
||||
$insert_fields_string = $this->insertFields ? ' (' . implode(', ', $this->insertFields) . ') ' : ' ';
|
||||
return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery;
|
||||
}
|
||||
|
||||
return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') VALUES (' . implode(', ', $placeholders) . ')';
|
||||
@@ -57,39 +58,18 @@ class InsertQuery_sqlite extends InsertQuery {
|
||||
* we don't select those rows.
|
||||
*
|
||||
* A query like this one:
|
||||
* UPDATE test SET name = 'newname' WHERE tid = 1
|
||||
* UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1
|
||||
* will become:
|
||||
* UPDATE test SET name = 'newname' WHERE tid = 1 AND name <> 'newname'
|
||||
* UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1 AND (col1 <> 'newcol1' OR col2 <> 'newcol2')
|
||||
*/
|
||||
class UpdateQuery_sqlite extends UpdateQuery {
|
||||
/**
|
||||
* Helper function that removes the fields that are already in a condition.
|
||||
*
|
||||
* @param $fields
|
||||
* The fields.
|
||||
* @param QueryConditionInterface $condition
|
||||
* A database condition.
|
||||
*/
|
||||
protected function removeFieldsInCondition(&$fields, QueryConditionInterface $condition) {
|
||||
foreach ($condition->conditions() as $child_condition) {
|
||||
if ($child_condition['field'] instanceof QueryConditionInterface) {
|
||||
$this->removeFieldsInCondition($fields, $child_condition['field']);
|
||||
}
|
||||
else {
|
||||
unset($fields[$child_condition['field']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if (!empty($this->queryOptions['sqlite_return_matched_rows'])) {
|
||||
return parent::execute();
|
||||
}
|
||||
|
||||
// Get the fields used in the update query, and remove those that are already
|
||||
// in the condition.
|
||||
// Get the fields used in the update query.
|
||||
$fields = $this->expressionFields + $this->fields;
|
||||
$this->removeFieldsInCondition($fields, $this->condition);
|
||||
|
||||
// Add the inverse of the fields to the condition.
|
||||
$condition = new DatabaseCondition('OR');
|
||||
|
||||
@@ -13,14 +13,6 @@
|
||||
*/
|
||||
interface DrupalEntityControllerInterface {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param $entityType
|
||||
* The entity type for which the instance is created.
|
||||
*/
|
||||
public function __construct($entityType);
|
||||
|
||||
/**
|
||||
* Resets the internal, static entity cache.
|
||||
*
|
||||
@@ -119,6 +111,9 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
|
||||
|
||||
/**
|
||||
* Constructor: sets basic variables.
|
||||
*
|
||||
* @param $entityType
|
||||
* The entity type for which the instance is created.
|
||||
*/
|
||||
public function __construct($entityType) {
|
||||
$this->entityType = $entityType;
|
||||
@@ -365,9 +360,23 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
|
||||
// This ensures the same behavior whether loading from memory or database.
|
||||
if ($conditions) {
|
||||
foreach ($entities as $entity) {
|
||||
$entity_values = (array) $entity;
|
||||
if (array_diff_assoc($conditions, $entity_values)) {
|
||||
unset($entities[$entity->{$this->idKey}]);
|
||||
// Iterate over all conditions and compare them to the entity
|
||||
// properties. We cannot use array_diff_assoc() here since the
|
||||
// conditions can be nested arrays, too.
|
||||
foreach ($conditions as $property_name => $condition) {
|
||||
if (is_array($condition)) {
|
||||
// Multiple condition values for one property are treated as OR
|
||||
// operation: only if the value is not at all in the condition array
|
||||
// we remove the entity.
|
||||
if (!in_array($entity->{$property_name}, $condition)) {
|
||||
unset($entities[$entity->{$this->idKey}]);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
elseif ($condition != $entity->{$property_name}) {
|
||||
unset($entities[$entity->{$this->idKey}]);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -634,7 +643,7 @@ class EntityFieldQuery {
|
||||
|
||||
/**
|
||||
* Adds a condition on field values.
|
||||
*
|
||||
*
|
||||
* Note that entities with empty field values will be excluded from the
|
||||
* EntityFieldQuery results when using this method.
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Maps PHP error constants to watchdog severity levels.
|
||||
*
|
||||
* The error constants are documented at
|
||||
* http://php.net/manual/en/errorfunc.constants.php
|
||||
* http://php.net/manual/errorfunc.constants.php
|
||||
*
|
||||
* @ingroup logging_severity_levels
|
||||
*/
|
||||
@@ -169,7 +169,7 @@ function error_displayable($error = NULL) {
|
||||
* TRUE if the error is fatal.
|
||||
*/
|
||||
function _drupal_log_error($error, $fatal = FALSE) {
|
||||
// Initialize a maintenance theme if the boostrap was not complete.
|
||||
// Initialize a maintenance theme if the bootstrap was not complete.
|
||||
// Do it early because drupal_set_message() triggers a drupal_theme_initialize().
|
||||
if ($fatal && (drupal_get_bootstrap_phase() != DRUPAL_BOOTSTRAP_FULL)) {
|
||||
unset($GLOBALS['theme']);
|
||||
|
||||
@@ -89,7 +89,7 @@ define('FILE_STATUS_PERMANENT', 1);
|
||||
* wrappers that are appropriate for particular usage. For example, this returns
|
||||
* only stream wrappers that use local file storage:
|
||||
* @code
|
||||
* $local_stream_wrappers = file_get_stream_wrappers(STEAM_WRAPPERS_LOCAL);
|
||||
* $local_stream_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL);
|
||||
* @endcode
|
||||
*
|
||||
* The $filter parameter can only filter to types containing a particular flag.
|
||||
@@ -99,7 +99,7 @@ define('FILE_STATUS_PERMANENT', 1);
|
||||
* array_diff_key() function can be used to help with this. For example, this
|
||||
* returns only stream wrappers that do not use local file storage:
|
||||
* @code
|
||||
* $remote_stream_wrappers = array_diff_key(file_get_stream_wrappers(STREAM_WRAPPERS_ALL), file_get_stream_wrappers(STEAM_WRAPPERS_LOCAL));
|
||||
* $remote_stream_wrappers = array_diff_key(file_get_stream_wrappers(STREAM_WRAPPERS_ALL), file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL));
|
||||
* @endcode
|
||||
*
|
||||
* @param $filter
|
||||
@@ -282,10 +282,6 @@ function file_stream_wrapper_uri_normalize($uri) {
|
||||
$uri = $scheme . '://' . $target;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The default scheme is file://
|
||||
$url = 'file://' . $uri;
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
|
||||
@@ -474,8 +470,11 @@ function file_ensure_htaccess() {
|
||||
* @param $private
|
||||
* FALSE indicates that $directory should be an open and public directory.
|
||||
* The default is TRUE which indicates a private and protected directory.
|
||||
* @param $force_overwrite
|
||||
* Set to TRUE to attempt to overwrite the existing .htaccess file if one is
|
||||
* already present. Defaults to FALSE.
|
||||
*/
|
||||
function file_create_htaccess($directory, $private = TRUE) {
|
||||
function file_create_htaccess($directory, $private = TRUE, $force_overwrite = FALSE) {
|
||||
if (file_uri_scheme($directory)) {
|
||||
$directory = file_stream_wrapper_uri_normalize($directory);
|
||||
}
|
||||
@@ -484,19 +483,12 @@ function file_create_htaccess($directory, $private = TRUE) {
|
||||
}
|
||||
$htaccess_path = $directory . '/.htaccess';
|
||||
|
||||
if (file_exists($htaccess_path)) {
|
||||
if (file_exists($htaccess_path) && !$force_overwrite) {
|
||||
// Short circuit if the .htaccess file already exists.
|
||||
return;
|
||||
}
|
||||
|
||||
if ($private) {
|
||||
// Private .htaccess file.
|
||||
$htaccess_lines = "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nDeny from all\nOptions None\nOptions +FollowSymLinks";
|
||||
}
|
||||
else {
|
||||
// Public .htaccess file.
|
||||
$htaccess_lines = "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\nOptions +FollowSymLinks";
|
||||
}
|
||||
$htaccess_lines = file_htaccess_lines($private);
|
||||
|
||||
// Write the .htaccess file.
|
||||
if (file_put_contents($htaccess_path, $htaccess_lines)) {
|
||||
@@ -508,6 +500,45 @@ function file_create_htaccess($directory, $private = TRUE) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the standard .htaccess lines that Drupal writes to file directories.
|
||||
*
|
||||
* @param $private
|
||||
* (Optional) Set to FALSE to return the .htaccess lines for an open and
|
||||
* public directory. The default is TRUE, which returns the .htaccess lines
|
||||
* for a private and protected directory.
|
||||
*
|
||||
* @return
|
||||
* A string representing the desired contents of the .htaccess file.
|
||||
*
|
||||
* @see file_create_htaccess()
|
||||
*/
|
||||
function file_htaccess_lines($private = TRUE) {
|
||||
$lines = <<<EOF
|
||||
# Turn off all options we don't need.
|
||||
Options None
|
||||
Options +FollowSymLinks
|
||||
|
||||
# Set the catch-all handler to prevent scripts from being executed.
|
||||
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
|
||||
<Files *>
|
||||
# Override the handler again if we're run later in the evaluation list.
|
||||
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
|
||||
</Files>
|
||||
|
||||
# If we know how to do it safely, disable the PHP engine entirely.
|
||||
<IfModule mod_php5.c>
|
||||
php_flag engine off
|
||||
</IfModule>
|
||||
EOF;
|
||||
|
||||
if ($private) {
|
||||
$lines = "Deny from all\n\n" . $lines;
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads file objects from the database.
|
||||
*
|
||||
@@ -590,7 +621,11 @@ function file_save(stdClass $file) {
|
||||
module_invoke_all('entity_update', $file, 'file');
|
||||
}
|
||||
|
||||
// Clear internal properties.
|
||||
unset($file->original);
|
||||
// Clear the static loading cache.
|
||||
entity_get_controller('file')->resetCache(array($file->fid));
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
@@ -723,10 +758,11 @@ function file_usage_delete(stdClass $file, $module, $type = NULL, $id = NULL, $c
|
||||
* stored in the database. This is a powerful function that in many ways
|
||||
* performs like an advanced version of copy().
|
||||
* - Checks if $source and $destination are valid and readable/writable.
|
||||
* - Checks that $source is not equal to $destination; if they are an error
|
||||
* is reported.
|
||||
* - If file already exists in $destination either the call will error out,
|
||||
* replace the file or rename the file based on the $replace parameter.
|
||||
* - If the $source and $destination are equal, the behavior depends on the
|
||||
* $replace parameter. FILE_EXISTS_REPLACE will error out. FILE_EXISTS_RENAME
|
||||
* will rename the file until the $destination is unique.
|
||||
* - Adds the new file to the files database. If the source file is a
|
||||
* temporary file, the resulting file will also be a temporary file. See
|
||||
* file_save_upload() for details on temporary files.
|
||||
@@ -821,10 +857,11 @@ function file_valid_uri($uri) {
|
||||
* This is a powerful function that in many ways performs like an advanced
|
||||
* version of copy().
|
||||
* - Checks if $source and $destination are valid and readable/writable.
|
||||
* - Checks that $source is not equal to $destination; if they are an error
|
||||
* is reported.
|
||||
* - If file already exists in $destination either the call will error out,
|
||||
* replace the file or rename the file based on the $replace parameter.
|
||||
* - If the $source and $destination are equal, the behavior depends on the
|
||||
* $replace parameter. FILE_EXISTS_REPLACE will error out. FILE_EXISTS_RENAME
|
||||
* will rename the file until the $destination is unique.
|
||||
* - Provides a fallback using realpaths if the move fails using stream
|
||||
* wrappers. This can occur because PHP's copy() function does not properly
|
||||
* support streams if safe_mode or open_basedir are enabled. See
|
||||
@@ -834,9 +871,8 @@ function file_valid_uri($uri) {
|
||||
* A string specifying the filepath or URI of the source file.
|
||||
* @param $destination
|
||||
* A URI containing the destination that $source should be copied to. The
|
||||
* URI may be a bare filepath (without a scheme) and in that case the default
|
||||
* scheme (file://) will be used. If this value is omitted, Drupal's default
|
||||
* files scheme will be used, usually "public://".
|
||||
* URI may be a bare filepath (without a scheme). If this value is omitted,
|
||||
* Drupal's default files scheme will be used, usually "public://".
|
||||
* @param $replace
|
||||
* Replace behavior when the destination file already exists:
|
||||
* - FILE_EXISTS_REPLACE - Replace the existing file.
|
||||
@@ -892,7 +928,7 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
|
||||
$destination = file_destination($destination, $replace);
|
||||
if ($destination === FALSE) {
|
||||
drupal_set_message(t('The file %file could not be copied because a file by that name already exists in the destination directory.', array('%file' => $original_source)), 'error');
|
||||
watchdog('file', 'File %file could not be copied because a file by that name already exists in the destination directory (%directory)', array('%file' => $original_source, '%destination' => $destination));
|
||||
watchdog('file', 'File %file could not be copied because a file by that name already exists in the destination directory (%directory)', array('%file' => $original_source, '%directory' => $destination));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1113,7 +1149,7 @@ function file_munge_filename($filename, $extensions, $alerts = TRUE) {
|
||||
|
||||
// Allow potentially insecure uploads for very savvy users and admin
|
||||
if (!variable_get('allow_insecure_uploads', 0)) {
|
||||
// Remove any null bytes. See http://php.net/manual/en/security.filesystem.nullbytes.php
|
||||
// Remove any null bytes. See http://php.net/manual/security.filesystem.nullbytes.php
|
||||
$filename = str_replace(chr(0), '', $filename);
|
||||
|
||||
$whitelist = array_unique(explode(' ', trim($extensions)));
|
||||
@@ -1261,6 +1297,7 @@ function file_delete(stdClass $file, $force = FALSE) {
|
||||
if (file_unmanaged_delete($file->uri)) {
|
||||
db_delete('file_managed')->condition('fid', $file->fid)->execute();
|
||||
db_delete('file_usage')->condition('fid', $file->fid)->execute();
|
||||
entity_get_controller('file')->resetCache();
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1370,8 +1407,9 @@ function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
|
||||
* Temporary files are periodically cleaned. To make the file a permanent file,
|
||||
* assign the status and use file_save() to save the changes.
|
||||
*
|
||||
* @param $source
|
||||
* A string specifying the filepath or URI of the uploaded file to save.
|
||||
* @param $form_field_name
|
||||
* A string that is the associative array key of the upload form element in
|
||||
* the form array.
|
||||
* @param $validators
|
||||
* An optional, associative array of callback functions used to validate the
|
||||
* file. See file_validate() for a full discussion of the array format.
|
||||
@@ -1382,9 +1420,9 @@ function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
|
||||
* (Beware: this is not safe and should only be allowed for trusted users, if
|
||||
* at all).
|
||||
* @param $destination
|
||||
* A string containing the URI $source should be copied to.
|
||||
* This must be a stream wrapper URI. If this value is omitted, Drupal's
|
||||
* temporary files scheme will be used ("temporary://").
|
||||
* A string containing the URI that the file should be copied to. This must
|
||||
* be a stream wrapper URI. If this value is omitted, Drupal's temporary
|
||||
* files scheme will be used ("temporary://").
|
||||
* @param $replace
|
||||
* Replace behavior when the destination file already exists:
|
||||
* - FILE_EXISTS_REPLACE: Replace the existing file.
|
||||
@@ -1402,45 +1440,45 @@ function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
|
||||
* - source: Path to the file before it is moved.
|
||||
* - destination: Path to the file after it is moved (same as 'uri').
|
||||
*/
|
||||
function file_save_upload($source, $validators = array(), $destination = FALSE, $replace = FILE_EXISTS_RENAME) {
|
||||
function file_save_upload($form_field_name, $validators = array(), $destination = FALSE, $replace = FILE_EXISTS_RENAME) {
|
||||
global $user;
|
||||
static $upload_cache;
|
||||
|
||||
// Return cached objects without processing since the file will have
|
||||
// already been processed and the paths in _FILES will be invalid.
|
||||
if (isset($upload_cache[$source])) {
|
||||
return $upload_cache[$source];
|
||||
if (isset($upload_cache[$form_field_name])) {
|
||||
return $upload_cache[$form_field_name];
|
||||
}
|
||||
|
||||
// Make sure there's an upload to process.
|
||||
if (empty($_FILES['files']['name'][$source])) {
|
||||
if (empty($_FILES['files']['name'][$form_field_name])) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check for file upload errors and return FALSE if a lower level system
|
||||
// error occurred. For a complete list of errors:
|
||||
// See http://php.net/manual/en/features.file-upload.errors.php.
|
||||
switch ($_FILES['files']['error'][$source]) {
|
||||
// See http://php.net/manual/features.file-upload.errors.php.
|
||||
switch ($_FILES['files']['error'][$form_field_name]) {
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
drupal_set_message(t('The file %file could not be saved, because it exceeds %maxsize, the maximum allowed size for uploads.', array('%file' => $_FILES['files']['name'][$source], '%maxsize' => format_size(file_upload_max_size()))), 'error');
|
||||
drupal_set_message(t('The file %file could not be saved, because it exceeds %maxsize, the maximum allowed size for uploads.', array('%file' => $_FILES['files']['name'][$form_field_name], '%maxsize' => format_size(file_upload_max_size()))), 'error');
|
||||
return FALSE;
|
||||
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
drupal_set_message(t('The file %file could not be saved, because the upload did not complete.', array('%file' => $_FILES['files']['name'][$source])), 'error');
|
||||
drupal_set_message(t('The file %file could not be saved, because the upload did not complete.', array('%file' => $_FILES['files']['name'][$form_field_name])), 'error');
|
||||
return FALSE;
|
||||
|
||||
case UPLOAD_ERR_OK:
|
||||
// Final check that this is a valid upload, if it isn't, use the
|
||||
// default error handler.
|
||||
if (is_uploaded_file($_FILES['files']['tmp_name'][$source])) {
|
||||
if (is_uploaded_file($_FILES['files']['tmp_name'][$form_field_name])) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Unknown error
|
||||
default:
|
||||
drupal_set_message(t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $_FILES['files']['name'][$source])), 'error');
|
||||
drupal_set_message(t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $_FILES['files']['name'][$form_field_name])), 'error');
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1448,10 +1486,10 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
|
||||
$file = new stdClass();
|
||||
$file->uid = $user->uid;
|
||||
$file->status = 0;
|
||||
$file->filename = trim(drupal_basename($_FILES['files']['name'][$source]), '.');
|
||||
$file->uri = $_FILES['files']['tmp_name'][$source];
|
||||
$file->filename = trim(drupal_basename($_FILES['files']['name'][$form_field_name]), '.');
|
||||
$file->uri = $_FILES['files']['tmp_name'][$form_field_name];
|
||||
$file->filemime = file_get_mimetype($file->filename);
|
||||
$file->filesize = $_FILES['files']['size'][$source];
|
||||
$file->filesize = $_FILES['files']['size'][$form_field_name];
|
||||
|
||||
$extensions = '';
|
||||
if (isset($validators['file_validate_extensions'])) {
|
||||
@@ -1508,7 +1546,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$file->source = $source;
|
||||
$file->source = $form_field_name;
|
||||
// A URI may already have a trailing slash or look like "public://".
|
||||
if (substr($destination, -1) != '/') {
|
||||
$destination .= '/';
|
||||
@@ -1517,7 +1555,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
|
||||
// If file_destination() returns FALSE then $replace == FILE_EXISTS_ERROR and
|
||||
// there's an existing file so we need to bail.
|
||||
if ($file->destination === FALSE) {
|
||||
drupal_set_message(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', array('%source' => $source, '%directory' => $destination)), 'error');
|
||||
drupal_set_message(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', array('%source' => $form_field_name, '%directory' => $destination)), 'error');
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1536,7 +1574,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
|
||||
else {
|
||||
$message .= ' ' . array_pop($errors);
|
||||
}
|
||||
form_set_error($source, $message);
|
||||
form_set_error($form_field_name, $message);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1544,8 +1582,8 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
|
||||
// directory. This overcomes open_basedir restrictions for future file
|
||||
// operations.
|
||||
$file->uri = $file->destination;
|
||||
if (!drupal_move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->uri)) {
|
||||
form_set_error($source, t('File upload error. Could not move uploaded file.'));
|
||||
if (!drupal_move_uploaded_file($_FILES['files']['tmp_name'][$form_field_name], $file->uri)) {
|
||||
form_set_error($form_field_name, t('File upload error. Could not move uploaded file.'));
|
||||
watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->uri));
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1565,7 +1603,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
|
||||
// If we made it this far it's safe to record this file in the database.
|
||||
if ($file = file_save($file)) {
|
||||
// Add file to the cache.
|
||||
$upload_cache[$source] = $file;
|
||||
$upload_cache[$form_field_name] = $file;
|
||||
return $file;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -2182,7 +2220,7 @@ function drupal_chmod($uri, $mode = NULL) {
|
||||
* @param $uri
|
||||
* A URI or pathname.
|
||||
* @param $context
|
||||
* Refer to http://php.net/manual/en/ref.stream.php
|
||||
* Refer to http://php.net/manual/ref.stream.php
|
||||
*
|
||||
* @return
|
||||
* Boolean TRUE on success, or FALSE on failure.
|
||||
@@ -2204,29 +2242,21 @@ function drupal_unlink($uri, $context = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute local filesystem path of a stream URI.
|
||||
* Resolves the absolute filepath of a local URI or filepath.
|
||||
*
|
||||
* This function was originally written to ease the conversion of 6.x code to
|
||||
* use 7.x stream wrappers. However, it assumes that every URI may be resolved
|
||||
* to an absolute local filesystem path, and this assumption fails when stream
|
||||
* wrappers are used to support remote file storage. Remote stream wrappers
|
||||
* may implement the realpath method by always returning FALSE. The use of
|
||||
* drupal_realpath() is discouraged, and is slowly being removed from core
|
||||
* functions where possible.
|
||||
* The use of drupal_realpath() is discouraged, because it does not work for
|
||||
* remote URIs. Except in rare cases, URIs should not be manually resolved.
|
||||
*
|
||||
* Only use this function if you know that the stream wrapper in the URI uses
|
||||
* the local file system, and you need to pass an absolute path to a function
|
||||
* that is incompatible with stream URIs.
|
||||
*
|
||||
* @param $uri
|
||||
* A stream wrapper URI or a filesystem path, possibly including one or more
|
||||
* symbolic links.
|
||||
* @param string $uri
|
||||
* A stream wrapper URI or a filepath, possibly including one or more symbolic
|
||||
* links.
|
||||
*
|
||||
* @return
|
||||
* The absolute local filesystem path (with no symbolic links), or FALSE on
|
||||
* failure.
|
||||
*
|
||||
* @todo This function is deprecated, and should be removed wherever possible.
|
||||
* @return string|false
|
||||
* The absolute local filepath (with no symbolic links), or FALSE on failure.
|
||||
*
|
||||
* @see DrupalStreamWrapperInterface::realpath()
|
||||
* @see http://php.net/manual/function.realpath.php
|
||||
@@ -2323,7 +2353,7 @@ function drupal_basename($uri, $suffix = NULL) {
|
||||
* @param $recursive
|
||||
* Default to FALSE.
|
||||
* @param $context
|
||||
* Refer to http://php.net/manual/en/ref.stream.php
|
||||
* Refer to http://php.net/manual/ref.stream.php
|
||||
*
|
||||
* @return
|
||||
* Boolean TRUE on success, or FALSE on failure.
|
||||
@@ -2354,7 +2384,7 @@ function drupal_mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) {
|
||||
* @param $uri
|
||||
* A URI or pathname.
|
||||
* @param $context
|
||||
* Refer to http://php.net/manual/en/ref.stream.php
|
||||
* Refer to http://php.net/manual/ref.stream.php
|
||||
*
|
||||
* @return
|
||||
* Boolean TRUE on success, or FALSE on failure.
|
||||
@@ -2481,20 +2511,10 @@ function file_directory_temp() {
|
||||
function file_get_content_headers($file) {
|
||||
$name = mime_header_encode($file->filename);
|
||||
$type = mime_header_encode($file->filemime);
|
||||
// Serve images, text, and flash content for display rather than download.
|
||||
$inline_types = variable_get('file_inline_types', array('^text/', '^image/', 'flash$'));
|
||||
$disposition = 'attachment';
|
||||
foreach ($inline_types as $inline_type) {
|
||||
// Exclamation marks are used as delimiters to avoid escaping slashes.
|
||||
if (preg_match('!' . $inline_type . '!', $file->filemime)) {
|
||||
$disposition = 'inline';
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'Content-Type' => $type,
|
||||
'Content-Length' => $file->filesize,
|
||||
'Content-Disposition' => $disposition . '; filename="' . $name . '"',
|
||||
'Cache-Control' => 'private',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -406,10 +406,20 @@ class SkipDotsRecursiveDirectoryIterator extends RecursiveDirectoryIterator {
|
||||
*/
|
||||
function __construct($path) {
|
||||
parent::__construct($path);
|
||||
$this->skipdots();
|
||||
}
|
||||
|
||||
function rewind() {
|
||||
parent::rewind();
|
||||
$this->skipdots();
|
||||
}
|
||||
|
||||
function next() {
|
||||
parent::next();
|
||||
$this->skipdots();
|
||||
}
|
||||
|
||||
protected function skipdots() {
|
||||
while ($this->isDot()) {
|
||||
parent::next();
|
||||
}
|
||||
|
||||
@@ -82,11 +82,11 @@ class FileTransferFTPExtension extends FileTransferFTP implements FileTransferCh
|
||||
if (!$list) {
|
||||
$list = array();
|
||||
}
|
||||
foreach ($list as $item){
|
||||
foreach ($list as $item) {
|
||||
if ($item == '.' || $item == '..') {
|
||||
continue;
|
||||
}
|
||||
if (@ftp_chdir($this->connection, $item)){
|
||||
if (@ftp_chdir($this->connection, $item)) {
|
||||
ftp_cdup($this->connection);
|
||||
$this->removeDirectory(ftp_pwd($this->connection) . '/' . $item);
|
||||
}
|
||||
@@ -122,7 +122,7 @@ class FileTransferFTPExtension extends FileTransferFTP implements FileTransferCh
|
||||
|
||||
function chmodJailed($path, $mode, $recursive) {
|
||||
if (!ftp_chmod($this->connection, $mode, $path)) {
|
||||
throw new FileTransferException("Unable to set permissions on %file", NULL, array ('%file' => $path));
|
||||
throw new FileTransferException("Unable to set permissions on %file", NULL, array('%file' => $path));
|
||||
}
|
||||
if ($this->isDirectory($path) && $recursive) {
|
||||
$filelist = @ftp_nlist($this->connection, $path);
|
||||
|
||||
@@ -15,10 +15,9 @@
|
||||
* reference the form builder function using \@see. For examples, of this see
|
||||
* system_modules_uninstall() or user_pass(), the latter of which has the
|
||||
* following in its doxygen documentation:
|
||||
*
|
||||
* \@ingroup forms
|
||||
* \@see user_pass_validate().
|
||||
* \@see user_pass_submit().
|
||||
* - \@ingroup forms
|
||||
* - \@see user_pass_validate()
|
||||
* - \@see user_pass_submit()
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -168,6 +167,12 @@ function drupal_get_form($form_id) {
|
||||
* processed.
|
||||
* - base_form_id: Identification for a base form, as declared in a
|
||||
* hook_forms() implementation.
|
||||
* - immutable: If this flag is set to TRUE, a new form build id is
|
||||
* generated when the form is loaded from the cache. If it is subsequently
|
||||
* saved to the cache again, it will have another cache id and therefore
|
||||
* the original form and form-state will remain unaltered. This is
|
||||
* important when page caching is enabled in order to prevent form state
|
||||
* from leaking between anonymous users.
|
||||
* - rebuild_info: Internal. Similar to 'build_info', but pertaining to
|
||||
* drupal_rebuild_form().
|
||||
* - rebuild: Normally, after the entire form processing is completed and
|
||||
@@ -235,6 +240,12 @@ function drupal_get_form($form_id) {
|
||||
* likely to occur during Ajax operations.
|
||||
* - programmed: If TRUE, the form was submitted programmatically, usually
|
||||
* invoked via drupal_form_submit(). Defaults to FALSE.
|
||||
* - programmed_bypass_access_check: If TRUE, programmatic form submissions
|
||||
* are processed without taking #access into account. Set this to FALSE
|
||||
* when submitting a form programmatically with values that may have been
|
||||
* input by the user executing the current request; this will cause #access
|
||||
* to be respected as it would on a normal form submission. Defaults to
|
||||
* TRUE.
|
||||
* - process_input: Boolean flag. TRUE signifies correct form submission.
|
||||
* This is always TRUE for programmed forms coming from drupal_form_submit()
|
||||
* (see 'programmed' key), or if the form_id coming from the $_POST data is
|
||||
@@ -402,6 +413,7 @@ function form_state_defaults() {
|
||||
'submitted' => FALSE,
|
||||
'executed' => FALSE,
|
||||
'programmed' => FALSE,
|
||||
'programmed_bypass_access_check' => TRUE,
|
||||
'cache'=> FALSE,
|
||||
'method' => 'post',
|
||||
'groups' => array(),
|
||||
@@ -452,17 +464,25 @@ function drupal_rebuild_form($form_id, &$form_state, $old_form = NULL) {
|
||||
$form = drupal_retrieve_form($form_id, $form_state);
|
||||
|
||||
// If only parts of the form will be returned to the browser (e.g., Ajax or
|
||||
// RIA clients), re-use the old #build_id to not require client-side code to
|
||||
// manually update the hidden 'build_id' input element.
|
||||
// RIA clients), or if the form already had a new build ID regenerated when it
|
||||
// was retrieved from the form cache, reuse the existing #build_id.
|
||||
// Otherwise, a new #build_id is generated, to not clobber the previous
|
||||
// build's data in the form cache; also allowing the user to go back to an
|
||||
// earlier build, make changes, and re-submit.
|
||||
// @see drupal_prepare_form()
|
||||
if (isset($old_form['#build_id']) && !empty($form_state['rebuild_info']['copy']['#build_id'])) {
|
||||
$enforce_old_build_id = isset($old_form['#build_id']) && !empty($form_state['rebuild_info']['copy']['#build_id']);
|
||||
$old_form_is_mutable_copy = isset($old_form['#build_id_old']);
|
||||
if ($enforce_old_build_id || $old_form_is_mutable_copy) {
|
||||
$form['#build_id'] = $old_form['#build_id'];
|
||||
if ($old_form_is_mutable_copy) {
|
||||
$form['#build_id_old'] = $old_form['#build_id_old'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$form['#build_id'] = 'form-' . drupal_hash_base64(uniqid(mt_rand(), TRUE) . mt_rand());
|
||||
if (isset($old_form['#build_id'])) {
|
||||
$form['#build_id_old'] = $old_form['#build_id'];
|
||||
}
|
||||
$form['#build_id'] = 'form-' . drupal_random_key();
|
||||
}
|
||||
|
||||
// #action defaults to request_uri(), but in case of Ajax and other partial
|
||||
@@ -516,6 +536,15 @@ function form_get_cache($form_build_id, &$form_state) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Generate a new #build_id if the cached form was rendered on a cacheable
|
||||
// page.
|
||||
if (!empty($form_state['build_info']['immutable'])) {
|
||||
$form['#build_id_old'] = $form['#build_id'];
|
||||
$form['#build_id'] = 'form-' . drupal_random_key();
|
||||
$form['form_build_id']['#value'] = $form['#build_id'];
|
||||
$form['form_build_id']['#id'] = $form['#build_id'];
|
||||
unset($form_state['build_info']['immutable']);
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
@@ -528,15 +557,28 @@ function form_set_cache($form_build_id, $form, $form_state) {
|
||||
// 6 hours cache life time for forms should be plenty.
|
||||
$expire = 21600;
|
||||
|
||||
// Ensure that the form build_id embedded in the form structure is the same as
|
||||
// the one passed in as a parameter. This is an additional safety measure to
|
||||
// prevent legacy code operating directly with form_get_cache and
|
||||
// form_set_cache from accidentally overwriting immutable form state.
|
||||
if ($form['#build_id'] != $form_build_id) {
|
||||
watchdog('form', 'Form build-id mismatch detected while attempting to store a form in the cache.', array(), WATCHDOG_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache form structure.
|
||||
if (isset($form)) {
|
||||
if ($GLOBALS['user']->uid) {
|
||||
$form['#cache_token'] = drupal_get_token();
|
||||
}
|
||||
unset($form['#build_id_old']);
|
||||
cache_set('form_' . $form_build_id, $form, 'cache_form', REQUEST_TIME + $expire);
|
||||
}
|
||||
|
||||
// Cache form state.
|
||||
if (variable_get('cache', 0) && drupal_page_is_cacheable()) {
|
||||
$form_state['build_info']['immutable'] = TRUE;
|
||||
}
|
||||
if ($data = array_diff_key($form_state, array_flip(form_state_keys_no_cache()))) {
|
||||
cache_set('form_state_' . $form_build_id, $data, 'cache_form', REQUEST_TIME + $expire);
|
||||
}
|
||||
@@ -727,8 +769,9 @@ function drupal_retrieve_form($form_id, &$form_state) {
|
||||
// Record the filepath of the include file containing the original form, so
|
||||
// the form builder callbacks can be loaded when the form is being rebuilt
|
||||
// from cache on a different path (such as 'system/ajax'). See
|
||||
// form_get_cache().
|
||||
// $menu_get_item() is not available during installation.
|
||||
// form_get_cache(). Don't do this in maintenance mode as Drupal may not be
|
||||
// fully bootstrapped (i.e. during installation) in which case
|
||||
// menu_get_item() is not available.
|
||||
if (!isset($form_state['build_info']['files']['menu']) && !defined('MAINTENANCE_MODE')) {
|
||||
$item = menu_get_item();
|
||||
if (!empty($item['include_file'])) {
|
||||
@@ -976,7 +1019,7 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
|
||||
// @see drupal_build_form()
|
||||
// @see drupal_rebuild_form()
|
||||
if (!isset($form['#build_id'])) {
|
||||
$form['#build_id'] = 'form-' . drupal_hash_base64(uniqid(mt_rand(), TRUE) . mt_rand());
|
||||
$form['#build_id'] = 'form-' . drupal_random_key();
|
||||
}
|
||||
$form['form_build_id'] = array(
|
||||
'#type' => 'hidden',
|
||||
@@ -1128,6 +1171,12 @@ function drupal_validate_form($form_id, &$form, &$form_state) {
|
||||
|
||||
// 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)));
|
||||
|
||||
// Stop here and don't run any further validation handlers, because they
|
||||
// could invoke non-safe operations which opens the door for CSRF
|
||||
// vulnerabilities.
|
||||
$validated_forms[$form_id] = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1978,7 +2027,7 @@ function _form_builder_handle_input_element($form_id, &$element, &$form_state) {
|
||||
// #access=FALSE on an element usually allow access for some users, so forms
|
||||
// submitted with drupal_form_submit() may bypass access restriction and be
|
||||
// treated as high-privilege users instead.
|
||||
$process_input = empty($element['#disabled']) && ($form_state['programmed'] || ($form_state['process_input'] && (!isset($element['#access']) || $element['#access'])));
|
||||
$process_input = empty($element['#disabled']) && (($form_state['programmed'] && $form_state['programmed_bypass_access_check']) || ($form_state['process_input'] && (!isset($element['#access']) || $element['#access'])));
|
||||
|
||||
// Set the element's #value property.
|
||||
if (!isset($element['#value']) && !array_key_exists('#value', $element)) {
|
||||
@@ -3051,14 +3100,12 @@ function form_process_radios($element) {
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
* - element: An associative array containing the properties of the element.
|
||||
* Properties used: #title, #value, #return_value, #description, #required,
|
||||
* #attributes, #checked.
|
||||
* Properties used: #id, #name, #attributes, #checked, #return_value.
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_checkbox($variables) {
|
||||
$element = $variables['element'];
|
||||
$t = get_t();
|
||||
$element['#attributes']['type'] = 'checkbox';
|
||||
element_set_attributes($element, array('id', 'name', '#return_value' => 'value'));
|
||||
|
||||
@@ -3662,35 +3709,6 @@ function form_pre_render_fieldset($element) {
|
||||
/**
|
||||
* Creates a group formatted as vertical tabs.
|
||||
*
|
||||
* Note that autocomplete callbacks should include special handling as the
|
||||
* user's input may contain forward slashes. If the user-submitted string has a
|
||||
* '/' in the text that is sent in the autocomplete request, the menu system
|
||||
* will split the text and pass it to the callback as multiple arguments.
|
||||
*
|
||||
* Suppose your autocomplete path in the menu system is 'mymodule_autocomplete.'
|
||||
* In your form you have:
|
||||
* @code
|
||||
* '#autocomplete_path' => 'mymodule_autocomplete/' . $some_key . '/' . $some_id,
|
||||
* @endcode
|
||||
* The user types in "keywords" so the full path called is:
|
||||
* 'mymodule_autocomplete/$some_key/$some_id/keywords'
|
||||
*
|
||||
* You should include code similar to the following to handle slashes in the
|
||||
* input:
|
||||
* @code
|
||||
* function mymodule_autocomplete_callback($arg1, $arg2, $keywords) {
|
||||
* $args = func_get_args();
|
||||
* // We need to remove $arg1 and $arg2 from the beginning of the array so we
|
||||
* // are left with the keywords.
|
||||
* array_shift($args);
|
||||
* array_shift($args);
|
||||
* // We store the user's original input in $keywords, including any slashes.
|
||||
* $keywords = implode('/', $args);
|
||||
*
|
||||
* // Your code here.
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param $element
|
||||
* An associative array containing the properties and children of the
|
||||
* fieldset.
|
||||
@@ -4039,8 +4057,6 @@ function theme_file($variables) {
|
||||
*/
|
||||
function theme_form_element($variables) {
|
||||
$element = &$variables['element'];
|
||||
// This is also used in the installer, pre-database setup.
|
||||
$t = get_t();
|
||||
|
||||
// This function is invoked as theme wrapper, but the rendered form element
|
||||
// may not necessarily have been processed by form_builder().
|
||||
@@ -4199,7 +4215,7 @@ function _form_set_class(&$element, $class = array()) {
|
||||
if (!empty($element['#required'])) {
|
||||
$element['#attributes']['class'][] = 'required';
|
||||
}
|
||||
if (isset($element['#parents']) && form_get_error($element) !== NULL) {
|
||||
if (isset($element['#parents']) && form_get_error($element) !== NULL && !empty($element['#validated'])) {
|
||||
$element['#attributes']['class'][] = 'error';
|
||||
}
|
||||
}
|
||||
@@ -4276,7 +4292,7 @@ function element_validate_number($element, &$form_state) {
|
||||
* returns any user input in the 'results' or 'message' keys of $context,
|
||||
* it must also sanitize them first.
|
||||
*
|
||||
* Sample batch operations:
|
||||
* Sample callback_batch_operation():
|
||||
* @code
|
||||
* // Simple and artificial: load a node of a given type for a given user
|
||||
* function my_function_1($uid, $type, &$context) {
|
||||
@@ -4328,7 +4344,7 @@ function element_validate_number($element, &$form_state) {
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Sample 'finished' callback:
|
||||
* Sample callback_batch_finished():
|
||||
* @code
|
||||
* function batch_test_finished($success, $results, $operations) {
|
||||
* // The 'success' parameter means no fatal PHP errors were detected. All
|
||||
@@ -4367,12 +4383,14 @@ function element_validate_number($element, &$form_state) {
|
||||
* @param $batch_definition
|
||||
* An associative array defining the batch, with the following elements (all
|
||||
* are optional except as noted):
|
||||
* - operations: (required) Array of function calls to be performed.
|
||||
* - operations: (required) Array of operations to be performed, where each
|
||||
* item is an array consisting of the name of an implementation of
|
||||
* callback_batch_operation() and an array of parameter.
|
||||
* Example:
|
||||
* @code
|
||||
* array(
|
||||
* array('my_function_1', array($arg1)),
|
||||
* array('my_function_2', array($arg2_1, $arg2_2)),
|
||||
* array('callback_batch_operation_1', array($arg1)),
|
||||
* array('callback_batch_operation_2', array($arg2_1, $arg2_2)),
|
||||
* )
|
||||
* @endcode
|
||||
* - title: A safe, translated string to use as the title for the progress
|
||||
@@ -4384,10 +4402,10 @@ function element_validate_number($element, &$form_state) {
|
||||
* @elapsed. Defaults to t('Completed @current of @total.').
|
||||
* - error_message: Message displayed if an error occurred while processing
|
||||
* the batch. Defaults to t('An error has occurred.').
|
||||
* - finished: Name of a function to be executed after the batch has
|
||||
* completed. This should be used to perform any result massaging that may
|
||||
* be needed, and possibly save data in $_SESSION for display after final
|
||||
* page redirection.
|
||||
* - finished: Name of an implementation of callback_batch_finished(). This is
|
||||
* executed after the batch has completed. This should be used to perform
|
||||
* any result massaging that may be needed, and possibly save data in
|
||||
* $_SESSION for display after final page redirection.
|
||||
* - file: Path to the file containing the definitions of the 'operations' and
|
||||
* 'finished' functions, for instance if they don't reside in the main
|
||||
* .module file. The path should be relative to base_path(), and thus should
|
||||
|
||||
@@ -233,11 +233,11 @@ function image_dimensions_scale(array &$dimensions, $width = NULL, $height = NUL
|
||||
* @param $image
|
||||
* An image object returned by image_load().
|
||||
* @param $width
|
||||
* The target width, in pixels. This value is omitted then the scaling will
|
||||
* based only on the height value.
|
||||
* The target width, in pixels. If this value is NULL then the scaling will
|
||||
* be based only on the height value.
|
||||
* @param $height
|
||||
* The target height, in pixels. This value is omitted then the scaling will
|
||||
* based only on the width value.
|
||||
* The target height, in pixels. If this value is NULL then the scaling will
|
||||
* be based only on the width value.
|
||||
* @param $upscale
|
||||
* Boolean indicating that files smaller than the dimensions will be scaled
|
||||
* up. This generally results in a low quality image.
|
||||
|
||||
@@ -692,6 +692,21 @@ function install_full_redirect_url($install_state) {
|
||||
*/
|
||||
function install_display_output($output, $install_state) {
|
||||
drupal_page_header();
|
||||
|
||||
// Prevent install.php from being indexed when installed in a sub folder.
|
||||
// robots.txt rules are not read if the site is within domain.com/subfolder
|
||||
// resulting in /subfolder/install.php being found through search engines.
|
||||
// When settings.php is writeable this can be used via an external database
|
||||
// leading a malicious user to gain php access to the server.
|
||||
$noindex_meta_tag = array(
|
||||
'#tag' => 'meta',
|
||||
'#attributes' => array(
|
||||
'name' => 'robots',
|
||||
'content' => 'noindex, nofollow',
|
||||
),
|
||||
);
|
||||
drupal_add_html_head($noindex_meta_tag, 'install_meta_robots');
|
||||
|
||||
// Only show the task list if there is an active task; otherwise, the page
|
||||
// request has ended before tasks have even been started, so there is nothing
|
||||
// meaningful to show.
|
||||
@@ -766,6 +781,15 @@ function install_system_module(&$install_state) {
|
||||
// Install system.module.
|
||||
drupal_install_system();
|
||||
|
||||
// Call file_ensure_htaccess() to ensure that all of Drupal's standard
|
||||
// directories (e.g., the public and private files directories) have
|
||||
// appropriate .htaccess files. These directories will have already been
|
||||
// created by this point in the installer, since Drupal creates them during
|
||||
// the install_verify_requirements() task. Note that we cannot call
|
||||
// file_ensure_htaccess() any earlier than this, since it relies on
|
||||
// system.module in order to work.
|
||||
file_ensure_htaccess();
|
||||
|
||||
// Enable the user module so that sessions can be recorded during the
|
||||
// upcoming bootstrap step.
|
||||
module_enable(array('user'), FALSE);
|
||||
@@ -981,7 +1005,7 @@ function install_settings_form_submit($form, &$form_state) {
|
||||
'required' => TRUE,
|
||||
);
|
||||
$settings['drupal_hash_salt'] = array(
|
||||
'value' => drupal_hash_base64(drupal_random_bytes(55)),
|
||||
'value' => drupal_random_key(),
|
||||
'required' => TRUE,
|
||||
);
|
||||
drupal_rewrite_settings($settings);
|
||||
@@ -1041,7 +1065,21 @@ function install_select_profile(&$install_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects an installation profile from a list or from a $_POST submission.
|
||||
* Selects an installation profile.
|
||||
*
|
||||
* A profile will be selected if:
|
||||
* - Only one profile is available,
|
||||
* - A profile was submitted through $_POST,
|
||||
* - Exactly one of the profiles is marked as "exclusive".
|
||||
* If multiple profiles are marked as "exclusive" then no profile will be
|
||||
* selected.
|
||||
*
|
||||
* @param array $profiles
|
||||
* An associative array of profiles with the machine-readable names as keys.
|
||||
*
|
||||
* @return
|
||||
* The machine-readable name of the selected profile or NULL if no profile was
|
||||
* selected.
|
||||
*/
|
||||
function _install_select_profile($profiles) {
|
||||
if (sizeof($profiles) == 0) {
|
||||
@@ -1061,6 +1099,23 @@ function _install_select_profile($profiles) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for a profile marked as "exclusive" and ensure that only one
|
||||
// profile is marked as such.
|
||||
$exclusive_profile = NULL;
|
||||
foreach ($profiles as $profile) {
|
||||
$profile_info = install_profile_info($profile->name);
|
||||
if (!empty($profile_info['exclusive'])) {
|
||||
if (empty($exclusive_profile)) {
|
||||
$exclusive_profile = $profile->name;
|
||||
}
|
||||
else {
|
||||
// We found a second "exclusive" profile. There's no way to choose
|
||||
// between them, so we ignore the property.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $exclusive_profile;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -741,20 +741,27 @@ function drupal_install_system() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls a given list of modules.
|
||||
* Uninstalls a given list of disabled modules.
|
||||
*
|
||||
* @param $module_list
|
||||
* The modules to uninstall.
|
||||
* @param $uninstall_dependents
|
||||
* If TRUE, the function will check that all modules which depend on the
|
||||
* passed-in module list either are already uninstalled or contained in the
|
||||
* list, and it will ensure that the modules are uninstalled 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.
|
||||
* @param array $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.
|
||||
* @param bool $uninstall_dependents
|
||||
* (optional) If TRUE, the function will check that all modules which depend
|
||||
* on the passed-in module list either are already uninstalled or contained in
|
||||
* the list, and it will ensure that the modules are uninstalled 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.
|
||||
* Defaults to TRUE.
|
||||
*
|
||||
* @return
|
||||
* FALSE if one or more dependent modules are missing from the list, TRUE
|
||||
* otherwise.
|
||||
* @return bool
|
||||
* Returns TRUE if the operation succeeds or FALSE if it aborts due to an
|
||||
* unsafe condition, namely, $uninstall_dependents is TRUE and a module in
|
||||
* $module_list has dependents which are not already uninstalled and not also
|
||||
* included in $module_list).
|
||||
*
|
||||
* @see module_disable()
|
||||
*/
|
||||
function drupal_uninstall_modules($module_list = array(), $uninstall_dependents = TRUE) {
|
||||
if ($uninstall_dependents) {
|
||||
@@ -766,7 +773,7 @@ function drupal_uninstall_modules($module_list = array(), $uninstall_dependents
|
||||
$profile = drupal_get_profile();
|
||||
while (list($module) = each($module_list)) {
|
||||
if (!isset($module_data[$module]) || drupal_get_installed_schema_version($module) == SCHEMA_UNINSTALLED) {
|
||||
// This module doesn't exist or is already uninstalled, skip it.
|
||||
// This module doesn't exist or is already uninstalled. Skip it.
|
||||
unset($module_list[$module]);
|
||||
continue;
|
||||
}
|
||||
@@ -799,7 +806,7 @@ function drupal_uninstall_modules($module_list = array(), $uninstall_dependents
|
||||
}
|
||||
|
||||
if (!empty($module_list)) {
|
||||
// Call hook_module_uninstall to let other modules act
|
||||
// Let other modules react.
|
||||
module_invoke_all('modules_uninstalled', $module_list);
|
||||
}
|
||||
|
||||
@@ -1127,7 +1134,6 @@ function st($string, array $args = array(), array $options = array()) {
|
||||
}
|
||||
}
|
||||
|
||||
require_once DRUPAL_ROOT . '/includes/theme.inc';
|
||||
// Transform arguments before inserting them
|
||||
foreach ($args as $key => $value) {
|
||||
switch ($key[0]) {
|
||||
@@ -1244,6 +1250,12 @@ function drupal_check_module($module) {
|
||||
* - distribution_name: The name of the Drupal distribution that is being
|
||||
* installed, to be shown throughout the installation process. Defaults to
|
||||
* 'Drupal'.
|
||||
* - exclusive: If the install profile is intended to be the only eligible
|
||||
* choice in a distribution, setting exclusive = TRUE will auto-select it
|
||||
* during installation, and the install profile selection screen will be
|
||||
* skipped. If more than one profile is found where exclusive = TRUE then
|
||||
* this property will have no effect and the profile selection screen will
|
||||
* be shown as normal with all available profiles shown.
|
||||
*
|
||||
* Note that this function does an expensive file system scan to get info file
|
||||
* information for dependencies. If you only need information from the info
|
||||
|
||||
@@ -53,6 +53,7 @@ function _country_get_predefined_list() {
|
||||
'BM' => $t('Bermuda'),
|
||||
'BN' => $t('Brunei'),
|
||||
'BO' => $t('Bolivia'),
|
||||
'BQ' => $t('Caribbean Netherlands'),
|
||||
'BR' => $t('Brazil'),
|
||||
'BS' => $t('Bahamas'),
|
||||
'BT' => $t('Bhutan'),
|
||||
@@ -74,8 +75,8 @@ function _country_get_predefined_list() {
|
||||
'CO' => $t('Colombia'),
|
||||
'CR' => $t('Costa Rica'),
|
||||
'CU' => $t('Cuba'),
|
||||
'CW' => $t('Curaçao'),
|
||||
'CV' => $t('Cape Verde'),
|
||||
'CW' => $t('Curaçao'),
|
||||
'CX' => $t('Christmas Island'),
|
||||
'CY' => $t('Cyprus'),
|
||||
'CZ' => $t('Czech Republic'),
|
||||
@@ -230,8 +231,10 @@ function _country_get_predefined_list() {
|
||||
'SN' => $t('Senegal'),
|
||||
'SO' => $t('Somalia'),
|
||||
'SR' => $t('Suriname'),
|
||||
'SS' => $t('South Sudan'),
|
||||
'ST' => $t('Sao Tome and Principe'),
|
||||
'SV' => $t('El Salvador'),
|
||||
'SX' => $t('Sint Maarten'),
|
||||
'SY' => $t('Syria'),
|
||||
'SZ' => $t('Swaziland'),
|
||||
'TC' => $t('Turks and Caicos Islands'),
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Multiple language handling functionality.
|
||||
* Language Negotiation API.
|
||||
*
|
||||
* @see http://drupal.org/node/1497272
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -11,7 +13,95 @@
|
||||
define('LANGUAGE_NEGOTIATION_DEFAULT', 'language-default');
|
||||
|
||||
/**
|
||||
* Return all the defined language types.
|
||||
* @defgroup language_negotiation Language Negotiation API functionality
|
||||
* @{
|
||||
* Functions to customize the language types and the negotiation process.
|
||||
*
|
||||
* The language negotiation API is based on two major concepts:
|
||||
* - Language types: types of translatable data (the types of data that a user
|
||||
* can view or request).
|
||||
* - Language negotiation providers: functions for determining which language to
|
||||
* use to present a particular piece of data to the user.
|
||||
* Both language types and language negotiation providers are customizable.
|
||||
*
|
||||
* Drupal defines three built-in language types:
|
||||
* - Interface language: The page's main language, used to present translated
|
||||
* user interface elements such as titles, labels, help text, and messages.
|
||||
* - Content language: The language used to present content that is available
|
||||
* in more than one language (see
|
||||
* @link field_language Field Language API @endlink for details).
|
||||
* - URL language: The language associated with URLs. When generating a URL,
|
||||
* this value will be used by url() as a default if no explicit preference is
|
||||
* provided.
|
||||
* Modules can define additional language types through
|
||||
* hook_language_types_info(), and alter existing language type definitions
|
||||
* through hook_language_types_info_alter().
|
||||
*
|
||||
* Language types may be configurable or fixed. The language negotiation
|
||||
* providers associated with a configurable language type can be explicitly
|
||||
* set through the user interface. A fixed language type has predetermined
|
||||
* (module-defined) language negotiation settings and, thus, does not appear in
|
||||
* the configuration page. Here is a code snippet that makes the content
|
||||
* language (which by default inherits the interface language's values)
|
||||
* configurable:
|
||||
* @code
|
||||
* function mymodule_language_types_info_alter(&$language_types) {
|
||||
* unset($language_types[LANGUAGE_TYPE_CONTENT]['fixed']);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Every language type can have a different set of language negotiation
|
||||
* providers assigned to it. Different language types often share the same
|
||||
* language negotiation settings, but they can have independent settings if
|
||||
* needed. If two language types are configured the same way, their language
|
||||
* switcher configuration will be functionally identical and the same settings
|
||||
* will act on both language types.
|
||||
*
|
||||
* Drupal defines the following built-in language negotiation providers:
|
||||
* - URL: Determine the language from the URL (path prefix or domain).
|
||||
* - Session: Determine the language from a request/session parameter.
|
||||
* - User: Follow the user's language preference.
|
||||
* - Browser: Determine the language from the browser's language settings.
|
||||
* - Default language: Use the default site language.
|
||||
* Language negotiation providers are simple callback functions that implement a
|
||||
* particular logic to return a language code. For instance, the URL provider
|
||||
* searches for a valid path prefix or domain name in the current request URL.
|
||||
* If a language negotiation provider does not return a valid language code, the
|
||||
* next provider associated to the language type (based on provider weight) is
|
||||
* invoked.
|
||||
*
|
||||
* Modules can define additional language negotiation providers through
|
||||
* hook_language_negotiation_info(), and alter existing providers through
|
||||
* hook_language_negotiation_info_alter(). Here is an example snippet that lets
|
||||
* path prefixes be ignored for administrative paths:
|
||||
* @code
|
||||
* function mymodule_language_negotiation_info_alter(&$negotiation_info) {
|
||||
* // Replace the core function with our own function.
|
||||
* module_load_include('language', 'inc', 'language.negotiation');
|
||||
* $negotiation_info[LANGUAGE_NEGOTIATION_URL]['callbacks']['language'] = 'mymodule_from_url';
|
||||
* $negotiation_info[LANGUAGE_NEGOTIATION_URL]['file'] = drupal_get_path('module', 'mymodule') . '/mymodule.module';
|
||||
* }
|
||||
*
|
||||
* function mymodule_from_url($languages) {
|
||||
* // Use the core URL language negotiation provider to get a valid language
|
||||
* // code.
|
||||
* module_load_include('language', 'inc', 'language.negotiation');
|
||||
* $langcode = language_from_url($languages);
|
||||
*
|
||||
* // If we are on an administrative path, override with the default language.
|
||||
* if (isset($_GET['q']) && strtok($_GET['q'], '/') == 'admin') {
|
||||
* return language_default()->langcode;
|
||||
* }
|
||||
* return $langcode;
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* For more information, see
|
||||
* @link http://drupal.org/node/1497272 Language Negotiation API @endlink
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns all the defined language types.
|
||||
*
|
||||
* @return
|
||||
* An array of language type names. The name will be used as the global
|
||||
@@ -30,11 +120,11 @@ function language_types_info() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return only the configurable language types.
|
||||
* Returns only the configurable language types.
|
||||
*
|
||||
* A language type maybe configurable or fixed. A fixed language type is a type
|
||||
* whose negotiation values are unchangeable and defined while defining the
|
||||
* language type itself.
|
||||
* whose language negotiation providers are module-defined and not altered
|
||||
* through the user interface.
|
||||
*
|
||||
* @param $stored
|
||||
* Optional. By default retrieves values from the 'language_types' variable to
|
||||
@@ -68,7 +158,7 @@ function language_types_configurable($stored = TRUE) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the given language types.
|
||||
* Disables the given language types.
|
||||
*
|
||||
* @param $types
|
||||
* An array of language types.
|
||||
@@ -122,16 +212,17 @@ function language_types_set() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a language provider is enabled.
|
||||
* Checks whether a language negotiation provider is enabled for a language type.
|
||||
*
|
||||
* This has two possible behaviors:
|
||||
* - If $provider_id is given return its ID if enabled, FALSE otherwise.
|
||||
* - If no ID is passed the first enabled language provider is returned.
|
||||
* - If no ID is passed the first enabled language negotiation provider is
|
||||
* returned.
|
||||
*
|
||||
* @param $type
|
||||
* The language negotiation type.
|
||||
* The language negotiation provider type.
|
||||
* @param $provider_id
|
||||
* The language provider ID.
|
||||
* The language negotiation provider ID.
|
||||
*
|
||||
* @return
|
||||
* The provider ID if it is enabled, FALSE otherwise.
|
||||
@@ -155,14 +246,13 @@ function language_negotiation_get($type, $provider_id = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given language provider is enabled for any configurable language
|
||||
* type.
|
||||
* Checks if the language negotiation provider is enabled for any language type.
|
||||
*
|
||||
* @param $provider_id
|
||||
* The language provider ID.
|
||||
* The language negotiation provider ID.
|
||||
*
|
||||
* @return
|
||||
* TRUE if there is at least one language type for which the give language
|
||||
* TRUE if there is at least one language type for which the given language
|
||||
* provider is enabled, FALSE otherwise.
|
||||
*/
|
||||
function language_negotiation_get_any($provider_id) {
|
||||
@@ -176,7 +266,7 @@ function language_negotiation_get_any($provider_id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the language switch links for the given language.
|
||||
* Returns the language switch links for the given language.
|
||||
*
|
||||
* @param $type
|
||||
* The language negotiation type.
|
||||
@@ -223,7 +313,7 @@ function language_negotiation_get_switch_links($type, $path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates language configuration to remove any language provider that is no longer defined.
|
||||
* Removes any unused language negotiation providers from the configuration.
|
||||
*/
|
||||
function language_negotiation_purge() {
|
||||
// Ensure that we are getting the defined language negotiation information. An
|
||||
@@ -246,12 +336,12 @@ function language_negotiation_purge() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a list of language providers.
|
||||
* Saves a list of language negotiation providers.
|
||||
*
|
||||
* @param $type
|
||||
* The language negotiation type.
|
||||
* @param $language_providers
|
||||
* An array of language provider weights keyed by id.
|
||||
* An array of language negotiation provider weights keyed by provider ID.
|
||||
* @see language_provider_weight()
|
||||
*/
|
||||
function language_negotiation_set($type, $language_providers) {
|
||||
@@ -277,7 +367,7 @@ function language_negotiation_set($type, $language_providers) {
|
||||
// If the provider does not express any preference about types, make it
|
||||
// available for any configurable type.
|
||||
$types = array_flip(isset($provider['types']) ? $provider['types'] : $default_types);
|
||||
// Check if the provider is defined and has the right type.
|
||||
// Check whether the provider is defined and has the right type.
|
||||
if (isset($types[$type])) {
|
||||
$provider_data = array();
|
||||
foreach ($provider_fields as $field) {
|
||||
@@ -294,10 +384,10 @@ function language_negotiation_set($type, $language_providers) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the defined language providers.
|
||||
* Returns all the defined language negotiation providers.
|
||||
*
|
||||
* @return
|
||||
* An array of language providers.
|
||||
* An array of language negotiation providers.
|
||||
*/
|
||||
function language_negotiation_info() {
|
||||
$language_providers = &drupal_static(__FUNCTION__);
|
||||
@@ -306,7 +396,7 @@ function language_negotiation_info() {
|
||||
// Collect all the module-defined language negotiation providers.
|
||||
$language_providers = module_invoke_all('language_negotiation_info');
|
||||
|
||||
// Add the default language provider.
|
||||
// Add the default language negotiation provider.
|
||||
$language_providers[LANGUAGE_NEGOTIATION_DEFAULT] = array(
|
||||
'callbacks' => array('language' => 'language_from_default'),
|
||||
'weight' => 10,
|
||||
@@ -314,7 +404,7 @@ function language_negotiation_info() {
|
||||
'description' => t('Use the default site language (@language_name).', array('@language_name' => language_default()->native)),
|
||||
);
|
||||
|
||||
// Let other modules alter the list of language providers.
|
||||
// Let other modules alter the list of language negotiation providers.
|
||||
drupal_alter('language_negotiation_info', $language_providers);
|
||||
}
|
||||
|
||||
@@ -322,16 +412,17 @@ function language_negotiation_info() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function used to cache the language providers results.
|
||||
* Helper function used to cache the language negotiation providers results.
|
||||
*
|
||||
* @param $provider_id
|
||||
* The language provider ID.
|
||||
* The language negotiation provider's identifier.
|
||||
* @param $provider
|
||||
* The language provider to be invoked. If not passed it will be explicitly
|
||||
* loaded through language_negotiation_info().
|
||||
* (optional) An associative array of information about the provider to be
|
||||
* invoked (see hook_language_negotiation_info() for details). If not passed
|
||||
* in, it will be loaded through language_negotiation_info().
|
||||
*
|
||||
* @return
|
||||
* The language provider's return value.
|
||||
* A language object representing the language chosen by the provider.
|
||||
*/
|
||||
function language_provider_invoke($provider_id, $provider = NULL) {
|
||||
$results = &drupal_static(__FUNCTION__);
|
||||
@@ -352,25 +443,26 @@ function language_provider_invoke($provider_id, $provider = NULL) {
|
||||
require_once DRUPAL_ROOT . '/' . $provider['file'];
|
||||
}
|
||||
|
||||
// If the language provider has no cache preference or this is satisfied
|
||||
// we can execute the callback.
|
||||
// If the language negotiation provider has no cache preference or this is
|
||||
// satisfied we can execute the callback.
|
||||
$cache = !isset($provider['cache']) || $user->uid || $provider['cache'] == variable_get('cache', 0);
|
||||
$callback = isset($provider['callbacks']['language']) ? $provider['callbacks']['language'] : FALSE;
|
||||
$langcode = $cache && function_exists($callback) ? $callback($languages) : FALSE;
|
||||
$results[$provider_id] = isset($languages[$langcode]) ? $languages[$langcode] : FALSE;
|
||||
}
|
||||
|
||||
// Since objects are resources we need to return a clone to prevent the
|
||||
// provider cache to be unintentionally altered. The same providers might be
|
||||
// used with different language types based on configuration.
|
||||
// Since objects are resources, we need to return a clone to prevent the
|
||||
// language negotiation provider cache from being unintentionally altered. The
|
||||
// same providers might be used with different language types based on
|
||||
// configuration.
|
||||
return !empty($results[$provider_id]) ? clone($results[$provider_id]) : $results[$provider_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the passed language provider weight or a default value.
|
||||
* Returns the passed language negotiation provider weight or a default value.
|
||||
*
|
||||
* @param $provider
|
||||
* A language provider data structure.
|
||||
* A language negotiation provider data structure.
|
||||
*
|
||||
* @return
|
||||
* A numeric weight.
|
||||
@@ -381,16 +473,16 @@ function language_provider_weight($provider) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose a language for the given type based on language negotiation settings.
|
||||
* Chooses a language based on language negotiation provider settings.
|
||||
*
|
||||
* @param $type
|
||||
* The language type.
|
||||
* The language type key to find the language for.
|
||||
*
|
||||
* @return
|
||||
* The negotiated language object.
|
||||
*/
|
||||
function language_initialize($type) {
|
||||
// Execute the language providers in the order they were set up and return the
|
||||
// Execute the language negotiation providers in the order they were set up and return the
|
||||
// first valid language found.
|
||||
$negotiation = variable_get("language_negotiation_$type", array());
|
||||
|
||||
@@ -409,7 +501,7 @@ function language_initialize($type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Default language provider.
|
||||
* Returns the default language negotiation provider.
|
||||
*
|
||||
* @return
|
||||
* The default language code.
|
||||
@@ -421,8 +513,8 @@ function language_from_default() {
|
||||
/**
|
||||
* Splits the given path into prefix and actual path.
|
||||
*
|
||||
* Parse the given path and return the language object identified by the
|
||||
* prefix and the actual path.
|
||||
* Parse the given path and return the language object identified by the prefix
|
||||
* and the actual path.
|
||||
*
|
||||
* @param $path
|
||||
* The path to split.
|
||||
@@ -482,3 +574,7 @@ function language_fallback_get_candidates($type = LANGUAGE_TYPE_CONTENT) {
|
||||
|
||||
return $fallback_candidates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "language_negotiation"
|
||||
*/
|
||||
|
||||
@@ -93,7 +93,9 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
|
||||
* will be {$module}_{$key}.
|
||||
* @param $to
|
||||
* The e-mail address or addresses where the message will be sent to. The
|
||||
* formatting of this string must comply with RFC 2822. Some examples are:
|
||||
* formatting of this string will be validated with the
|
||||
* @link http://php.net/manual/filter.filters.validate.php PHP e-mail validation filter. @endlink
|
||||
* Some examples are:
|
||||
* - user@example.com
|
||||
* - user@example.com, anotheruser@example.com
|
||||
* - User <user@example.com>
|
||||
@@ -212,9 +214,9 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N
|
||||
* 'mail_system', which is a keyed array. The default implementation
|
||||
* is the class whose name is the value of 'default-system' key. A more specific
|
||||
* match first to key and then to module will be used in preference to the
|
||||
* default. To specificy a different class for all mail sent by one module, set
|
||||
* default. To specify a different class for all mail sent by one module, set
|
||||
* the class name as the value for the key corresponding to the module name. To
|
||||
* specificy a class for a particular message sent by one module, set the class
|
||||
* specify a class for a particular message sent by one module, set the class
|
||||
* name as the value for the array key that is the message id, which is
|
||||
* "${module}_${key}".
|
||||
*
|
||||
@@ -307,19 +309,21 @@ interface MailSystemInterface {
|
||||
* - id: A unique identifier of the e-mail type. Examples: 'contact_user_copy',
|
||||
* 'user_password_reset'.
|
||||
* - to: The mail address or addresses where the message will be sent to.
|
||||
* The formatting of this string must comply with RFC 2822. Some examples:
|
||||
* The formatting of this string will be validated with the
|
||||
* @link http://php.net/manual/filter.filters.validate.php PHP e-mail validation filter. @endlink
|
||||
* Some examples are:
|
||||
* - user@example.com
|
||||
* - user@example.com, anotheruser@example.com
|
||||
* - User <user@example.com>
|
||||
* - User <user@example.com>, Another User <anotheruser@example.com>
|
||||
* - subject: Subject of the e-mail to be sent. This must not contain any
|
||||
* newline characters, or the mail may not be sent properly.
|
||||
* - body: Message to be sent. Accepts both CRLF and LF line-endings.
|
||||
* E-mail bodies must be wrapped. You can use drupal_wrap_mail() for
|
||||
* smart plain text wrapping.
|
||||
* - headers: Associative array containing all additional mail headers not
|
||||
* defined by one of the other parameters. PHP's mail() looks for Cc
|
||||
* and Bcc headers and sends the mail to addresses in these headers too.
|
||||
* - subject: Subject of the e-mail to be sent. This must not contain any
|
||||
* newline characters, or the mail may not be sent properly.
|
||||
* - body: Message to be sent. Accepts both CRLF and LF line-endings.
|
||||
* E-mail bodies must be wrapped. You can use drupal_wrap_mail() for
|
||||
* smart plain text wrapping.
|
||||
* - headers: Associative array containing all additional mail headers not
|
||||
* defined by one of the other parameters. PHP's mail() looks for Cc and
|
||||
* Bcc headers and sends the mail to addresses in these headers too.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the mail was successfully accepted for delivery, otherwise FALSE.
|
||||
@@ -335,13 +339,13 @@ interface MailSystemInterface {
|
||||
*
|
||||
* We deliberately use LF rather than CRLF, see drupal_mail().
|
||||
*
|
||||
* @param $text
|
||||
* @param string $text
|
||||
* The plain text to process.
|
||||
* @param $indent (optional)
|
||||
* @param string $indent (optional)
|
||||
* A string to indent the text with. Only '>' characters are repeated on
|
||||
* subsequent wrapped lines. Others are replaced by spaces.
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* The content of the email as a string with formatting applied.
|
||||
*/
|
||||
function drupal_wrap_mail($text, $indent = '') {
|
||||
@@ -352,8 +356,9 @@ function drupal_wrap_mail($text, $indent = '') {
|
||||
$soft = strpos($clean_indent, ' ') === FALSE;
|
||||
// Check if the string has line breaks.
|
||||
if (strpos($text, "\n") !== FALSE) {
|
||||
// Remove trailing spaces to make existing breaks hard.
|
||||
$text = preg_replace('/ +\n/m', "\n", $text);
|
||||
// Remove trailing spaces to make existing breaks hard, but leave signature
|
||||
// marker untouched (RFC 3676, Section 4.3).
|
||||
$text = preg_replace('/(?(?<!^--) +\n| +\n)/m', "\n", $text);
|
||||
// Wrap each line at the needed width.
|
||||
$lines = explode("\n", $text);
|
||||
array_walk($lines, '_drupal_wrap_mail_line', array('soft' => $soft, 'length' => strlen($indent)));
|
||||
@@ -559,7 +564,7 @@ function drupal_html_to_text($string, $allowed_tags = NULL) {
|
||||
*/
|
||||
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");
|
||||
$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");
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ define('MENU_PREFERRED_LINK', '1cf698d64d1aa4b83907cf6ed55db3a7f8e92c91');
|
||||
* actually exists. This list of 'masks' is built in menu_rebuild().
|
||||
*
|
||||
* @param $parts
|
||||
* An array of path parts, for the above example
|
||||
* An array of path parts; for the above example,
|
||||
* array('node', '12345', 'edit').
|
||||
*
|
||||
* @return
|
||||
@@ -430,7 +430,7 @@ function menu_set_item($path, $router_item) {
|
||||
* Gets a router item.
|
||||
*
|
||||
* @param $path
|
||||
* The path, for example node/5. The function will find the corresponding
|
||||
* The path; for example, 'node/5'. The function will find the corresponding
|
||||
* node/% item and return that.
|
||||
* @param $router_item
|
||||
* Internal use only.
|
||||
@@ -542,7 +542,7 @@ function menu_execute_active_handler($path = NULL, $deliver = TRUE) {
|
||||
* @param $item
|
||||
* A menu router or menu link item
|
||||
* @param $map
|
||||
* An array of path arguments (ex: array('node', '5'))
|
||||
* An array of path arguments; for example, array('node', '5').
|
||||
*
|
||||
* @return
|
||||
* Returns TRUE for success, FALSE if an object cannot be loaded.
|
||||
@@ -612,12 +612,13 @@ function _menu_load_objects(&$item, &$map) {
|
||||
* @param $item
|
||||
* A menu router or menu link item
|
||||
* @param $map
|
||||
* An array of path arguments (ex: array('node', '5'))
|
||||
* An array of path arguments; for example, array('node', '5').
|
||||
*
|
||||
* @return
|
||||
* $item['access'] becomes TRUE if the item is accessible, FALSE otherwise.
|
||||
*/
|
||||
function _menu_check_access(&$item, $map) {
|
||||
$item['access'] = FALSE;
|
||||
// Determine access callback, which will decide whether or not the current
|
||||
// user has access to this path.
|
||||
$callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']);
|
||||
@@ -737,7 +738,7 @@ function _menu_item_localize(&$item, $map, $link_translate = FALSE) {
|
||||
* @param $router_item
|
||||
* A menu router item
|
||||
* @param $map
|
||||
* An array of path arguments (ex: array('node', '5'))
|
||||
* An array of path arguments; for example, array('node', '5').
|
||||
* @param $to_arg
|
||||
* Execute $item['to_arg_functions'] or not. Use only if you want to render a
|
||||
* path from the menu table, for example tabs.
|
||||
@@ -800,9 +801,9 @@ function _menu_translate(&$router_item, $map, $to_arg = FALSE) {
|
||||
* Translates the path elements in the map using any to_arg helper function.
|
||||
*
|
||||
* @param $map
|
||||
* An array of path arguments (ex: array('node', '5'))
|
||||
* An array of path arguments; for example, array('node', '5').
|
||||
* @param $to_arg_functions
|
||||
* An array of helper function (ex: array(2 => 'menu_tail_to_arg'))
|
||||
* An array of helper functions; for example, array(2 => 'menu_tail_to_arg').
|
||||
*
|
||||
* @see hook_menu()
|
||||
*/
|
||||
@@ -999,7 +1000,7 @@ function menu_tree($menu_name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rendered menu tree.
|
||||
* Returns an output structure for rendering a menu tree.
|
||||
*
|
||||
* The menu item's LI element is given one of the following classes:
|
||||
* - expanded: The menu item is showing its submenu.
|
||||
@@ -1925,13 +1926,21 @@ function menu_local_tasks($level = 0) {
|
||||
}
|
||||
|
||||
// Get all tabs (also known as local tasks) and the root page.
|
||||
$result = db_select('menu_router', NULL, array('fetch' => PDO::FETCH_ASSOC))
|
||||
->fields('menu_router')
|
||||
->condition('tab_root', $router_item['tab_root'])
|
||||
->condition('context', MENU_CONTEXT_INLINE, '<>')
|
||||
->orderBy('weight')
|
||||
->orderBy('title')
|
||||
->execute();
|
||||
$cid = 'local_tasks:' . $router_item['tab_root'];
|
||||
if ($cache = cache_get($cid, 'cache_menu')) {
|
||||
$result = $cache->data;
|
||||
}
|
||||
else {
|
||||
$result = db_select('menu_router', NULL, array('fetch' => PDO::FETCH_ASSOC))
|
||||
->fields('menu_router')
|
||||
->condition('tab_root', $router_item['tab_root'])
|
||||
->condition('context', MENU_CONTEXT_INLINE, '<>')
|
||||
->orderBy('weight')
|
||||
->orderBy('title')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
cache_set($cid, $result, 'cache_menu');
|
||||
}
|
||||
$map = $router_item['original_map'];
|
||||
$children = array();
|
||||
$tasks = array();
|
||||
@@ -2138,7 +2147,7 @@ function menu_local_tasks($level = 0) {
|
||||
* example 'node' or 'admin/structure/block/manage'.
|
||||
* @param $args
|
||||
* A list of dynamic path arguments to append to $parent_path to form the
|
||||
* fully-qualified menu router path, for example array(123) for a certain
|
||||
* fully-qualified menu router path; for example, array(123) for a certain
|
||||
* node or array('system', 'navigation') for a certain block.
|
||||
*
|
||||
* @return
|
||||
@@ -2429,7 +2438,7 @@ function menu_set_active_trail($new_trail = NULL) {
|
||||
* Looks up the preferred menu link for a given system path.
|
||||
*
|
||||
* @param $path
|
||||
* The path, for example 'node/5'. The function will find the corresponding
|
||||
* The path; for example, 'node/5'. The function will find the corresponding
|
||||
* menu link ('node/5' if it exists, or fallback to 'node/%').
|
||||
* @param $selected_menu
|
||||
* The name of a menu used to restrict the search for a preferred menu link.
|
||||
|
||||
@@ -610,9 +610,40 @@ function module_disable($module_list, $disable_dependents = TRUE) {
|
||||
* just models that you can modify. Only the hooks implemented within modules
|
||||
* are executed when running Drupal.
|
||||
*
|
||||
* See also @link themeable the themeable group page. @endlink
|
||||
* @see themeable
|
||||
* @see callbacks
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup callbacks Callbacks
|
||||
* @{
|
||||
* Callback function signatures.
|
||||
*
|
||||
* Drupal's API sometimes uses callback functions to allow you to define how
|
||||
* some type of processing happens. A callback is a function with a defined
|
||||
* signature, which you define in a module. Then you pass the function name as
|
||||
* a parameter to a Drupal API function or return it as part of a hook
|
||||
* implementation return value, and your function is called at an appropriate
|
||||
* time. For instance, when setting up batch processing you might need to
|
||||
* provide a callback function for each processing step and/or a callback for
|
||||
* when processing is finished; you would do that by defining these functions
|
||||
* and passing their names into the batch setup function.
|
||||
*
|
||||
* Callback function signatures, like hook definitions, are described by
|
||||
* creating and documenting dummy functions in a *.api.php file; normally, the
|
||||
* dummy callback function's name should start with "callback_", and you should
|
||||
* document the parameters and return value and provide a sample function body.
|
||||
* Then your API documentation can refer to this callback function in its
|
||||
* documentation. A user of your API can usually name their callback function
|
||||
* anything they want, although a standard name would be to replace "callback_"
|
||||
* with the module name.
|
||||
*
|
||||
* @see hooks
|
||||
* @see themeable
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determines whether a module implements a hook.
|
||||
*
|
||||
@@ -803,10 +834,7 @@ function module_hook_info() {
|
||||
*/
|
||||
function module_implements_write_cache() {
|
||||
$implementations = &drupal_static('module_implements');
|
||||
// Check whether we need to write the cache. We do not want to cache hooks
|
||||
// which are only invoked on HTTP POST requests since these do not need to be
|
||||
// optimized as tightly, and not doing so keeps the cache entry smaller.
|
||||
if (isset($implementations['#write_cache']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD')) {
|
||||
if (isset($implementations['#write_cache'])) {
|
||||
unset($implementations['#write_cache']);
|
||||
cache_set('module_implements', $implementations, 'cache_bootstrap');
|
||||
}
|
||||
@@ -815,6 +843,9 @@ function module_implements_write_cache() {
|
||||
/**
|
||||
* Invokes a hook in a particular module.
|
||||
*
|
||||
* All arguments are passed by value. Use drupal_alter() if you need to pass
|
||||
* arguments by reference.
|
||||
*
|
||||
* @param $module
|
||||
* The name of the module (without the .module extension).
|
||||
* @param $hook
|
||||
@@ -824,6 +855,8 @@ function module_implements_write_cache() {
|
||||
*
|
||||
* @return
|
||||
* The return value of the hook implementation.
|
||||
*
|
||||
* @see drupal_alter()
|
||||
*/
|
||||
function module_invoke($module, $hook) {
|
||||
$args = func_get_args();
|
||||
@@ -837,6 +870,9 @@ function module_invoke($module, $hook) {
|
||||
/**
|
||||
* Invokes a hook in all enabled modules that implement it.
|
||||
*
|
||||
* All arguments are passed by value. Use drupal_alter() if you need to pass
|
||||
* arguments by reference.
|
||||
*
|
||||
* @param $hook
|
||||
* The name of the hook to invoke.
|
||||
* @param ...
|
||||
@@ -845,6 +881,8 @@ 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.
|
||||
*
|
||||
* @see drupal_alter()
|
||||
*/
|
||||
function module_invoke_all($hook) {
|
||||
$args = func_get_args();
|
||||
@@ -898,9 +936,10 @@ function drupal_required_modules() {
|
||||
* hook_TYPE_alter() implementations in modules. It ensures a consistent
|
||||
* interface for all altering operations.
|
||||
*
|
||||
* A maximum of 2 alterable arguments is supported. In case more arguments need
|
||||
* to be passed and alterable, modules provide additional variables assigned by
|
||||
* reference in the last $context argument:
|
||||
* A maximum of 2 alterable arguments is supported (a third is supported for
|
||||
* legacy reasons, but should not be used in new code). In case more arguments
|
||||
* need to be passed and alterable, modules provide additional variables
|
||||
* assigned by reference in the last $context argument:
|
||||
* @code
|
||||
* $context = array(
|
||||
* 'alterable' => &$alterable,
|
||||
@@ -939,8 +978,14 @@ function drupal_required_modules() {
|
||||
* (optional) An additional variable that is passed by reference. If more
|
||||
* context needs to be provided to implementations, then this should be an
|
||||
* associative array as described above.
|
||||
* @param $context3
|
||||
* (optional) An additional variable that is passed by reference. This
|
||||
* parameter is deprecated and will not exist in Drupal 8; consequently, it
|
||||
* should not be used for new Drupal 7 code either. It is here only for
|
||||
* backwards compatibility with older code that passed additional arguments
|
||||
* to drupal_alter().
|
||||
*/
|
||||
function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
|
||||
function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL, &$context3 = NULL) {
|
||||
// Use the advanced drupal_static() pattern, since this is called very often.
|
||||
static $drupal_static_fast;
|
||||
if (!isset($drupal_static_fast)) {
|
||||
@@ -1053,6 +1098,6 @@ function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
|
||||
}
|
||||
|
||||
foreach ($functions[$cid] as $function) {
|
||||
$function($data, $context1, $context2);
|
||||
$function($data, $context1, $context2, $context3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ function _password_itoa64() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode bytes into printable base 64 using the *nix standard from crypt().
|
||||
* Encodes bytes into printable base 64 using the *nix standard from crypt().
|
||||
*
|
||||
* @param $input
|
||||
* The string containing bytes to encode.
|
||||
|
||||
@@ -386,7 +386,7 @@ function drupal_path_alias_whitelist_rebuild($source = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a specific URL alias from the database.
|
||||
* Fetches a specific URL alias from the database.
|
||||
*
|
||||
* @param $conditions
|
||||
* A string representing the source, a number representing the pid, or an
|
||||
@@ -475,11 +475,11 @@ function path_delete($criteria) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a path is in the administrative section of the site.
|
||||
* Determines whether a path is in the administrative section of the site.
|
||||
*
|
||||
* By default, paths are considered to be non-administrative. If a path does not
|
||||
* match any of the patterns in path_get_admin_paths(), or if it matches both
|
||||
* administrative and non-administrative patterns, it is considered
|
||||
* By default, paths are considered to be non-administrative. If a path does
|
||||
* not match any of the patterns in path_get_admin_paths(), or if it matches
|
||||
* both administrative and non-administrative patterns, it is considered
|
||||
* non-administrative.
|
||||
*
|
||||
* @param $path
|
||||
@@ -503,7 +503,7 @@ function path_is_admin($path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of administrative and non-administrative paths.
|
||||
* Gets a list of administrative and non-administrative paths.
|
||||
*
|
||||
* @return array
|
||||
* An associative array containing the following keys:
|
||||
@@ -560,8 +560,8 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) {
|
||||
elseif ($dynamic_allowed && preg_match('/\/\%/', $path)) {
|
||||
// Path is dynamic (ie 'user/%'), so check directly against menu_router table.
|
||||
if ($item = db_query("SELECT * FROM {menu_router} where path = :path", array(':path' => $path))->fetchAssoc()) {
|
||||
$item['link_path'] = $form_item['link_path'];
|
||||
$item['link_title'] = $form_item['link_title'];
|
||||
$item['link_path'] = $item['path'];
|
||||
$item['link_title'] = $item['title'];
|
||||
$item['external'] = FALSE;
|
||||
$item['options'] = '';
|
||||
_menu_link_translate($item);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* @{
|
||||
* The code registry engine.
|
||||
*
|
||||
* Drupal maintains an internal registry of all functions or classes in the
|
||||
* Drupal maintains an internal registry of all interfaces or classes in the
|
||||
* system, allowing it to lazy-load code files as needed (reducing the amount
|
||||
* of code that must be parsed on each request).
|
||||
*/
|
||||
@@ -120,7 +120,10 @@ function registry_get_parsed_files() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all files that have changed since the registry was last built, and save their function and class listings.
|
||||
* Parse all changed files and save their interface and class listings.
|
||||
*
|
||||
* Parse all files that have changed since the registry was last built, and save
|
||||
* their interface and class listings.
|
||||
*
|
||||
* @param $files
|
||||
* The list of files to check and parse.
|
||||
@@ -149,7 +152,7 @@ function _registry_parse_files($files) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a file and save its function and class listings.
|
||||
* Parse a file and save its interface and class listings.
|
||||
*
|
||||
* @param $filename
|
||||
* Name of the file we are going to parse.
|
||||
|
||||
@@ -263,10 +263,10 @@ function drupal_session_initialize() {
|
||||
// Less random sessions (which are much faster to generate) are used for
|
||||
// anonymous users than are generated in drupal_session_regenerate() when
|
||||
// a user becomes authenticated.
|
||||
session_id(drupal_hash_base64(uniqid(mt_rand(), TRUE)));
|
||||
session_id(drupal_random_key());
|
||||
if ($is_https && variable_get('https', FALSE)) {
|
||||
$insecure_session_name = substr(session_name(), 1);
|
||||
$session_id = drupal_hash_base64(uniqid(mt_rand(), TRUE));
|
||||
$session_id = drupal_random_key();
|
||||
$_COOKIE[$insecure_session_name] = $session_id;
|
||||
}
|
||||
}
|
||||
@@ -274,7 +274,7 @@ function drupal_session_initialize() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Forcefully starts a session, preserving already set session data.
|
||||
* Starts a session forcefully, preserving already set session data.
|
||||
*
|
||||
* @ingroup php_wrappers
|
||||
*/
|
||||
@@ -360,7 +360,7 @@ function drupal_session_regenerate() {
|
||||
$old_insecure_session_id = $_COOKIE[$insecure_session_name];
|
||||
}
|
||||
$params = session_get_cookie_params();
|
||||
$session_id = drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55));
|
||||
$session_id = drupal_random_key();
|
||||
// If a session cookie lifetime is set, the session will expire
|
||||
// $params['lifetime'] seconds from the current request. If it is not set,
|
||||
// it will expire when the browser is closed.
|
||||
@@ -372,7 +372,7 @@ function drupal_session_regenerate() {
|
||||
if (drupal_session_started()) {
|
||||
$old_session_id = session_id();
|
||||
}
|
||||
session_id(drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55)));
|
||||
session_id(drupal_random_key());
|
||||
|
||||
if (isset($old_session_id)) {
|
||||
$params = session_get_cookie_params();
|
||||
|
||||
@@ -93,7 +93,7 @@ define('STREAM_WRAPPERS_LOCAL_NORMAL', STREAM_WRAPPERS_LOCAL | STREAM_WRAPPERS_N
|
||||
/**
|
||||
* Generic PHP stream wrapper interface.
|
||||
*
|
||||
* @see http://www.php.net/manual/en/class.streamwrapper.php
|
||||
* @see http://www.php.net/manual/class.streamwrapper.php
|
||||
*/
|
||||
interface StreamWrapperInterface {
|
||||
public function stream_open($uri, $mode, $options, &$opened_url);
|
||||
@@ -401,7 +401,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* Returns TRUE if file was opened successfully.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-open.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-open.php
|
||||
*/
|
||||
public function stream_open($uri, $mode, $options, &$opened_path) {
|
||||
$this->uri = $uri;
|
||||
@@ -429,7 +429,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* Always returns TRUE at the present time.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-lock.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-lock.php
|
||||
*/
|
||||
public function stream_lock($operation) {
|
||||
if (in_array($operation, array(LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB))) {
|
||||
@@ -448,7 +448,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* The string that was read, or FALSE in case of an error.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-read.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-read.php
|
||||
*/
|
||||
public function stream_read($count) {
|
||||
return fread($this->handle, $count);
|
||||
@@ -463,7 +463,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* The number of bytes written (integer).
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-write.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-write.php
|
||||
*/
|
||||
public function stream_write($data) {
|
||||
return fwrite($this->handle, $data);
|
||||
@@ -475,7 +475,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE if end-of-file has been reached.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-eof.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-eof.php
|
||||
*/
|
||||
public function stream_eof() {
|
||||
return feof($this->handle);
|
||||
@@ -492,7 +492,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-seek.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-seek.php
|
||||
*/
|
||||
public function stream_seek($offset, $whence) {
|
||||
// fseek returns 0 on success and -1 on a failure.
|
||||
@@ -506,7 +506,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE if data was successfully stored (or there was no data to store).
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-flush.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-flush.php
|
||||
*/
|
||||
public function stream_flush() {
|
||||
return fflush($this->handle);
|
||||
@@ -518,7 +518,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* The current offset in bytes from the beginning of file.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-tell.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-tell.php
|
||||
*/
|
||||
public function stream_tell() {
|
||||
return ftell($this->handle);
|
||||
@@ -531,7 +531,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* An array with file status, or FALSE in case of an error - see fstat()
|
||||
* for a description of this array.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-stat.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-stat.php
|
||||
*/
|
||||
public function stream_stat() {
|
||||
return fstat($this->handle);
|
||||
@@ -543,7 +543,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE if stream was successfully closed.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.stream-close.php
|
||||
* @see http://php.net/manual/streamwrapper.stream-close.php
|
||||
*/
|
||||
public function stream_close() {
|
||||
return fclose($this->handle);
|
||||
@@ -558,7 +558,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE if resource was successfully deleted.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.unlink.php
|
||||
* @see http://php.net/manual/streamwrapper.unlink.php
|
||||
*/
|
||||
public function unlink($uri) {
|
||||
$this->uri = $uri;
|
||||
@@ -576,7 +576,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE if file was successfully renamed.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.rename.php
|
||||
* @see http://php.net/manual/streamwrapper.rename.php
|
||||
*/
|
||||
public function rename($from_uri, $to_uri) {
|
||||
return rename($this->getLocalPath($from_uri), $this->getLocalPath($to_uri));
|
||||
@@ -622,7 +622,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE if directory was successfully created.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.mkdir.php
|
||||
* @see http://php.net/manual/streamwrapper.mkdir.php
|
||||
*/
|
||||
public function mkdir($uri, $mode, $options) {
|
||||
$this->uri = $uri;
|
||||
@@ -654,7 +654,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE if directory was successfully removed.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.rmdir.php
|
||||
* @see http://php.net/manual/streamwrapper.rmdir.php
|
||||
*/
|
||||
public function rmdir($uri, $options) {
|
||||
$this->uri = $uri;
|
||||
@@ -678,7 +678,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* An array with file status, or FALSE in case of an error - see fstat()
|
||||
* for a description of this array.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.url-stat.php
|
||||
* @see http://php.net/manual/streamwrapper.url-stat.php
|
||||
*/
|
||||
public function url_stat($uri, $flags) {
|
||||
$this->uri = $uri;
|
||||
@@ -704,7 +704,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.dir-opendir.php
|
||||
* @see http://php.net/manual/streamwrapper.dir-opendir.php
|
||||
*/
|
||||
public function dir_opendir($uri, $options) {
|
||||
$this->uri = $uri;
|
||||
@@ -719,7 +719,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* The next filename, or FALSE if there are no more files in the directory.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.dir-readdir.php
|
||||
* @see http://php.net/manual/streamwrapper.dir-readdir.php
|
||||
*/
|
||||
public function dir_readdir() {
|
||||
return readdir($this->handle);
|
||||
@@ -731,7 +731,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.dir-rewinddir.php
|
||||
* @see http://php.net/manual/streamwrapper.dir-rewinddir.php
|
||||
*/
|
||||
public function dir_rewinddir() {
|
||||
rewinddir($this->handle);
|
||||
@@ -747,7 +747,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*
|
||||
* @see http://php.net/manual/en/streamwrapper.dir-closedir.php
|
||||
* @see http://php.net/manual/streamwrapper.dir-closedir.php
|
||||
*/
|
||||
public function dir_closedir() {
|
||||
closedir($this->handle);
|
||||
@@ -788,8 +788,6 @@ class DrupalPublicStreamWrapper extends DrupalLocalStreamWrapper {
|
||||
*
|
||||
* Provides support for storing privately accessible files with the Drupal file
|
||||
* interface.
|
||||
*
|
||||
* Extends DrupalPublicStreamWrapper.
|
||||
*/
|
||||
class DrupalPrivateStreamWrapper extends DrupalLocalStreamWrapper {
|
||||
/**
|
||||
|
||||
@@ -55,7 +55,7 @@ class TableSort extends SelectQueryExtender {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the table sort context.
|
||||
* Initializes the table sort context.
|
||||
*/
|
||||
protected function init() {
|
||||
$ts = $this->order();
|
||||
@@ -115,7 +115,7 @@ function tablesort_init($header) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a column header.
|
||||
* Formats a column header.
|
||||
*
|
||||
* If the cell in question is the column header for the current sort criterion,
|
||||
* it gets special formatting. All possible sort criteria become links.
|
||||
@@ -126,6 +126,7 @@ function tablesort_init($header) {
|
||||
* An array of column headers in the format described in theme_table().
|
||||
* @param $ts
|
||||
* The current table sort context as returned from tablesort_init().
|
||||
*
|
||||
* @return
|
||||
* A properly formatted cell, ready for _theme_table_cell().
|
||||
*/
|
||||
@@ -151,7 +152,7 @@ function tablesort_header($cell, $header, $ts) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a table cell.
|
||||
* Formats a table cell.
|
||||
*
|
||||
* Adds a class attribute to all cells in the currently active column.
|
||||
*
|
||||
@@ -163,6 +164,7 @@ function tablesort_header($cell, $header, $ts) {
|
||||
* The current table sort context as returned from tablesort_init().
|
||||
* @param $i
|
||||
* The index of the cell's table column.
|
||||
*
|
||||
* @return
|
||||
* A properly formatted cell, ready for _theme_table_cell().
|
||||
*/
|
||||
@@ -179,7 +181,7 @@ function tablesort_cell($cell, $header, $ts, $i) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a URL query parameter array for table sorting links.
|
||||
* Composes a URL query parameter array for table sorting links.
|
||||
*
|
||||
* @return
|
||||
* A URL query parameter array that consists of all components of the current
|
||||
@@ -190,10 +192,11 @@ function tablesort_get_query_parameters() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the current sort criterion.
|
||||
* Determines the current sort criterion.
|
||||
*
|
||||
* @param $headers
|
||||
* An array of column headers in the format described in theme_table().
|
||||
*
|
||||
* @return
|
||||
* An associative array describing the criterion, containing the keys:
|
||||
* - "name": The localized title of the table column.
|
||||
@@ -226,10 +229,11 @@ function tablesort_get_order($headers) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the current sort direction.
|
||||
* Determines the current sort direction.
|
||||
*
|
||||
* @param $headers
|
||||
* An array of column headers in the format described in theme_table().
|
||||
*
|
||||
* @return
|
||||
* The current sort direction ("asc" or "desc").
|
||||
*/
|
||||
|
||||
@@ -65,7 +65,7 @@ function _drupal_theme_access($theme) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the theme system by loading the theme.
|
||||
* Initializes the theme system by loading the theme.
|
||||
*/
|
||||
function drupal_theme_initialize() {
|
||||
global $theme, $user, $theme_key;
|
||||
@@ -113,8 +113,9 @@ function drupal_theme_initialize() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the theme system given already loaded information. This
|
||||
* function is useful to initialize a theme when no database is present.
|
||||
* Initializes the theme system given already loaded information.
|
||||
*
|
||||
* This function is useful to initialize a theme when no database is present.
|
||||
*
|
||||
* @param $theme
|
||||
* An object with the following information:
|
||||
@@ -235,7 +236,7 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the theme registry.
|
||||
* Gets the theme registry.
|
||||
*
|
||||
* @param $complete
|
||||
* Optional boolean to indicate whether to return the complete theme registry
|
||||
@@ -280,7 +281,7 @@ function theme_get_registry($complete = TRUE) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the callback that will be used by theme_get_registry() to fetch the registry.
|
||||
* Sets the callback that will be used by theme_get_registry().
|
||||
*
|
||||
* @param $callback
|
||||
* The name of the callback function.
|
||||
@@ -296,7 +297,7 @@ function _theme_registry_callback($callback = NULL, array $arguments = array())
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the theme_registry cache; if it doesn't exist, build it.
|
||||
* Gets the theme_registry cache; if it doesn't exist, builds it.
|
||||
*
|
||||
* @param $theme
|
||||
* The loaded $theme object as returned by list_themes().
|
||||
@@ -336,16 +337,17 @@ function _theme_load_registry($theme, $base_theme = NULL, $theme_engine = NULL,
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the theme_registry cache into the database.
|
||||
* Writes the theme_registry cache into the database.
|
||||
*/
|
||||
function _theme_save_registry($theme, $registry) {
|
||||
cache_set("theme_registry:$theme->name", $registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the system to rebuild the theme registry; this should be called
|
||||
* when modules are added to the system, or when a dynamic system needs
|
||||
* to add more theme hooks.
|
||||
* Forces the system to rebuild the theme registry.
|
||||
*
|
||||
* This function should be called when modules are added to the system, or when
|
||||
* a dynamic system needs to add more theme hooks.
|
||||
*/
|
||||
function drupal_theme_rebuild() {
|
||||
drupal_static_reset('theme_get_registry');
|
||||
@@ -506,7 +508,7 @@ class ThemeRegistry Extends DrupalCacheArray {
|
||||
* themes/bartik.
|
||||
*
|
||||
* @see theme()
|
||||
* @see _theme_process_registry()
|
||||
* @see _theme_build_registry()
|
||||
* @see hook_theme()
|
||||
* @see list_themes()
|
||||
*/
|
||||
@@ -635,7 +637,8 @@ function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
|
||||
$cache = $result + $cache;
|
||||
}
|
||||
|
||||
// Let themes have variable processors even if they didn't register a template.
|
||||
// Let themes have variable processors even if they didn't register a
|
||||
// template.
|
||||
if ($type == 'theme' || $type == 'base_theme') {
|
||||
foreach ($cache as $hook => $info) {
|
||||
// Check only if not registered by the theme or engine.
|
||||
@@ -662,7 +665,7 @@ function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the theme registry cache.
|
||||
* Builds the theme registry cache.
|
||||
*
|
||||
* @param $theme
|
||||
* The loaded $theme object as returned by list_themes().
|
||||
@@ -724,7 +727,7 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all currently available themes.
|
||||
* Returns a list of all currently available themes.
|
||||
*
|
||||
* Retrieved from the database, if available and the site is not in maintenance
|
||||
* mode; otherwise compiled freshly from the filesystem.
|
||||
@@ -766,7 +769,7 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
|
||||
* their base theme), direct sub-themes of sub-themes, etc. The keys are
|
||||
* the themes' machine names, and the values are the themes' human-readable
|
||||
* names. This element is not set if there are no themes on the system that
|
||||
* declare this theme as their base theme.
|
||||
* declare this theme as their base theme.
|
||||
*/
|
||||
function list_themes($refresh = FALSE) {
|
||||
$list = &drupal_static(__FUNCTION__, array());
|
||||
@@ -866,11 +869,18 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) {
|
||||
/**
|
||||
* Generates themed output.
|
||||
*
|
||||
* All requests for themed output must go through this function. It examines
|
||||
* the request and routes it to the appropriate
|
||||
* All requests for themed output must go through this function (however,
|
||||
* calling the theme() function directly is strongly discouraged - see next
|
||||
* paragraph). It examines the request and routes it to the appropriate
|
||||
* @link themeable theme function or template @endlink, by checking the theme
|
||||
* registry.
|
||||
*
|
||||
* Avoid calling this function directly. It is preferable to replace direct
|
||||
* calls to the theme() function with calls to drupal_render() by passing a
|
||||
* render array with a #theme key to drupal_render(), which in turn calls
|
||||
* theme().
|
||||
*
|
||||
* @section sec_theme_hooks Theme Hooks
|
||||
* Most commonly, the first argument to this function is the name of the theme
|
||||
* hook. For instance, to theme a taxonomy term, the theme hook name is
|
||||
* 'taxonomy_term'. Modules register theme hooks within a hook_theme()
|
||||
@@ -882,6 +892,7 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) {
|
||||
* underscores changed to hyphens, so for the 'taxonomy_term' theme hook, the
|
||||
* default template is 'taxonomy-term.tpl.php'.
|
||||
*
|
||||
* @subsection sub_overriding_theme_hooks Overriding Theme Hooks
|
||||
* Themes may also register new theme hooks within a hook_theme()
|
||||
* implementation, but it is more common for themes to override default
|
||||
* implementations provided by modules than to register entirely new theme
|
||||
@@ -894,21 +905,22 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) {
|
||||
* rendering engine, it overrides the default implementation of the 'page' theme
|
||||
* hook by containing a 'page.tpl.php' file within its folder structure).
|
||||
*
|
||||
* @subsection sub_preprocess_templates Preprocessing for Template Files
|
||||
* If the implementation is a template file, several functions are called
|
||||
* before the template file is invoked, to modify the $variables array. These
|
||||
* fall into the "preprocessing" phase and the "processing" phase, and are
|
||||
* executed (if they exist), in the following order (note that in the following
|
||||
* list, HOOK indicates the theme hook name, MODULE indicates a module name,
|
||||
* THEME indicates a theme name, and ENGINE indicates a theme engine name):
|
||||
* - template_preprocess(&$variables, $hook): Creates a default set of variables
|
||||
* for all theme hooks with template implementations.
|
||||
* - template_preprocess(&$variables, $hook): Creates a default set of
|
||||
* variables for all theme hooks with template implementations.
|
||||
* - template_preprocess_HOOK(&$variables): Should be implemented by the module
|
||||
* that registers the theme hook, to set up default variables.
|
||||
* - MODULE_preprocess(&$variables, $hook): hook_preprocess() is invoked on all
|
||||
* implementing modules.
|
||||
* - MODULE_preprocess_HOOK(&$variables): hook_preprocess_HOOK() is invoked on
|
||||
* all implementing modules, so that modules that didn't define the theme hook
|
||||
* can alter the variables.
|
||||
* all implementing modules, so that modules that didn't define the theme
|
||||
* hook can alter the variables.
|
||||
* - ENGINE_engine_preprocess(&$variables, $hook): Allows the theme engine to
|
||||
* set necessary variables for all theme hooks with template implementations.
|
||||
* - ENGINE_engine_preprocess_HOOK(&$variables): Allows the theme engine to set
|
||||
@@ -942,12 +954,14 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) {
|
||||
* - THEME_process_HOOK(&$variables): Allows the theme to process the
|
||||
* variables specific to the theme hook.
|
||||
*
|
||||
* @subsection sub_preprocess_theme_funcs Preprocessing for Theme Functions
|
||||
* If the implementation is a function, only the theme-hook-specific preprocess
|
||||
* and process functions (the ones ending in _HOOK) are called from the
|
||||
* list above. This is because theme hooks with function implementations
|
||||
* need to be fast, and calling the non-theme-hook-specific preprocess and
|
||||
* process functions for them would incur a noticeable performance penalty.
|
||||
*
|
||||
* @subsection sub_alternate_suggestions Suggesting Alternate Hooks
|
||||
* There are two special variables that these preprocess and process functions
|
||||
* can set: 'theme_hook_suggestion' and 'theme_hook_suggestions'. These will be
|
||||
* merged together to form a list of 'suggested' alternate theme hooks to use,
|
||||
@@ -963,10 +977,10 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) {
|
||||
* @param $hook
|
||||
* The name of the theme hook to call. If the name contains a
|
||||
* double-underscore ('__') and there isn't an implementation for the full
|
||||
* name, the part before the '__' is checked. This allows a fallback to a more
|
||||
* generic implementation. For example, if theme('links__node', ...) is
|
||||
* called, but there is no implementation of that theme hook, then the 'links'
|
||||
* implementation is used. This process is iterative, so if
|
||||
* name, the part before the '__' is checked. This allows a fallback to a
|
||||
* more generic implementation. For example, if theme('links__node', ...) is
|
||||
* called, but there is no implementation of that theme hook, then the
|
||||
* 'links' implementation is used. This process is iterative, so if
|
||||
* theme('links__contextual__node', ...) is called, theme() checks for the
|
||||
* following implementations, and uses the first one that exists:
|
||||
* - links__contextual__node
|
||||
@@ -989,6 +1003,7 @@ function drupal_find_base_themes($themes, $key, $used_keys = array()) {
|
||||
* @return
|
||||
* An HTML string representing the themed output.
|
||||
*
|
||||
* @see drupal_render()
|
||||
* @see themeable
|
||||
* @see hook_theme()
|
||||
* @see template_preprocess()
|
||||
@@ -1030,7 +1045,7 @@ function theme($hook, $variables = array()) {
|
||||
// Only log a message when not trying theme suggestions ($hook being an
|
||||
// array).
|
||||
if (!isset($candidate)) {
|
||||
watchdog('theme', 'Theme key "@key" not found.', array('@key' => $hook), WATCHDOG_WARNING);
|
||||
watchdog('theme', 'Theme hook %hook not found.', array('%hook' => $hook), WATCHDOG_WARNING);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
@@ -1042,7 +1057,8 @@ function theme($hook, $variables = array()) {
|
||||
// point path_to_theme() to the currently used theme path:
|
||||
$theme_path = $info['theme path'];
|
||||
|
||||
// Include a file if the theme function or variable processor is held elsewhere.
|
||||
// Include a file if the theme function or variable processor is held
|
||||
// elsewhere.
|
||||
if (!empty($info['includes'])) {
|
||||
foreach ($info['includes'] as $include_file) {
|
||||
include_once DRUPAL_ROOT . '/' . $include_file;
|
||||
@@ -1191,14 +1207,14 @@ function theme($hook, $variables = array()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path to the current themed element.
|
||||
* Returns the path to the current themed element.
|
||||
*
|
||||
* It can point to the active theme or the module handling a themed implementation.
|
||||
* For example, when invoked within the scope of a theming call it will depend
|
||||
* on where the theming function is handled. If implemented from a module, it
|
||||
* will point to the module. If implemented from the active theme, it will point
|
||||
* to the active theme. When called outside the scope of a theming call, it will
|
||||
* always point to the active theme.
|
||||
* It can point to the active theme or the module handling a themed
|
||||
* implementation. For example, when invoked within the scope of a theming call
|
||||
* it will depend on where the theming function is handled. If implemented from
|
||||
* a module, it will point to the module. If implemented from the active theme,
|
||||
* it will point to the active theme. When called outside the scope of a
|
||||
* theming call, it will always point to the active theme.
|
||||
*/
|
||||
function path_to_theme() {
|
||||
global $theme_path;
|
||||
@@ -1211,7 +1227,7 @@ function path_to_theme() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow themes and/or theme engines to easily discover overridden theme functions.
|
||||
* Allows themes and/or theme engines to discover overridden theme functions.
|
||||
*
|
||||
* @param $cache
|
||||
* The existing cache of theme hooks to test against.
|
||||
@@ -1268,7 +1284,7 @@ function drupal_find_theme_functions($cache, $prefixes) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow themes and/or theme engines to easily discover overridden templates.
|
||||
* Allows themes and/or theme engines to easily discover overridden templates.
|
||||
*
|
||||
* @param $cache
|
||||
* The existing cache of theme hooks to test against.
|
||||
@@ -1345,7 +1361,8 @@ function drupal_find_theme_templates($cache, $extension, $path) {
|
||||
if ($matches) {
|
||||
foreach ($matches as $match) {
|
||||
$file = substr($match, 0, strpos($match, '.'));
|
||||
// Put the underscores back in for the hook name and register this pattern.
|
||||
// Put the underscores back in for the hook name and register this
|
||||
// pattern.
|
||||
$arg_name = isset($info['variables']) ? 'variables' : 'render element';
|
||||
$implementations[strtr($file, '-', '_')] = array(
|
||||
'template' => $file,
|
||||
@@ -1361,7 +1378,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a setting for the current theme or for a given theme.
|
||||
* Retrieves a setting for the current theme or for a given theme.
|
||||
*
|
||||
* The final setting is obtained from the last value found in the following
|
||||
* sources:
|
||||
@@ -1479,7 +1496,7 @@ function theme_get_setting($setting_name, $theme = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a system default template, which is essentially a PHP template.
|
||||
* Renders a system default template, which is essentially a PHP template.
|
||||
*
|
||||
* @param $template_file
|
||||
* The filename of the template to render.
|
||||
@@ -1490,14 +1507,21 @@ function theme_get_setting($setting_name, $theme = NULL) {
|
||||
* The output generated by the template.
|
||||
*/
|
||||
function theme_render_template($template_file, $variables) {
|
||||
extract($variables, EXTR_SKIP); // Extract the variables to a local namespace
|
||||
ob_start(); // Start output buffering
|
||||
include DRUPAL_ROOT . '/' . $template_file; // Include the template file
|
||||
return ob_get_clean(); // End buffering and return its contents
|
||||
// Extract the variables to a local namespace
|
||||
extract($variables, EXTR_SKIP);
|
||||
|
||||
// Start output buffering
|
||||
ob_start();
|
||||
|
||||
// Include the template file
|
||||
include DRUPAL_ROOT . '/' . $template_file;
|
||||
|
||||
// End buffering and return its contents
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a given list of themes.
|
||||
* Enables a given list of themes.
|
||||
*
|
||||
* @param $theme_list
|
||||
* An array of theme names.
|
||||
@@ -1522,7 +1546,7 @@ function theme_enable($theme_list) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable a given list of themes.
|
||||
* Disables a given list of themes.
|
||||
*
|
||||
* @param $theme_list
|
||||
* An array of theme names.
|
||||
@@ -1608,13 +1632,13 @@ function theme_status_messages($variables) {
|
||||
* theme('link') for rendering the anchor tag.
|
||||
*
|
||||
* To optimize performance for sites that don't need custom theming of links,
|
||||
* the l() function includes an inline copy of this function, and uses that copy
|
||||
* if none of the enabled modules or the active theme implement any preprocess
|
||||
* or process functions or override this theme implementation.
|
||||
* the l() function includes an inline copy of this function, and uses that
|
||||
* 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.
|
||||
* An associative array containing the keys 'text', 'path', and 'options'.
|
||||
* See the l() function for information about these variables.
|
||||
*
|
||||
* @see l()
|
||||
*/
|
||||
@@ -1635,15 +1659,16 @@ function theme_link($variables) {
|
||||
* item in the links list.
|
||||
* - html: (optional) Whether or not 'title' is HTML. If set, the title
|
||||
* will not be passed through check_plain().
|
||||
* - attributes: (optional) Attributes for the anchor, or for the <span> tag
|
||||
* used in its place if no 'href' is supplied. If element 'class' is
|
||||
* - attributes: (optional) Attributes for the anchor, or for the <span>
|
||||
* tag used in its place if no 'href' is supplied. If element 'class' is
|
||||
* included, it must be an array of one or more class names.
|
||||
* If the 'href' element is supplied, the entire link array is passed to l()
|
||||
* as its $options parameter.
|
||||
* If the 'href' element is supplied, the entire link array is passed to
|
||||
* l() as its $options parameter.
|
||||
* - attributes: A keyed array of attributes for the UL containing the
|
||||
* list of links.
|
||||
* - heading: (optional) A heading to precede the links. May be an associative
|
||||
* array or a string. If it's an array, it can have the following elements:
|
||||
* - heading: (optional) A heading to precede the links. May be an
|
||||
* associative array or a string. If it's an array, it can have the
|
||||
* following elements:
|
||||
* - text: The heading text.
|
||||
* - level: The heading level (e.g. 'h2', 'h3').
|
||||
* - class: (optional) An array of the CSS classes for the heading.
|
||||
@@ -1747,8 +1772,8 @@ function theme_links($variables) {
|
||||
* attribute to be omitted in some cases. Therefore, this variable defaults
|
||||
* to an empty string, but can be set to NULL for the attribute to be
|
||||
* omitted. Usually, neither omission nor an empty string satisfies
|
||||
* accessibility requirements, so it is strongly encouraged for code calling
|
||||
* theme('image') to pass a meaningful value for this variable.
|
||||
* accessibility requirements, so it is strongly encouraged for code
|
||||
* calling theme('image') to pass a meaningful value for this variable.
|
||||
* - http://www.w3.org/TR/REC-html40/struct/objects.html#h-13.8
|
||||
* - http://www.w3.org/TR/xhtml1/dtds.html
|
||||
* - http://dev.w3.org/html5/spec/Overview.html#alt
|
||||
@@ -1801,7 +1826,9 @@ function theme_breadcrumb($variables) {
|
||||
* - "data": The localized title of the table column.
|
||||
* - "field": The database field represented in the table column (required
|
||||
* if user is to be able to sort on this column).
|
||||
* - "sort": A default sort order for this column ("asc" or "desc").
|
||||
* - "sort": A default sort order for this column ("asc" or "desc"). Only
|
||||
* one column should be given a default sort order because table sorting
|
||||
* only applies to one column at a time.
|
||||
* - Any HTML attributes, such as "colspan", to apply to the column header
|
||||
* cell.
|
||||
* - rows: An array of table rows. Every row is an array of cells, or an
|
||||
@@ -1960,25 +1987,24 @@ function theme_table($variables) {
|
||||
$flip = array('even' => 'odd', 'odd' => 'even');
|
||||
$class = 'even';
|
||||
foreach ($rows as $number => $row) {
|
||||
$attributes = array();
|
||||
|
||||
// Check if we're dealing with a simple or complex row
|
||||
if (isset($row['data'])) {
|
||||
foreach ($row as $key => $value) {
|
||||
if ($key == 'data') {
|
||||
$cells = $value;
|
||||
}
|
||||
else {
|
||||
$attributes[$key] = $value;
|
||||
}
|
||||
}
|
||||
$cells = $row['data'];
|
||||
$no_striping = isset($row['no_striping']) ? $row['no_striping'] : FALSE;
|
||||
|
||||
// Set the attributes array and exclude 'data' and 'no_striping'.
|
||||
$attributes = $row;
|
||||
unset($attributes['data']);
|
||||
unset($attributes['no_striping']);
|
||||
}
|
||||
else {
|
||||
$cells = $row;
|
||||
$attributes = array();
|
||||
$no_striping = FALSE;
|
||||
}
|
||||
if (count($cells)) {
|
||||
// Add odd/even class
|
||||
if (empty($row['no_striping'])) {
|
||||
if (!$no_striping) {
|
||||
$class = $flip[$class];
|
||||
$attributes['class'][] = $class;
|
||||
}
|
||||
@@ -2005,7 +2031,8 @@ function theme_table($variables) {
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
* - style: Set to either 'asc' or 'desc', this determines which icon to show.
|
||||
* - style: Set to either 'asc' or 'desc', this determines which icon to
|
||||
* show.
|
||||
*/
|
||||
function theme_tablesort_indicator($variables) {
|
||||
if ($variables['style'] == "asc") {
|
||||
@@ -2148,7 +2175,8 @@ function theme_feed_icon($variables) {
|
||||
* - script: To load JavaScript.
|
||||
* - #attributes: (optional) An array of HTML attributes to apply to the
|
||||
* tag.
|
||||
* - #value: (optional) A string containing tag content, such as inline CSS.
|
||||
* - #value: (optional) A string containing tag content, such as inline
|
||||
* CSS.
|
||||
* - #value_prefix: (optional) A string to prepend to #value, e.g. a CDATA
|
||||
* wrapper prefix.
|
||||
* - #value_suffix: (optional) A string to append to #value, e.g. a CDATA
|
||||
@@ -2316,8 +2344,9 @@ function template_preprocess(&$variables, $hook) {
|
||||
global $user;
|
||||
static $count = array();
|
||||
|
||||
// Track run count for each hook to provide zebra striping.
|
||||
// See "template_preprocess_block()" which provides the same feature specific to blocks.
|
||||
// Track run count for each hook to provide zebra striping. See
|
||||
// "template_preprocess_block()" which provides the same feature specific to
|
||||
// blocks.
|
||||
$count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1;
|
||||
$variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even';
|
||||
$variables['id'] = $count[$hook]++;
|
||||
@@ -2677,13 +2706,13 @@ function theme_get_suggestions($args, $base, $delimiter = '__') {
|
||||
}
|
||||
|
||||
/**
|
||||
* The variables array generated here is a mirror of template_preprocess_page().
|
||||
* This preprocessor will run its course when theme_maintenance_page() is
|
||||
* invoked.
|
||||
* Process variables for maintenance-page.tpl.php.
|
||||
*
|
||||
* An alternate template file of "maintenance-page--offline.tpl.php" can be
|
||||
* used when the database is offline to hide errors and completely replace the
|
||||
* content.
|
||||
* The variables array generated here is a mirror of
|
||||
* template_preprocess_page(). This preprocessor will run its course when
|
||||
* theme_maintenance_page() is invoked. An alternate template file of
|
||||
* maintenance-page--offline.tpl.php can be used when the database is offline to
|
||||
* hide errors and completely replace the content.
|
||||
*
|
||||
* The $variables array contains the following arguments:
|
||||
* - $content
|
||||
@@ -2777,10 +2806,13 @@ function template_preprocess_maintenance_page(&$variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme process function for theme_maintenance_field().
|
||||
*
|
||||
* The variables array generated here is a mirror of template_process_html().
|
||||
* This processor will run its course when theme_maintenance_page() is invoked.
|
||||
*
|
||||
* @see maintenance-page.tpl.php
|
||||
* @see template_process_html()
|
||||
*/
|
||||
function template_process_maintenance_page(&$variables) {
|
||||
$variables['head'] = drupal_get_html_head();
|
||||
@@ -2792,7 +2824,7 @@ function template_process_maintenance_page(&$variables) {
|
||||
/**
|
||||
* Preprocess variables for region.tpl.php
|
||||
*
|
||||
* Prepare the values passed to the theme_region function to be passed into a
|
||||
* Prepares the values passed to the theme_region function to be passed into a
|
||||
* pluggable template engine. Uses the region name to generate a template file
|
||||
* suggestions. If none are found, the default region.tpl.php is used.
|
||||
*
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
*
|
||||
* Used for site installs, updates and when the site is in maintenance mode.
|
||||
* It also applies when the database is unavailable or bootstrap was not
|
||||
* complete. Seven is always used for the initial install and update operations.
|
||||
* In other cases, Bartik is used, but this can be overridden by setting a
|
||||
* "maintenance_theme" key in the $conf variable in settings.php.
|
||||
* complete. Seven is always used for the initial install and update
|
||||
* operations. In other cases, Bartik is used, but this can be overridden by
|
||||
* setting a "maintenance_theme" key in the $conf variable in settings.php.
|
||||
*/
|
||||
function _drupal_maintenance_theme() {
|
||||
global $theme, $theme_key, $conf;
|
||||
@@ -85,7 +85,7 @@ function _drupal_maintenance_theme() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This builds the registry when the site needs to bypass any database calls.
|
||||
* Builds the registry when the site needs to bypass any database calls.
|
||||
*/
|
||||
function _theme_load_offline_registry($theme, $base_theme = NULL, $theme_engine = NULL) {
|
||||
return _theme_build_registry($theme, $base_theme, $theme_engine);
|
||||
@@ -160,7 +160,7 @@ function theme_update_page($variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for a report of the results from an operation run via authorize.php.
|
||||
* Returns HTML for a results report of an operation run by authorize.php.
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
|
||||
@@ -113,13 +113,13 @@ function token_replace($text, array $data = array(), array $options = array()) {
|
||||
*/
|
||||
function token_scan($text) {
|
||||
// Matches tokens with the following pattern: [$type:$name]
|
||||
// $type and $name may not contain [ ] or whitespace characters.
|
||||
// $type may not contain : characters, but $name may.
|
||||
// $type and $name may not contain [ ] characters.
|
||||
// $type may not contain : or whitespace characters, but $name may.
|
||||
preg_match_all('/
|
||||
\[ # [ - pattern start
|
||||
([^\s\[\]:]*) # match $type not containing whitespace : [ or ]
|
||||
: # : - separator
|
||||
([^\s\[\]]*) # match $name not containing whitespace [ or ]
|
||||
([^\[\]]*) # match $name not containing [ or ]
|
||||
\] # ] - pattern end
|
||||
/x', $text, $matches);
|
||||
|
||||
@@ -190,10 +190,10 @@ function token_generate($type, array $tokens, array $data = array(), array $opti
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of tokens, returns those that begin with a specific prefix.
|
||||
* Returns a list of tokens that begin with a specific prefix.
|
||||
*
|
||||
* Used to extract a group of 'chained' tokens (such as [node:author:name]) from
|
||||
* the full list of tokens found in text. For example:
|
||||
* Used to extract a group of 'chained' tokens (such as [node:author:name])
|
||||
* from the full list of tokens found in text. For example:
|
||||
* @code
|
||||
* $data = array(
|
||||
* 'author:name' => '[node:author:name]',
|
||||
@@ -230,8 +230,10 @@ function token_find_with_prefix(array $tokens, $prefix, $delimiter = ':') {
|
||||
/**
|
||||
* Returns metadata describing supported tokens.
|
||||
*
|
||||
* The metadata array contains token type, name, and description data as well as
|
||||
* an optional pointer indicating that the token chains to another set of tokens.
|
||||
* The metadata array contains token type, name, and description data as well
|
||||
* as an optional pointer indicating that the token chains to another set of
|
||||
* tokens.
|
||||
*
|
||||
* For example:
|
||||
* @code
|
||||
* $data['types']['node'] = array(
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides Unicode-related conversions and operations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Indicates an error during check for PHP unicode support.
|
||||
*/
|
||||
@@ -19,8 +24,6 @@ define('UNICODE_MULTIBYTE', 1);
|
||||
/**
|
||||
* Matches Unicode characters that are word boundaries.
|
||||
*
|
||||
* @see http://unicode.org/glossary
|
||||
*
|
||||
* Characters with the following General_category (gc) property values are used
|
||||
* as word boundaries. While this does not fully conform to the Word Boundaries
|
||||
* algorithm described in http://unicode.org/reports/tr29, as PCRE does not
|
||||
@@ -39,6 +42,8 @@ define('UNICODE_MULTIBYTE', 1);
|
||||
* Note that the PCRE property matcher is not used because we wanted to be
|
||||
* compatible with Unicode 5.2.0 regardless of the PCRE version used (and any
|
||||
* bugs in PCRE property tables).
|
||||
*
|
||||
* @see http://unicode.org/glossary
|
||||
*/
|
||||
define('PREG_CLASS_UNICODE_WORD_BOUNDARY',
|
||||
'\x{0}-\x{2F}\x{3A}-\x{40}\x{5B}-\x{60}\x{7B}-\x{A9}\x{AB}-\x{B1}\x{B4}' .
|
||||
@@ -125,7 +130,7 @@ function _unicode_check() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Unicode library status and errors.
|
||||
* Returns Unicode library status and errors.
|
||||
*/
|
||||
function unicode_requirements() {
|
||||
// Ensure translations don't break during installation.
|
||||
@@ -157,14 +162,14 @@ function unicode_requirements() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a new XML parser.
|
||||
* Prepares a new XML parser.
|
||||
*
|
||||
* This is a wrapper around xml_parser_create() which extracts the encoding from
|
||||
* the XML data first and sets the output encoding to UTF-8. This function should
|
||||
* be used instead of xml_parser_create(), because PHP 4's XML parser doesn't
|
||||
* check the input encoding itself. "Starting from PHP 5, the input encoding is
|
||||
* automatically detected, so that the encoding parameter specifies only the
|
||||
* output encoding."
|
||||
* This is a wrapper around xml_parser_create() which extracts the encoding
|
||||
* from the XML data first and sets the output encoding to UTF-8. This function
|
||||
* should be used instead of xml_parser_create(), because PHP 4's XML parser
|
||||
* doesn't check the input encoding itself. "Starting from PHP 5, the input
|
||||
* encoding is automatically detected, so that the encoding parameter specifies
|
||||
* only the output encoding."
|
||||
*
|
||||
* This is also where unsupported encodings will be converted. Callers should
|
||||
* take this into account: $data might have been changed after the call.
|
||||
@@ -213,7 +218,7 @@ function drupal_xml_parser_create(&$data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert data to UTF-8
|
||||
* Converts data to UTF-8.
|
||||
*
|
||||
* Requires the iconv, GNU recode or mbstring PHP extension.
|
||||
*
|
||||
@@ -244,15 +249,15 @@ function drupal_convert_to_utf8($data, $encoding) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate a UTF-8-encoded string safely to a number of bytes.
|
||||
* Truncates a UTF-8-encoded string safely to a number of bytes.
|
||||
*
|
||||
* If the end position is in the middle of a UTF-8 sequence, it scans backwards
|
||||
* until the beginning of the byte sequence.
|
||||
*
|
||||
* Use this function whenever you want to chop off a string at an unsure
|
||||
* location. On the other hand, if you're sure that you're splitting on a
|
||||
* character boundary (e.g. after using strpos() or similar), you can safely use
|
||||
* substr() instead.
|
||||
* character boundary (e.g. after using strpos() or similar), you can safely
|
||||
* use substr() instead.
|
||||
*
|
||||
* @param $string
|
||||
* The string to truncate.
|
||||
@@ -306,7 +311,7 @@ function drupal_truncate_bytes($string, $len) {
|
||||
* boundaries, giving you "See myverylongurl..." (assuming you had set
|
||||
* $add_ellipses to TRUE).
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* The truncated string.
|
||||
*/
|
||||
function truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis = FALSE, $min_wordsafe_length = 1) {
|
||||
@@ -356,8 +361,7 @@ function truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis =
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes MIME/HTTP header values that contain non-ASCII, UTF-8 encoded
|
||||
* characters.
|
||||
* Encodes MIME/HTTP header values that contain incorrectly encoded characters.
|
||||
*
|
||||
* For example, mime_header_encode('tést.txt') returns "=?UTF-8?B?dMOpc3QudHh0?=".
|
||||
*
|
||||
@@ -369,6 +373,14 @@ function truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis =
|
||||
* each chunk starts and ends on a character boundary.
|
||||
* - Using \n as the chunk separator may cause problems on some systems and may
|
||||
* have to be changed to \r\n or \r.
|
||||
*
|
||||
* @param $string
|
||||
* The header to encode.
|
||||
*
|
||||
* @return string
|
||||
* The mime-encoded header.
|
||||
*
|
||||
* @see mime_header_decode()
|
||||
*/
|
||||
function mime_header_encode($string) {
|
||||
if (preg_match('/[^\x20-\x7E]/', $string)) {
|
||||
@@ -388,7 +400,15 @@ function mime_header_encode($string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Complement to mime_header_encode
|
||||
* Decodes MIME/HTTP encoded header values.
|
||||
*
|
||||
* @param $header
|
||||
* The header to decode.
|
||||
*
|
||||
* @return string
|
||||
* The mime-decoded header.
|
||||
*
|
||||
* @see mime_header_encode()
|
||||
*/
|
||||
function mime_header_decode($header) {
|
||||
// First step: encoded chunks followed by other encoded chunks (need to collapse whitespace)
|
||||
@@ -398,7 +418,17 @@ function mime_header_decode($header) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to mime_header_decode
|
||||
* Decodes encoded header data passed from mime_header_decode().
|
||||
*
|
||||
* Callback for preg_replace_callback() within mime_header_decode().
|
||||
*
|
||||
* @param $matches
|
||||
* The array of matches from preg_replace_callback().
|
||||
*
|
||||
* @return string
|
||||
* The mime-decoded string.
|
||||
*
|
||||
* @see mime_header_decode()
|
||||
*/
|
||||
function _mime_header_decode($matches) {
|
||||
// Regexp groups:
|
||||
@@ -415,9 +445,9 @@ function _mime_header_decode($matches) {
|
||||
/**
|
||||
* Decodes all HTML entities (including numerical ones) to regular UTF-8 bytes.
|
||||
*
|
||||
* Double-escaped entities will only be decoded once ("&lt;" becomes "<",
|
||||
* not "<"). Be careful when using this function, as decode_entities can revert
|
||||
* previous sanitization efforts (<script> will become <script>).
|
||||
* Double-escaped entities will only be decoded once ("&lt;" becomes "<"
|
||||
* , not "<"). Be careful when using this function, as decode_entities can
|
||||
* revert previous sanitization efforts (<script> will become <script>).
|
||||
*
|
||||
* @param $text
|
||||
* The text to decode entities in.
|
||||
@@ -430,8 +460,15 @@ function decode_entities($text) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the amount of characters in a UTF-8 string. This is less than or
|
||||
* equal to the byte count.
|
||||
* Counts the number of characters in a UTF-8 string.
|
||||
*
|
||||
* This is less than or equal to the byte count.
|
||||
*
|
||||
* @param $text
|
||||
* The string to run the operation on.
|
||||
*
|
||||
* @return integer
|
||||
* The length of the string.
|
||||
*
|
||||
* @ingroup php_wrappers
|
||||
*/
|
||||
@@ -449,6 +486,12 @@ function drupal_strlen($text) {
|
||||
/**
|
||||
* Uppercase a UTF-8 string.
|
||||
*
|
||||
* @param $text
|
||||
* The string to run the operation on.
|
||||
*
|
||||
* @return string
|
||||
* The string in uppercase.
|
||||
*
|
||||
* @ingroup php_wrappers
|
||||
*/
|
||||
function drupal_strtoupper($text) {
|
||||
@@ -468,6 +511,12 @@ function drupal_strtoupper($text) {
|
||||
/**
|
||||
* Lowercase a UTF-8 string.
|
||||
*
|
||||
* @param $text
|
||||
* The string to run the operation on.
|
||||
*
|
||||
* @return string
|
||||
* The string in lowercase.
|
||||
*
|
||||
* @ingroup php_wrappers
|
||||
*/
|
||||
function drupal_strtolower($text) {
|
||||
@@ -485,15 +534,28 @@ function drupal_strtolower($text) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for case conversion of Latin-1.
|
||||
* Used for flipping U+C0-U+DE to U+E0-U+FD and back.
|
||||
* Flips U+C0-U+DE to U+E0-U+FD and back.
|
||||
*
|
||||
* @param $matches
|
||||
* An array of matches.
|
||||
*
|
||||
* @return array
|
||||
* The Latin-1 version of the array of matches.
|
||||
*
|
||||
* @see drupal_strtolower()
|
||||
*/
|
||||
function _unicode_caseflip($matches) {
|
||||
return $matches[0][0] . chr(ord($matches[0][1]) ^ 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Capitalize the first letter of a UTF-8 string.
|
||||
* Capitalizes the first letter of a UTF-8 string.
|
||||
*
|
||||
* @param $text
|
||||
* The string to convert.
|
||||
*
|
||||
* @return
|
||||
* The string with the first letter as uppercase.
|
||||
*
|
||||
* @ingroup php_wrappers
|
||||
*/
|
||||
@@ -503,12 +565,21 @@ function drupal_ucfirst($text) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cut off a piece of a string based on character indices and counts. Follows
|
||||
* the same behavior as PHP's own substr() function.
|
||||
* Cuts off a piece of a string based on character indices and counts.
|
||||
*
|
||||
* Note that for cutting off a string at a known character/substring
|
||||
* location, the usage of PHP's normal strpos/substr is safe and
|
||||
* much faster.
|
||||
* Follows the same behavior as PHP's own substr() function. Note that for
|
||||
* cutting off a string at a known character/substring location, the usage of
|
||||
* PHP's normal strpos/substr is safe and much faster.
|
||||
*
|
||||
* @param $text
|
||||
* The input string.
|
||||
* @param $start
|
||||
* The position at which to start reading.
|
||||
* @param $length
|
||||
* The number of characters to read.
|
||||
*
|
||||
* @return
|
||||
* The shortened string.
|
||||
*
|
||||
* @ingroup php_wrappers
|
||||
*/
|
||||
|
||||
@@ -38,7 +38,7 @@ function update_fix_compatibility() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to test compatibility of a module or theme.
|
||||
* Tests the compatibility of a module or theme.
|
||||
*/
|
||||
function update_check_incompatibility($name, $type = 'module') {
|
||||
static $themes, $modules;
|
||||
@@ -908,7 +908,7 @@ function update_get_d6_session_name() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform one update and store the results for display on finished page.
|
||||
* Performs one update and stores the results for display on the results page.
|
||||
*
|
||||
* If an update function completes successfully, it should return a message
|
||||
* as a string indicating success, for example:
|
||||
@@ -1008,7 +1008,7 @@ function update_do_one($module, $number, $dependency_map, &$context) {
|
||||
class DrupalUpdateException extends Exception { }
|
||||
|
||||
/**
|
||||
* Start the database update batch process.
|
||||
* Starts the database update batch process.
|
||||
*
|
||||
* @param $start
|
||||
* An array whose keys contain the names of modules to be updated during the
|
||||
@@ -1078,7 +1078,7 @@ function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the update process and store results for eventual display.
|
||||
* Finishes the update process and stores the results for eventual display.
|
||||
*
|
||||
* After the updates run, all caches are flushed. The update results are
|
||||
* stored into the session (for example, to be displayed on the update results
|
||||
@@ -1115,7 +1115,7 @@ function update_finished($success, $results, $operations) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all the pending database updates.
|
||||
* Returns a list of all the pending database updates.
|
||||
*
|
||||
* @return
|
||||
* An associative array keyed by module name which contains all information
|
||||
@@ -1409,7 +1409,7 @@ function update_already_performed($module, $number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke hook_update_dependencies() in all installed modules.
|
||||
* Invokes hook_update_dependencies() in all installed modules.
|
||||
*
|
||||
* This function is similar to module_invoke_all(), with the main difference
|
||||
* that it does not require that a module be enabled to invoke its hook, only
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
* The variable to export.
|
||||
* @param $prefix
|
||||
* A prefix that will be added at the beginning of every lines of the output.
|
||||
*
|
||||
* @return
|
||||
* The variable exported in a way compatible to Drupal's coding standards.
|
||||
*/
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Initiates a browser-based installation of Drupal.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Root directory of Drupal installation.
|
||||
*/
|
||||
define('DRUPAL_ROOT', getcwd());
|
||||
|
||||
/**
|
||||
* Global flag to indicate that 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,81 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en" dir="ltr" > <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en" dir="ltr" > <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en" dir="ltr" > <![endif]-->
|
||||
<!-- Consider adding an manifest.appcache: h5bp.com/d/Offline -->
|
||||
<!--[if gt IE 8]><!-->
|
||||
<html class="js no-flexbox canvas canvastext webgl no-touch geolocation postmessage no-websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients no-cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths" dir="ltr" lang="en"><!--<![endif]-->
|
||||
<head>
|
||||
|
||||
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
|
||||
Remove this if you use the .htaccess -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
|
||||
<link type="image/png" rel="shortcut icon" href="http://www.materio.com/sites/all/themes/gui/materiobasetheme/materio-icon-O.png">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="alternate" type="application/rss+xml" title="Materio's news" href="http://www.materio.com/en/rss/feed">
|
||||
|
||||
<title>Site under maintenance | materiO’</title>
|
||||
<style type="text/css" media="all">
|
||||
@import url("http://www.materio.com/modules/system/system.base.css?mu8p7n");
|
||||
@import url("http://www.materio.com/modules/system/system.menus.css?mu8p7n");
|
||||
@import url("http://www.materio.com/modules/system/system.theme.css?mu8p7n");
|
||||
</style>
|
||||
<style type="text/css" media="all">
|
||||
@import url("http://www.materio.com/sites/all/modules/contrib/mail/simplenews/simplenews.css?mu8p7n");
|
||||
@import url("http://www.materio.com/modules/field/theme/field.css?mu8p7n");
|
||||
@import url("http://www.materio.com/modules/node/node.css?mu8p7n");
|
||||
</style>
|
||||
<style type="text/css" media="all">
|
||||
@import url("http://www.materio.com/sites/all/modules/contrib/theming/extlink/extlink.css?mu8p7n");
|
||||
</style>
|
||||
<style type="text/css" media="all">
|
||||
@import url("http://www.materio.com/sites/all/themes/gui/materiobasetheme/css/normalize.css?mu8p7n");
|
||||
@import url("http://www.materio.com/sites/all/themes/gui/materiobasetheme/fonts/ubuntu/ubuntu.css?mu8p7n");
|
||||
@import url("http://www.materio.com/sites/all/themes/gui/materiobasetheme/css/styles.css?mu8p7n");
|
||||
@import url("http://www.materio.com/sites/all/themes/gui/materiobasetheme/css/nonsemantic.css?mu8p7n");
|
||||
</style>
|
||||
|
||||
|
||||
<!-- All JavaScript at the bottom, except for Modernizr / Respond.
|
||||
|
||||
|
||||
<!--[if lt IE 9]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
|
||||
</head>
|
||||
|
||||
<body class="maintenance-page in-maintenance no-sidebars">
|
||||
<div id="root">
|
||||
|
||||
<div id="container">
|
||||
|
||||
<header id="header">
|
||||
<h1 class="site-name">materiO’</h1>
|
||||
<h2 class="site-slogan">l'inspiration par la matière </h2>
|
||||
</header>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<section id="center">
|
||||
|
||||
<section id="content">
|
||||
<div class="inner-content">
|
||||
<h3 class="page-title">Site under maintenance</h3> <p>materiO' is currently working hard to make a better service for you !<br>We should be back shortly.<br>Thank you for your patience.</p>
|
||||
<img src="index_files/maintenance.jpg">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</section> <!-- /center -->
|
||||
|
||||
</div><!-- /main -->
|
||||
|
||||
<div id="footer"></div>
|
||||
|
||||
</div>
|
||||
<!-- /container -->
|
||||
|
||||
</div>
|
||||
<!-- /root -->
|
||||
|
||||
|
||||
<div style="display: none;" id="cboxOverlay"></div><div style="display: none;" tabindex="-1" role="dialog" class="" id="colorbox"><div id="cboxWrapper"><div><div style="float: left;" id="cboxTopLeft"></div><div style="float: left;" id="cboxTopCenter"></div><div style="float: left;" id="cboxTopRight"></div></div><div style="clear: left;"><div style="float: left;" id="cboxMiddleLeft"></div><div style="float: left;" id="cboxContent"><div style="float: left;" id="cboxTitle"></div><div style="float: left;" id="cboxCurrent"></div><button id="cboxPrevious" type="button"></button><button id="cboxNext" type="button"></button><button id="cboxSlideshow"></button><div style="float: left;" id="cboxLoadingOverlay"></div><div style="float: left;" id="cboxLoadingGraphic"></div><button id="cboxClose" type="button"></button></div><div style="float: left;" id="cboxMiddleRight"></div></div><div style="clear: left;"><div style="float: left;" id="cboxBottomLeft"></div><div style="float: left;" id="cboxBottomCenter"></div><div style="float: left;" id="cboxBottomRight"></div></div></div><div style="position: absolute; width: 9999px; visibility: hidden; display: none;"></div></div></body></html>
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -396,7 +396,7 @@ Drupal.ajax.prototype.success = function (response, status) {
|
||||
Drupal.freezeHeight();
|
||||
|
||||
for (var i in response) {
|
||||
if (response[i]['command'] && this.commands[response[i]['command']]) {
|
||||
if (response.hasOwnProperty(i) && response[i]['command'] && this.commands[response[i]['command']]) {
|
||||
this.commands[response[i]['command']](this, response[i], status);
|
||||
}
|
||||
}
|
||||
@@ -616,6 +616,13 @@ Drupal.ajax.prototype.commands = {
|
||||
.removeClass('odd even')
|
||||
.filter(':even').addClass('odd').end()
|
||||
.filter(':odd').addClass('even');
|
||||
},
|
||||
|
||||
/**
|
||||
* Command to update a form's build ID.
|
||||
*/
|
||||
updateBuildId: function(ajax, response, status) {
|
||||
$('input[name="form_build_id"][value="' + response['old'] + '"]').val(response['new']);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 118 B |
@@ -114,6 +114,7 @@ Drupal.jsAC.prototype.onkeyup = function (input, e) {
|
||||
*/
|
||||
Drupal.jsAC.prototype.select = function (node) {
|
||||
this.input.value = $(node).data('autocompleteValue');
|
||||
$(this.input).trigger('autocompleteSelect', [node]);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -167,7 +168,7 @@ Drupal.jsAC.prototype.unhighlight = function (node) {
|
||||
Drupal.jsAC.prototype.hidePopup = function (keycode) {
|
||||
// Select item if the right key or mousebutton was pressed.
|
||||
if (this.selected && ((keycode && keycode != 46 && keycode != 8 && keycode != 27) || !keycode)) {
|
||||
this.input.value = $(this.selected).data('autocompleteValue');
|
||||
this.select(this.selected);
|
||||
}
|
||||
// Hide popup.
|
||||
var popup = this.popup;
|
||||
@@ -220,7 +221,7 @@ Drupal.jsAC.prototype.found = function (matches) {
|
||||
for (key in matches) {
|
||||
$('<li></li>')
|
||||
.html($('<div></div>').html(matches[key]))
|
||||
.mousedown(function () { ac.select(this); })
|
||||
.mousedown(function () { ac.hidePopup(this); })
|
||||
.mouseover(function () { ac.highlight(this); })
|
||||
.mouseout(function () { ac.unhighlight(this); })
|
||||
.data('autocompleteValue', key)
|
||||
|
||||
|
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
|
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 268 B |