Merge branch '8.x-file-config' of git.drupal.org:sandbox/heyrocker/1145636 into 8.x-file-config
commit
e010dd66d6
|
@ -10,6 +10,7 @@ Drupal 8.0, xxxx-xx-xx (development version)
|
|||
modules with similar functionality are available:
|
||||
* Blog
|
||||
* Profile
|
||||
* Trigger
|
||||
- Removed the Garland theme from core.
|
||||
- Universally Unique IDentifier (UUID):
|
||||
* Support for generating and validating UUIDs.
|
||||
|
|
|
@ -18,7 +18,7 @@ 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 following command:
|
||||
prompt, enter the following command:
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER
|
||||
ON databasename.*
|
||||
|
|
|
@ -6,7 +6,7 @@ Branch maintainers
|
|||
------------------
|
||||
|
||||
The Drupal Core branch maintainers oversee the development of Drupal as a
|
||||
whole. The branch mainainers for Drupal 8 are:
|
||||
whole. The branch maintainers for Drupal 8 are:
|
||||
|
||||
- Dries Buytaert 'dries' <http://drupal.org/user/1>
|
||||
- Nathaniel Catchpole 'catch' <http://drupal.org/user/35733>
|
||||
|
@ -36,6 +36,7 @@ Batch system
|
|||
Cache system
|
||||
- Damien Tournoud 'DamZ' <http://drupal.org/user/22211>
|
||||
- Nathaniel Catchpole 'catch' <http://drupal.org/user/35733>
|
||||
- Mark Sonnabaum 'msonnabaum' <http://drupal.org/user/75278>
|
||||
|
||||
Cron system
|
||||
- Károly Négyesi 'chx' <http://drupal.org/user/9446>
|
||||
|
@ -133,7 +134,6 @@ Accessibility
|
|||
- Brandon Bowersox 'brandonojc' <http://drupal.org/user/186415>
|
||||
|
||||
Documentation
|
||||
- Ariane Khachatourians 'arianek' <http://drupal.org/user/158886>
|
||||
- Jennifer Hodgdon 'jhodgdon' <http://drupal.org/user/155601>
|
||||
|
||||
Security
|
||||
|
@ -264,9 +264,6 @@ Tracker module
|
|||
Translation module
|
||||
- Francesco Placella 'plach' <http://drupal.org/user/183211>
|
||||
|
||||
Trigger module
|
||||
- ?
|
||||
|
||||
Update module
|
||||
- Derek Wright 'dww' <http://drupal.org/user/46549>
|
||||
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of CacheBackendInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Cache;
|
||||
|
||||
/**
|
||||
* Defines an interface for cache implementations.
|
||||
*
|
||||
* All cache implementations have to implement this interface.
|
||||
* DrupalDatabaseCache provides the default implementation, which can be
|
||||
* consulted as an example.
|
||||
*
|
||||
* To make Drupal use your implementation for a certain cache bin, you have to
|
||||
* set a variable with the name of the cache bin as its key and the name of
|
||||
* your class as its value. For example, if your implementation of
|
||||
* DrupalCacheInterface was called MyCustomCache, the following line would make
|
||||
* Drupal use it for the 'cache_page' bin:
|
||||
* @code
|
||||
* variable_set('cache_class_cache_page', 'MyCustomCache');
|
||||
* @endcode
|
||||
*
|
||||
* Additionally, you can register your cache implementation to be used by
|
||||
* default for all cache bins by setting the variable 'cache_default_class' to
|
||||
* the name of your implementation of the DrupalCacheInterface, e.g.
|
||||
* @code
|
||||
* variable_set('cache_default_class', 'MyCustomCache');
|
||||
* @endcode
|
||||
*
|
||||
* To implement a completely custom cache bin, use the same variable format:
|
||||
* @code
|
||||
* variable_set('cache_class_custom_bin', 'MyCustomCache');
|
||||
* @endcode
|
||||
* To access your custom cache bin, specify the name of the bin when storing
|
||||
* or retrieving cached data:
|
||||
* @code
|
||||
* cache_set($cid, $data, 'custom_bin', $expire);
|
||||
* cache_get($cid, 'custom_bin');
|
||||
* @endcode
|
||||
*
|
||||
* @see cache()
|
||||
* @see DrupalDatabaseCache
|
||||
*/
|
||||
interface CacheBackendInterface {
|
||||
|
||||
/**
|
||||
* Constructs a new cache backend.
|
||||
*
|
||||
* @param $bin
|
||||
* The cache bin for which the object is created.
|
||||
*/
|
||||
function __construct($bin);
|
||||
|
||||
/**
|
||||
* Returns data from the persistent cache.
|
||||
*
|
||||
* Data may be stored as either plain text or as serialized data. cache_get()
|
||||
* will automatically return unserialized objects and arrays.
|
||||
*
|
||||
* @param $cid
|
||||
* The cache ID of the data to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The cache or FALSE on failure.
|
||||
*/
|
||||
function get($cid);
|
||||
|
||||
/**
|
||||
* Returns data from the persistent cache when given an array of cache IDs.
|
||||
*
|
||||
* @param $cids
|
||||
* An array of cache IDs for the data to retrieve. This is passed by
|
||||
* reference, and will have the IDs successfully returned from cache
|
||||
* removed.
|
||||
*
|
||||
* @return
|
||||
* An array of the items successfully returned from cache indexed by cid.
|
||||
*/
|
||||
function getMultiple(&$cids);
|
||||
|
||||
/**
|
||||
* Stores data in the persistent cache.
|
||||
*
|
||||
* @param $cid
|
||||
* 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.
|
||||
* @param $expire
|
||||
* One of the following values:
|
||||
* - CACHE_PERMANENT: Indicates that the item should never be removed unless
|
||||
* explicitly told to using cache_clear_all() with a cache ID.
|
||||
* - CACHE_TEMPORARY: Indicates that the item should be removed at the next
|
||||
* general cache wipe.
|
||||
* - A Unix timestamp: Indicates that the item should be kept at least until
|
||||
* the given time, after which it behaves like CACHE_TEMPORARY.
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT);
|
||||
|
||||
/**
|
||||
* Deletes an item from the cache.
|
||||
*
|
||||
* @param $cid
|
||||
* The cache ID to delete.
|
||||
*/
|
||||
function delete($cid);
|
||||
|
||||
/**
|
||||
* Deletes multiple items from the cache.
|
||||
*
|
||||
* @param $cids
|
||||
* An array of $cids to delete.
|
||||
*/
|
||||
function deleteMultiple(Array $cids);
|
||||
|
||||
/**
|
||||
* Deletes items from the cache using a wildcard prefix.
|
||||
*
|
||||
* @param $prefix
|
||||
* A wildcard prefix.
|
||||
*/
|
||||
function deletePrefix($prefix);
|
||||
|
||||
/**
|
||||
* Flushes all cache items in a bin.
|
||||
*/
|
||||
function flush();
|
||||
|
||||
/**
|
||||
* Expires temporary items from the cache.
|
||||
*/
|
||||
function expire();
|
||||
|
||||
/**
|
||||
* Performs garbage collection on a cache bin.
|
||||
*/
|
||||
function garbageCollection();
|
||||
|
||||
/**
|
||||
* Checks if a cache bin is empty.
|
||||
*
|
||||
* A cache bin is considered empty if it does not contain any valid data for
|
||||
* any cache ID.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the cache bin specified is empty.
|
||||
*/
|
||||
function isEmpty();
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of DatabaseBackend.
|
||||
*/
|
||||
|
||||
namespace Drupal\Cache;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Defines a default cache implementation.
|
||||
*
|
||||
* This is Drupal's default cache implementation. It uses the database to store
|
||||
* cached data. Each cache bin corresponds to a database table by the same name.
|
||||
*/
|
||||
class DatabaseBackend implements CacheBackendInterface {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $bin;
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::__construct().
|
||||
*/
|
||||
function __construct($bin) {
|
||||
// All cache tables should be prefixed with 'cache_', except for the
|
||||
// default 'cache' bin.
|
||||
if ($bin != 'cache') {
|
||||
$bin = 'cache_' . $bin;
|
||||
}
|
||||
$this->bin = $bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::get().
|
||||
*/
|
||||
function get($cid) {
|
||||
$cids = array($cid);
|
||||
$cache = $this->getMultiple($cids);
|
||||
return reset($cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::getMultiple().
|
||||
*/
|
||||
function getMultiple(&$cids) {
|
||||
try {
|
||||
// Garbage collection necessary when enforcing a minimum cache lifetime.
|
||||
$this->garbageCollection($this->bin);
|
||||
|
||||
// When serving cached pages, the overhead of using db_select() was found
|
||||
// to add around 30% overhead to the request. Since $this->bin is a
|
||||
// variable, this means the call to db_query() here uses a concatenated
|
||||
// string. This is highly discouraged under any other circumstances, and
|
||||
// is used here only due to the performance overhead we would incur
|
||||
// otherwise. When serving an uncached page, the overhead of using
|
||||
// db_select() is a much smaller proportion of the request.
|
||||
$result = db_query('SELECT cid, data, created, expire, serialized FROM {' . db_escape_table($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
|
||||
$cache = array();
|
||||
foreach ($result as $item) {
|
||||
$item = $this->prepareItem($item);
|
||||
if ($item) {
|
||||
$cache[$item->cid] = $item;
|
||||
}
|
||||
}
|
||||
$cids = array_diff($cids, array_keys($cache));
|
||||
return $cache;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// If the database is never going to be available, cache requests should
|
||||
// return FALSE in order to allow exception handling to occur.
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a cached item.
|
||||
*
|
||||
* Checks that items are either permanent or did not expire, and unserializes
|
||||
* data as appropriate.
|
||||
*
|
||||
* @param stdClass $cache
|
||||
* An item loaded from cache_get() or cache_get_multiple().
|
||||
*
|
||||
* @return mixed
|
||||
* The item with data unserialized as appropriate or FALSE if there is no
|
||||
* valid item to load.
|
||||
*/
|
||||
protected function prepareItem($cache) {
|
||||
global $user;
|
||||
|
||||
if (!isset($cache->data)) {
|
||||
return FALSE;
|
||||
}
|
||||
// If enforcing a minimum cache lifetime, validate that the data is
|
||||
// currently valid for this user before we return it by making sure the cache
|
||||
// entry was created before the timestamp in the current session's cache
|
||||
// timer. The cache variable is loaded into the $user object by
|
||||
// _drupal_session_read() in session.inc. If the data is permanent or we're
|
||||
// not enforcing a minimum cache lifetime always return the cached data.
|
||||
$config = config('system.performance');
|
||||
if ($cache->expire != CACHE_PERMANENT && $config->get('cache_lifetime') && $user->cache > $cache->created) {
|
||||
// This cache data is too old and thus not valid for us, ignore it.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ($cache->serialized) {
|
||||
$cache->data = unserialize($cache->data);
|
||||
}
|
||||
|
||||
return $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::set().
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT) {
|
||||
$fields = array(
|
||||
'serialized' => 0,
|
||||
'created' => REQUEST_TIME,
|
||||
'expire' => $expire,
|
||||
);
|
||||
if (!is_string($data)) {
|
||||
$fields['data'] = serialize($data);
|
||||
$fields['serialized'] = 1;
|
||||
}
|
||||
else {
|
||||
$fields['data'] = $data;
|
||||
$fields['serialized'] = 0;
|
||||
}
|
||||
|
||||
try {
|
||||
db_merge($this->bin)
|
||||
->key(array('cid' => $cid))
|
||||
->fields($fields)
|
||||
->execute();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// The database may not be available, so we'll ignore cache_set requests.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::delete().
|
||||
*/
|
||||
function delete($cid) {
|
||||
db_delete($this->bin)
|
||||
->condition('cid', $cid)
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::deleteMultiple().
|
||||
*/
|
||||
function deleteMultiple(Array $cids) {
|
||||
// Delete in chunks when a large array is passed.
|
||||
do {
|
||||
db_delete($this->bin)
|
||||
->condition('cid', array_splice($cids, 0, 1000), 'IN')
|
||||
->execute();
|
||||
}
|
||||
while (count($cids));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::deletePrefix().
|
||||
*/
|
||||
function deletePrefix($prefix) {
|
||||
db_delete($this->bin)
|
||||
->condition('cid', db_like($prefix) . '%', 'LIKE')
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::flush().
|
||||
*/
|
||||
function flush() {
|
||||
db_truncate($this->bin)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::expire().
|
||||
*/
|
||||
function expire() {
|
||||
if (variable_get('cache_lifetime', 0)) {
|
||||
// We store the time in the current user's $user->cache variable which
|
||||
// will be saved into the sessions bin by _drupal_session_write(). We then
|
||||
// simulate that the cache was flushed for this user by not returning
|
||||
// cached data that was cached before the timestamp.
|
||||
$GLOBALS['user']->cache = REQUEST_TIME;
|
||||
|
||||
$cache_flush = variable_get('cache_flush_' . $this->bin, 0);
|
||||
if ($cache_flush == 0) {
|
||||
// This is the first request to clear the cache, start a timer.
|
||||
variable_set('cache_flush_' . $this->bin, REQUEST_TIME);
|
||||
}
|
||||
elseif (REQUEST_TIME > ($cache_flush + variable_get('cache_lifetime', 0))) {
|
||||
// Clear the cache for everyone; cache_lifetime seconds have passed
|
||||
// since the first request to clear the cache.
|
||||
db_delete($this->bin)
|
||||
->condition('expire', CACHE_PERMANENT, '<>')
|
||||
->condition('expire', REQUEST_TIME, '<')
|
||||
->execute();
|
||||
variable_set('cache_flush_' . $this->bin, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No minimum cache lifetime, flush all temporary cache entries now.
|
||||
db_delete($this->bin)
|
||||
->condition('expire', CACHE_PERMANENT, '<>')
|
||||
->condition('expire', REQUEST_TIME, '<')
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::garbageCollection().
|
||||
*/
|
||||
function garbageCollection() {
|
||||
global $user;
|
||||
|
||||
// When cache lifetime is in force, avoid running garbage collection too
|
||||
// often since this will remove temporary cache items indiscriminately.
|
||||
$cache_flush = variable_get('cache_flush_' . $this->bin, 0);
|
||||
if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= REQUEST_TIME)) {
|
||||
// Reset the variable immediately to prevent a meltdown in heavy load situations.
|
||||
variable_set('cache_flush_' . $this->bin, 0);
|
||||
// Time to flush old cache data
|
||||
db_delete($this->bin)
|
||||
->condition('expire', CACHE_PERMANENT, '<>')
|
||||
->condition('expire', $cache_flush, '<=')
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::isEmpty().
|
||||
*/
|
||||
function isEmpty() {
|
||||
$this->garbageCollection();
|
||||
$query = db_select($this->bin);
|
||||
$query->addExpression('1');
|
||||
$result = $query->range(0, 1)
|
||||
->execute()
|
||||
->fetchField();
|
||||
return empty($result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of InstallBackend.
|
||||
*/
|
||||
|
||||
namespace Drupal\Cache;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Defines a stub cache implementation to be used during installation.
|
||||
*
|
||||
* The stub implementation is needed when database access is not yet available.
|
||||
* Because Drupal's caching system never requires that cached data be present,
|
||||
* these stub functions can short-circuit the process and sidestep the need for
|
||||
* any persistent storage. Obviously, using this cache implementation during
|
||||
* normal operations would have a negative impact on performance.
|
||||
*
|
||||
* If there is a database cache, this backend will attempt to clear it whenever
|
||||
* possible. The reason for doing this is that the database cache can accumulate
|
||||
* data during installation due to any full bootstraps that may occur at the
|
||||
* same time (for example, Ajax requests triggered by the installer). If we
|
||||
* didn't try to clear it whenever one of the delete function are called, the
|
||||
* data in the cache would become stale; for example, the installer sometimes
|
||||
* calls variable_set(), which updates the {variable} table and then clears the
|
||||
* cache to make sure that the next page request picks up the new value.
|
||||
* Not actually clearing the cache here therefore leads old variables to be
|
||||
* loaded on the first page requests after installation, which can cause
|
||||
* subtle bugs, some of which would not be fixed unless the site
|
||||
* administrator cleared the cache manually.
|
||||
*/
|
||||
class InstallBackend extends DatabaseBackend {
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Cache\DatabaseBackend::get().
|
||||
*/
|
||||
function get($cid) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Cache\DatabaseBackend::getMultiple().
|
||||
*/
|
||||
function getMultiple(&$cids) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Cache\DatabaseBackend::set().
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT) {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\DatabaseBackend::delete().
|
||||
*/
|
||||
function delete($cid) {
|
||||
try {
|
||||
if (class_exists('Database')) {
|
||||
parent::delete($cid);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\DatabaseBackend::deleteMultiple().
|
||||
*/
|
||||
function deleteMultiple(array $cids) {
|
||||
try {
|
||||
if (class_exists('Database')) {
|
||||
parent::deleteMultiple($cids);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\DatabaseBackend::deletePrefix().
|
||||
*/
|
||||
function deletePrefix($prefix) {
|
||||
try {
|
||||
if (class_exists('Database')) {
|
||||
parent::deletePrefix($prefix);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\DatabaseBackend::flush().
|
||||
*/
|
||||
function flush() {
|
||||
try {
|
||||
if (class_exists('Database')) {
|
||||
parent::flush();
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Cache\DatabaseBackend::isEmpty().
|
||||
*/
|
||||
function isEmpty() {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of NullBackend.
|
||||
*/
|
||||
|
||||
namespace Drupal\Cache;
|
||||
|
||||
/**
|
||||
* Defines a stub cache implementation.
|
||||
*
|
||||
* The stub implementation is needed when database access is not yet available.
|
||||
* Because Drupal's caching system never requires that cached data be present,
|
||||
* these stub functions can short-circuit the process and sidestep the need for
|
||||
* any persistent storage. Using this cache implementation during normal
|
||||
* operations would have a negative impact on performance.
|
||||
*
|
||||
* This also can be used for testing purposes.
|
||||
*/
|
||||
class NullBackend implements CacheBackendInterface {
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::__construct().
|
||||
*/
|
||||
function __construct($bin) {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::get().
|
||||
*/
|
||||
function get($cid) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::getMultiple().
|
||||
*/
|
||||
function getMultiple(&$cids) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::set().
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT) {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::delete().
|
||||
*/
|
||||
function delete($cid) {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::deleteMultiple().
|
||||
*/
|
||||
function deleteMultiple(array $cids) {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::deletePrefix().
|
||||
*/
|
||||
function deletePrefix($prefix) {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::flush().
|
||||
*/
|
||||
function flush() {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::expire().
|
||||
*/
|
||||
function expire() {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::garbageCollection().
|
||||
*/
|
||||
function garbageCollection() {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Cache\CacheBackendInterface::isEmpty().
|
||||
*/
|
||||
function isEmpty() {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
|
@ -11,9 +11,7 @@
|
|||
* Functions that perform an action on a certain system object.
|
||||
*
|
||||
* Action functions are declared by modules by implementing hook_action_info().
|
||||
* Modules can cause action functions to run by calling actions_do(), and
|
||||
* trigger.module provides a user interface that lets administrators define
|
||||
* events that cause action functions to run.
|
||||
* Modules can cause action functions to run by calling actions_do().
|
||||
*
|
||||
* Each action function takes two to four arguments:
|
||||
* - $entity: The object that the action acts on, such as a node, comment, or
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?php
|
||||
|
||||
use Symfony\Component\ClassLoader\UniversalClassLoader;
|
||||
use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functions that need to be loaded on every Drupal request.
|
||||
|
@ -299,12 +302,12 @@ abstract class DrupalCacheArray implements ArrayAccess {
|
|||
/**
|
||||
* A cid to pass to cache()->set() and cache()->get().
|
||||
*/
|
||||
private $cid;
|
||||
protected $cid;
|
||||
|
||||
/**
|
||||
* A bin to pass to cache()->set() and cache()->get().
|
||||
*/
|
||||
private $bin;
|
||||
protected $bin;
|
||||
|
||||
/**
|
||||
* An array of keys to add to the cache at the end of the request.
|
||||
|
@ -403,24 +406,20 @@ abstract class DrupalCacheArray implements ArrayAccess {
|
|||
/**
|
||||
* Writes a value to the persistent cache immediately.
|
||||
*
|
||||
* @param $cid
|
||||
* The cache ID.
|
||||
* @param $bin
|
||||
* The cache bin.
|
||||
* @param $data
|
||||
* The data to write to the persistent cache.
|
||||
* @param $lock
|
||||
* Whether to acquire a lock before writing to cache.
|
||||
*/
|
||||
protected function set($cid, $data, $bin, $lock = TRUE) {
|
||||
protected function set($data, $lock = TRUE) {
|
||||
// Lock cache writes to help avoid stampedes.
|
||||
// To implement locking for cache misses, override __construct().
|
||||
$lock_name = $cid . ':' . $bin;
|
||||
$lock_name = $this->cid . ':' . $this->bin;
|
||||
if (!$lock || lock_acquire($lock_name)) {
|
||||
if ($cached = cache($bin)->get($cid)) {
|
||||
if ($cached = cache($this->bin)->get($this->cid)) {
|
||||
$data = $cached->data + $data;
|
||||
}
|
||||
cache($bin)->set($cid, $data);
|
||||
cache($this->bin)->set($this->cid, $data);
|
||||
if ($lock) {
|
||||
lock_release($lock_name);
|
||||
}
|
||||
|
@ -438,7 +437,7 @@ abstract class DrupalCacheArray implements ArrayAccess {
|
|||
}
|
||||
}
|
||||
if (!empty($data)) {
|
||||
$this->set($this->cid, $data, $this->bin);
|
||||
$this->set($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -770,7 +769,7 @@ function drupal_settings_initialize() {
|
|||
global $base_url, $base_path, $base_root;
|
||||
|
||||
// Export the following settings.php variables to the global namespace
|
||||
global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $drupal_config_directory_name, $drupal_config_key;
|
||||
global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name, $config_signature_key;
|
||||
$conf = array();
|
||||
|
||||
if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {
|
||||
|
@ -1490,7 +1489,7 @@ function drupal_unpack($obj, $field = 'data') {
|
|||
* variable text such as user names or link URLs into translated text. Variable
|
||||
* substitution looks like this:
|
||||
* @code
|
||||
* $text = t("@name's blog", array('@name' => format_username($account)));
|
||||
* $text = t("@name's blog", array('@name' => user_format_name($account)));
|
||||
* @endcode
|
||||
* Basically, you can put variables like @name into your string, and t() will
|
||||
* substitute their sanitized values at translation time. (See the
|
||||
|
@ -1529,7 +1528,7 @@ function t($string, array $args = array(), array $options = array()) {
|
|||
|
||||
// Merge in default.
|
||||
if (empty($options['langcode'])) {
|
||||
$options['langcode'] = isset($language->language) ? $language->language : LANGUAGE_SYSTEM;
|
||||
$options['langcode'] = isset($language->langcode) ? $language->langcode : LANGUAGE_SYSTEM;
|
||||
}
|
||||
if (empty($options['context'])) {
|
||||
$options['context'] = '';
|
||||
|
@ -2293,39 +2292,24 @@ function _drupal_bootstrap_configuration() {
|
|||
// Initialize the configuration, including variables from settings.php.
|
||||
drupal_settings_initialize();
|
||||
|
||||
// Hook up the Symfony ClassLoader for loading PSR-0-compatible classes.
|
||||
require_once(DRUPAL_ROOT . '/core/includes/Symfony/Component/ClassLoader/UniversalClassLoader.php');
|
||||
// Include and activate the class loader.
|
||||
$loader = drupal_classloader();
|
||||
|
||||
// By default, use the UniversalClassLoader which is best for development,
|
||||
// as it does not break when code is moved on the file system. It is slow,
|
||||
// however, so for production the APC class loader should be used instead.
|
||||
// @todo Switch to a cleaner way to switch autoloaders than variable_get().
|
||||
switch (variable_get('autoloader_mode', 'default')) {
|
||||
case 'apc':
|
||||
if (function_exists('apc_store')) {
|
||||
require_once(DRUPAL_ROOT . '/core/includes/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php');
|
||||
$loader = new \Symfony\Component\ClassLoader\ApcUniversalClassLoader('drupal.' . $GLOBALS['drupal_hash_salt']);
|
||||
break;
|
||||
}
|
||||
// If APC was not loaded, fall through to the default loader so that
|
||||
// the site does not fail completely.
|
||||
case 'dev':
|
||||
case 'default':
|
||||
default:
|
||||
$loader = new \Symfony\Component\ClassLoader\UniversalClassLoader();
|
||||
break;
|
||||
}
|
||||
|
||||
// Register classes with namespaces.
|
||||
// Register explicit vendor namespaces.
|
||||
$loader->registerNamespaces(array(
|
||||
// All Symfony-borrowed code lives in /core/includes/Symfony.
|
||||
'Symfony' => DRUPAL_ROOT . '/core/includes',
|
||||
));
|
||||
// Register the Drupal namespace for classes in core as a fallback.
|
||||
// This allows to register additional namespaces within the Drupal namespace
|
||||
// (e.g., for modules) and avoids an additional file_exists() on the Drupal
|
||||
// core namespace, since the class loader can already determine the best
|
||||
// namespace match based on a string comparison. It further allows modules to
|
||||
// register/overload namespaces in Drupal core.
|
||||
$loader->registerNamespaceFallbacks(array(
|
||||
// All Drupal-namespaced code in core lives in /core/includes/Drupal.
|
||||
'Drupal' => DRUPAL_ROOT . '/core/includes',
|
||||
));
|
||||
|
||||
// Activate the autoloader.
|
||||
$loader->register();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2674,53 +2658,45 @@ function language_types() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of installed languages, indexed by the specified key.
|
||||
* Returns a list of configured languages.
|
||||
*
|
||||
* @param $field
|
||||
* (optional) The field to index the list with.
|
||||
* @param $only_enabled
|
||||
* (optional) Whether to return only enabled languages.
|
||||
*
|
||||
* @return
|
||||
* An associative array, keyed on the values of $field.
|
||||
* - If $field is 'weight' or 'enabled', the array is nested, with the outer
|
||||
* array's values each being associative arrays with language codes as
|
||||
* keys and language objects as values.
|
||||
* - For all other values of $field, the array is only one level deep, and
|
||||
* the array's values are language objects.
|
||||
* An associative array of languages, keyed by the language code, ordered by
|
||||
* weight ascending and name ascending.
|
||||
*/
|
||||
function language_list($field = 'language') {
|
||||
function language_list($only_enabled = FALSE) {
|
||||
$languages = &drupal_static(__FUNCTION__);
|
||||
// Init language list
|
||||
// Initialize master language list.
|
||||
if (!isset($languages)) {
|
||||
// Initialize local language list caches.
|
||||
$languages = array('all' => array(), 'enabled' => array());
|
||||
|
||||
// Fill in master language list based on current configuration.
|
||||
$default = language_default();
|
||||
if (language_multilingual() || module_exists('language')) {
|
||||
$languages['language'] = db_query('SELECT * FROM {language} ORDER BY weight ASC, name ASC')->fetchAllAssoc('language');
|
||||
// Use language module configuration if available.
|
||||
$languages['all'] = db_query('SELECT * FROM {language} ORDER BY weight ASC, name ASC')->fetchAllAssoc('langcode');
|
||||
}
|
||||
else {
|
||||
// No locale module, so use the default language only.
|
||||
$languages['language'][$default->language] = $default;
|
||||
// No language module, so use the default language only.
|
||||
$languages['all'][$default->langcode] = $default;
|
||||
}
|
||||
|
||||
// Initialize default property so callers have an easy reference and
|
||||
// can save the same object without data loss.
|
||||
foreach ($languages['language'] as $langcode => $language) {
|
||||
$languages['language'][$langcode]->default = ($langcode == $default->language);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the array indexed by the right field
|
||||
if (!isset($languages[$field])) {
|
||||
$languages[$field] = array();
|
||||
foreach ($languages['language'] as $lang) {
|
||||
// Some values should be collected into an array
|
||||
if (in_array($field, array('enabled', 'weight'))) {
|
||||
$languages[$field][$lang->$field][$lang->language] = $lang;
|
||||
}
|
||||
else {
|
||||
$languages[$field][$lang->$field] = $lang;
|
||||
// Initialize default property so callers have an easy reference and can
|
||||
// save the same object without data loss. Also fill in the filtered list
|
||||
// of enabled languages only.
|
||||
foreach ($languages['all'] as $langcode => $language) {
|
||||
$languages['all'][$langcode]->default = ($langcode == $default->langcode);
|
||||
if ($language->enabled) {
|
||||
$languages['enabled'][$langcode] = $languages['all'][$langcode];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $languages[$field];
|
||||
|
||||
return $only_enabled ? $languages['enabled'] : $languages['all'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2733,7 +2709,7 @@ function language_default() {
|
|||
$default = variable_get(
|
||||
'language_default',
|
||||
(object) array(
|
||||
'language' => 'en',
|
||||
'langcode' => 'en',
|
||||
'name' => 'English',
|
||||
'direction' => 0,
|
||||
'enabled' => 1,
|
||||
|
@ -3030,6 +3006,48 @@ function drupal_get_complete_schema($rebuild = FALSE) {
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initializes and returns the class loader.
|
||||
*
|
||||
* The class loader is responsible for lazy-loading all PSR-0 compatible
|
||||
* classes, interfaces, and traits (PHP 5.4 and later). Its only dependencies
|
||||
* are DRUPAL_ROOT and variable_get(). Otherwise it may be called as early as
|
||||
* possible.
|
||||
*
|
||||
* @return Symfony\Component\ClassLoader\UniversalClassLoader
|
||||
* A UniversalClassLoader class instance (or extension thereof).
|
||||
*/
|
||||
function drupal_classloader() {
|
||||
// Include the Symfony ClassLoader for loading PSR-0-compatible classes.
|
||||
require_once DRUPAL_ROOT . '/core/includes/Symfony/Component/ClassLoader/UniversalClassLoader.php';
|
||||
|
||||
// By default, use the UniversalClassLoader which is best for development,
|
||||
// as it does not break when code is moved on the file system. However, as it
|
||||
// is slow, allow to use the APC class loader in production.
|
||||
static $loader;
|
||||
|
||||
if (!isset($loader)) {
|
||||
// @todo Use a cleaner way than variable_get() to switch autoloaders.
|
||||
switch (variable_get('autoloader_mode', 'default')) {
|
||||
case 'apc':
|
||||
if (function_exists('apc_store')) {
|
||||
require_once DRUPAL_ROOT . '/core/includes/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
|
||||
$loader = new ApcUniversalClassLoader('drupal.' . $GLOBALS['drupal_hash_salt']);
|
||||
break;
|
||||
}
|
||||
// Fall through to the default loader if APC was not loaded, so that the
|
||||
// site does not fail completely.
|
||||
case 'dev':
|
||||
case 'default':
|
||||
default:
|
||||
$loader = new UniversalClassLoader();
|
||||
break;
|
||||
}
|
||||
$loader->register();
|
||||
}
|
||||
return $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms that an interface is available.
|
||||
*
|
||||
|
@ -3184,29 +3202,29 @@ function registry_update() {
|
|||
*
|
||||
* Example:
|
||||
* @code
|
||||
* function language_list($field = 'language') {
|
||||
* $languages = &drupal_static(__FUNCTION__);
|
||||
* if (!isset($languages)) {
|
||||
* function example_list($field = 'default') {
|
||||
* $examples = &drupal_static(__FUNCTION__);
|
||||
* if (!isset($examples)) {
|
||||
* // If this function is being called for the first time after a reset,
|
||||
* // query the database and execute any other code needed to retrieve
|
||||
* // information about the supported languages.
|
||||
* // information.
|
||||
* ...
|
||||
* }
|
||||
* if (!isset($languages[$field])) {
|
||||
* if (!isset($examples[$field])) {
|
||||
* // If this function is being called for the first time for a particular
|
||||
* // index field, then execute code needed to index the information already
|
||||
* // available in $languages by the desired field.
|
||||
* // available in $examples by the desired field.
|
||||
* ...
|
||||
* }
|
||||
* // Subsequent invocations of this function for a particular index field
|
||||
* // skip the above two code blocks and quickly return the already indexed
|
||||
* // information.
|
||||
* return $languages[$field];
|
||||
* return $examples[$field];
|
||||
* }
|
||||
* function locale_translate_overview_screen() {
|
||||
* // When building the content for the translations overview page, make
|
||||
* // sure to get completely fresh information about the supported languages.
|
||||
* drupal_static_reset('language_list');
|
||||
* function examples_admin_overview() {
|
||||
* // When building the content for the overview page, make sure to get
|
||||
* // completely fresh information.
|
||||
* drupal_static_reset('example_list');
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides a stub cache implementation to be used during installation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines a stub cache implementation to be used during installation.
|
||||
*
|
||||
* The stub implementation is needed when database access is not yet available.
|
||||
* Because Drupal's caching system never requires that cached data be present,
|
||||
* these stub functions can short-circuit the process and sidestep the need for
|
||||
* any persistent storage. Obviously, using this cache implementation during
|
||||
* normal operations would have a negative impact on performance.
|
||||
*/
|
||||
class DrupalFakeCache extends DrupalDatabaseCache implements DrupalCacheInterface {
|
||||
|
||||
/**
|
||||
* Overrides DrupalDatabaseCache::get().
|
||||
*/
|
||||
function get($cid) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides DrupalDatabaseCache::getMultiple().
|
||||
*/
|
||||
function getMultiple(&$cids) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides DrupalDatabaseCache::set().
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::deletePrefix().
|
||||
*/
|
||||
function deletePrefix($cid) {
|
||||
try {
|
||||
if (class_exists('Database')) {
|
||||
parent::deletePrefix($cid);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides DrupalDatabaseCache::clear().
|
||||
*/
|
||||
function clear($cid = NULL, $wildcard = FALSE) {
|
||||
// If there is a database cache, attempt to clear it whenever possible. The
|
||||
// reason for doing this is that the database cache can accumulate data
|
||||
// during installation due to any full bootstraps that may occur at the
|
||||
// same time (for example, Ajax requests triggered by the installer). If we
|
||||
// didn't try to clear it whenever this function is called, the data in the
|
||||
// cache would become stale; for example, the installer sometimes calls
|
||||
// variable_set(), which updates the {variable} table and then clears the
|
||||
// cache to make sure that the next page request picks up the new value.
|
||||
// Not actually clearing the cache here therefore leads old variables to be
|
||||
// loaded on the first page requests after installation, which can cause
|
||||
// subtle bugs, some of which would not be fixed unless the site
|
||||
// administrator cleared the cache manually.
|
||||
try {
|
||||
if (class_exists('Database')) {
|
||||
parent::clear($cid, $wildcard);
|
||||
}
|
||||
}
|
||||
// If the attempt at clearing the cache causes an error, that means that
|
||||
// either the database connection is not set up yet or the relevant cache
|
||||
// table in the database has not yet been created, so we can safely do
|
||||
// nothing here.
|
||||
catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides DrupalDatabaseCache::isEmpty().
|
||||
*/
|
||||
function isEmpty() {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
|
@ -8,18 +8,20 @@
|
|||
/**
|
||||
* Instantiates and statically caches the correct class for a cache bin.
|
||||
*
|
||||
* By default, this returns an instance of the DrupalDatabaseCache class.
|
||||
* Classes implementing DrupalCacheInterface can register themselves both as a
|
||||
* default implementation and for specific bins.
|
||||
* By default, this returns an instance of the Drupal\Cache\DatabaseBackend
|
||||
* class.
|
||||
*
|
||||
* Classes implementing Drupal\Cache\CacheBackendInterface can register themselves
|
||||
* both as a default implementation and for specific bins.
|
||||
*
|
||||
* @param $bin
|
||||
* The cache bin for which the cache object should be returned, defaults to
|
||||
* 'cache'.
|
||||
*
|
||||
* @return DrupalCacheInterface
|
||||
* @return Drupal\Cache\CacheBackendInterface
|
||||
* The cache object associated with the specified bin.
|
||||
*
|
||||
* @see DrupalCacheInterface
|
||||
* @see Drupal\Cache\CacheBackendInterface
|
||||
*/
|
||||
function cache($bin = 'cache') {
|
||||
// Temporary backwards compatibiltiy layer, allow old style prefixed cache
|
||||
|
@ -32,7 +34,7 @@ function cache($bin = 'cache') {
|
|||
if (!isset($cache_objects[$bin])) {
|
||||
$class = variable_get('cache_class_' . $bin);
|
||||
if (!isset($class)) {
|
||||
$class = variable_get('cache_default_class', 'DrupalDatabaseCache');
|
||||
$class = variable_get('cache_default_class', 'Drupal\Cache\DatabaseBackend');
|
||||
}
|
||||
$cache_objects[$bin] = new $class($bin);
|
||||
}
|
||||
|
@ -54,460 +56,3 @@ function cache_clear_all() {
|
|||
}
|
||||
cache('page')->expire();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines an interface for cache implementations.
|
||||
*
|
||||
* All cache implementations have to implement this interface.
|
||||
* DrupalDatabaseCache provides the default implementation, which can be
|
||||
* consulted as an example.
|
||||
*
|
||||
* To make Drupal use your implementation for a certain cache bin, you have to
|
||||
* set a variable with the name of the cache bin as its key and the name of
|
||||
* your class as its value. For example, if your implementation of
|
||||
* DrupalCacheInterface was called MyCustomCache, the following line would make
|
||||
* Drupal use it for the 'cache_page' bin:
|
||||
* @code
|
||||
* variable_set('cache_class_cache_page', 'MyCustomCache');
|
||||
* @endcode
|
||||
*
|
||||
* Additionally, you can register your cache implementation to be used by
|
||||
* default for all cache bins by setting the variable 'cache_default_class' to
|
||||
* the name of your implementation of the DrupalCacheInterface, e.g.
|
||||
* @code
|
||||
* variable_set('cache_default_class', 'MyCustomCache');
|
||||
* @endcode
|
||||
*
|
||||
* To implement a completely custom cache bin, use the same variable format:
|
||||
* @code
|
||||
* variable_set('cache_class_custom_bin', 'MyCustomCache');
|
||||
* @endcode
|
||||
* To access your custom cache bin, specify the name of the bin when storing
|
||||
* or retrieving cached data:
|
||||
* @code
|
||||
* cache_set($cid, $data, 'custom_bin', $expire);
|
||||
* cache_get($cid, 'custom_bin');
|
||||
* @endcode
|
||||
*
|
||||
* @see cache()
|
||||
* @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.
|
||||
*
|
||||
* Data may be stored as either plain text or as serialized data. cache_get()
|
||||
* will automatically return unserialized objects and arrays.
|
||||
*
|
||||
* @param $cid
|
||||
* The cache ID of the data to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The cache or FALSE on failure.
|
||||
*/
|
||||
function get($cid);
|
||||
|
||||
/**
|
||||
* Returns data from the persistent cache when given an array of cache IDs.
|
||||
*
|
||||
* @param $cids
|
||||
* An array of cache IDs for the data to retrieve. This is passed by
|
||||
* reference, and will have the IDs successfully returned from cache
|
||||
* removed.
|
||||
*
|
||||
* @return
|
||||
* An array of the items successfully returned from cache indexed by cid.
|
||||
*/
|
||||
function getMultiple(&$cids);
|
||||
|
||||
/**
|
||||
* Stores data in the persistent cache.
|
||||
*
|
||||
* @param $cid
|
||||
* 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.
|
||||
* @param $expire
|
||||
* One of the following values:
|
||||
* - CACHE_PERMANENT: Indicates that the item should never be removed unless
|
||||
* explicitly told to using cache_clear_all() with a cache ID.
|
||||
* - CACHE_TEMPORARY: Indicates that the item should be removed at the next
|
||||
* general cache wipe.
|
||||
* - A Unix timestamp: Indicates that the item should be kept at least until
|
||||
* the given time, after which it behaves like CACHE_TEMPORARY.
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT);
|
||||
|
||||
/**
|
||||
* Deletes an item from the cache.
|
||||
*
|
||||
* @param $cid
|
||||
* The cache ID to delete.
|
||||
*/
|
||||
function delete($cid);
|
||||
|
||||
/**
|
||||
* Deletes multiple items from the cache.
|
||||
*
|
||||
* @param $cids
|
||||
* An array of $cids to delete.
|
||||
*/
|
||||
function deleteMultiple(Array $cids);
|
||||
|
||||
/**
|
||||
* Deletes items from the cache using a wildcard prefix.
|
||||
*
|
||||
* @param $prefix
|
||||
* A wildcard prefix.
|
||||
*/
|
||||
function deletePrefix($prefix);
|
||||
|
||||
/**
|
||||
* Flushes all cache items in a bin.
|
||||
*/
|
||||
function flush();
|
||||
|
||||
/**
|
||||
* Expires temporary items from the cache.
|
||||
*/
|
||||
function expire();
|
||||
|
||||
/**
|
||||
* Performs garbage collection on a cache bin.
|
||||
*/
|
||||
function garbageCollection();
|
||||
|
||||
/**
|
||||
* Checks if a cache bin is empty.
|
||||
*
|
||||
* A cache bin is considered empty if it does not contain any valid data for
|
||||
* any cache ID.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the cache bin specified is empty.
|
||||
*/
|
||||
function isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a stub cache implementation.
|
||||
*
|
||||
* The stub implementation is needed when database access is not yet available.
|
||||
* Because Drupal's caching system never requires that cached data be present,
|
||||
* these stub functions can short-circuit the process and sidestep the need for
|
||||
* any persistent storage. Using this cache implementation during normal
|
||||
* operations would have a negative impact on performance.
|
||||
*
|
||||
* This also can be used for testing purposes.
|
||||
*/
|
||||
class DrupalNullCache implements DrupalCacheInterface {
|
||||
|
||||
/**
|
||||
* Constructs a DrupalNullCache object.
|
||||
*/
|
||||
function __construct($bin) {}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::get().
|
||||
*/
|
||||
function get($cid) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::getMultiple().
|
||||
*/
|
||||
function getMultiple(&$cids) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::set().
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT) {}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::delete().
|
||||
*/
|
||||
function delete($cid) {}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::deleteMultiple().
|
||||
*/
|
||||
function deleteMultiple(array $cids) {}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::deletePrefix().
|
||||
*/
|
||||
function deletePrefix($prefix) {}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::flush().
|
||||
*/
|
||||
function flush() {}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::expire().
|
||||
*/
|
||||
function expire() {}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::garbageCollection().
|
||||
*/
|
||||
function garbageCollection() {}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::isEmpty().
|
||||
*/
|
||||
function isEmpty() {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a default cache implementation.
|
||||
*
|
||||
* This is Drupal's default cache implementation. It uses the database to store
|
||||
* cached data. Each cache bin corresponds to a database table by the same name.
|
||||
*/
|
||||
class DrupalDatabaseCache implements DrupalCacheInterface {
|
||||
protected $bin;
|
||||
|
||||
/**
|
||||
* Constructs a new DrupalDatabaseCache object.
|
||||
*/
|
||||
function __construct($bin) {
|
||||
// All cache tables should be prefixed with 'cache_', except for the
|
||||
// default 'cache' bin.
|
||||
if ($bin != 'cache') {
|
||||
$bin = 'cache_' . $bin;
|
||||
}
|
||||
$this->bin = $bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::get().
|
||||
*/
|
||||
function get($cid) {
|
||||
$cids = array($cid);
|
||||
$cache = $this->getMultiple($cids);
|
||||
return reset($cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::getMultiple().
|
||||
*/
|
||||
function getMultiple(&$cids) {
|
||||
try {
|
||||
// Garbage collection necessary when enforcing a minimum cache lifetime.
|
||||
$this->garbageCollection($this->bin);
|
||||
|
||||
// When serving cached pages, the overhead of using db_select() was found
|
||||
// to add around 30% overhead to the request. Since $this->bin is a
|
||||
// variable, this means the call to db_query() here uses a concatenated
|
||||
// string. This is highly discouraged under any other circumstances, and
|
||||
// is used here only due to the performance overhead we would incur
|
||||
// otherwise. When serving an uncached page, the overhead of using
|
||||
// db_select() is a much smaller proportion of the request.
|
||||
$result = db_query('SELECT cid, data, created, expire, serialized FROM {' . db_escape_table($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
|
||||
$cache = array();
|
||||
foreach ($result as $item) {
|
||||
$item = $this->prepareItem($item);
|
||||
if ($item) {
|
||||
$cache[$item->cid] = $item;
|
||||
}
|
||||
}
|
||||
$cids = array_diff($cids, array_keys($cache));
|
||||
return $cache;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// If the database is never going to be available, cache requests should
|
||||
// return FALSE in order to allow exception handling to occur.
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a cached item.
|
||||
*
|
||||
* Checks that items are either permanent or did not expire, and unserializes
|
||||
* data as appropriate.
|
||||
*
|
||||
* @param $cache
|
||||
* An item loaded from cache_get() or cache_get_multiple().
|
||||
*
|
||||
* @return
|
||||
* The item with data unserialized as appropriate or FALSE if there is no
|
||||
* valid item to load.
|
||||
*/
|
||||
protected function prepareItem($cache) {
|
||||
global $user;
|
||||
|
||||
if (!isset($cache->data)) {
|
||||
return FALSE;
|
||||
}
|
||||
// If enforcing a minimum cache lifetime, validate that the data is
|
||||
// currently valid for this user before we return it by making sure the cache
|
||||
// entry was created before the timestamp in the current session's cache
|
||||
// timer. The cache variable is loaded into the $user object by
|
||||
// _drupal_session_read() in session.inc. If the data is permanent or we're
|
||||
// not enforcing a minimum cache lifetime always return the cached data.
|
||||
$config = config('system.performance');
|
||||
if ($cache->expire != CACHE_PERMANENT && $config->get('cache_lifetime') && $user->cache > $cache->created) {
|
||||
// This cache data is too old and thus not valid for us, ignore it.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ($cache->serialized) {
|
||||
$cache->data = unserialize($cache->data);
|
||||
}
|
||||
|
||||
return $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::set().
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT) {
|
||||
$fields = array(
|
||||
'serialized' => 0,
|
||||
'created' => REQUEST_TIME,
|
||||
'expire' => $expire,
|
||||
);
|
||||
if (!is_string($data)) {
|
||||
$fields['data'] = serialize($data);
|
||||
$fields['serialized'] = 1;
|
||||
}
|
||||
else {
|
||||
$fields['data'] = $data;
|
||||
$fields['serialized'] = 0;
|
||||
}
|
||||
|
||||
try {
|
||||
db_merge($this->bin)
|
||||
->key(array('cid' => $cid))
|
||||
->fields($fields)
|
||||
->execute();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// The database may not be available, so we'll ignore these calls.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::delete().
|
||||
*/
|
||||
function delete($cid) {
|
||||
db_delete($this->bin)
|
||||
->condition('cid', $cid)
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::deleteMultiple().
|
||||
*/
|
||||
function deleteMultiple(Array $cids) {
|
||||
// Delete in chunks when a large array is passed.
|
||||
do {
|
||||
db_delete($this->bin)
|
||||
->condition('cid', array_splice($cids, 0, 1000), 'IN')
|
||||
->execute();
|
||||
}
|
||||
while (count($cids));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::deletePrefix().
|
||||
*/
|
||||
function deletePrefix($prefix) {
|
||||
db_delete($this->bin)
|
||||
->condition('cid', db_like($prefix) . '%', 'LIKE')
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::flush().
|
||||
*/
|
||||
function flush() {
|
||||
db_truncate($this->bin)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::expire().
|
||||
*/
|
||||
function expire() {
|
||||
if (variable_get('cache_lifetime', 0)) {
|
||||
// We store the time in the current user's $user->cache variable which
|
||||
// will be saved into the sessions bin by _drupal_session_write(). We then
|
||||
// simulate that the cache was flushed for this user by not returning
|
||||
// cached data that was cached before the timestamp.
|
||||
$GLOBALS['user']->cache = REQUEST_TIME;
|
||||
|
||||
$cache_flush = variable_get('cache_flush_' . $this->bin, 0);
|
||||
if ($cache_flush == 0) {
|
||||
// This is the first request to clear the cache; start a timer.
|
||||
variable_set('cache_flush_' . $this->bin, REQUEST_TIME);
|
||||
}
|
||||
elseif (REQUEST_TIME > ($cache_flush + variable_get('cache_lifetime', 0))) {
|
||||
// Clear the cache for everyone; cache_lifetime seconds have passed
|
||||
// since the first request to clear the cache.
|
||||
db_delete($this->bin)
|
||||
->condition('expire', CACHE_PERMANENT, '<>')
|
||||
->condition('expire', REQUEST_TIME, '<')
|
||||
->execute();
|
||||
variable_set('cache_flush_' . $this->bin, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No minimum cache lifetime; flush all temporary cache entries now.
|
||||
db_delete($this->bin)
|
||||
->condition('expire', CACHE_PERMANENT, '<>')
|
||||
->condition('expire', REQUEST_TIME, '<')
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::garbageCollection().
|
||||
*/
|
||||
function garbageCollection() {
|
||||
global $user;
|
||||
|
||||
// When cache lifetime is in force, avoid running garbage collection too
|
||||
// often since this will remove temporary cache items indiscriminately.
|
||||
$cache_flush = variable_get('cache_flush_' . $this->bin, 0);
|
||||
if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= REQUEST_TIME)) {
|
||||
// Reset the variable immediately to prevent a meltdown in heavy load
|
||||
// situations.
|
||||
variable_set('cache_flush_' . $this->bin, 0);
|
||||
// Time to flush old cache data
|
||||
db_delete($this->bin)
|
||||
->condition('expire', CACHE_PERMANENT, '<>')
|
||||
->condition('expire', $cache_flush, '<=')
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements DrupalCacheInterface::isEmpty().
|
||||
*/
|
||||
function isEmpty() {
|
||||
$this->garbageCollection();
|
||||
$query = db_select($this->bin);
|
||||
$query->addExpression('1');
|
||||
$result = $query->range(0, 1)
|
||||
->execute()
|
||||
->fetchField();
|
||||
return empty($result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1597,7 +1597,7 @@ function filter_xss_bad_protocol($string, $decode = TRUE) {
|
|||
*/
|
||||
function format_rss_channel($title, $link, $description, $items, $langcode = NULL, $args = array()) {
|
||||
global $language_content;
|
||||
$langcode = $langcode ? $langcode : $language_content->language;
|
||||
$langcode = $langcode ? $langcode : $language_content->langcode;
|
||||
|
||||
$output = "<channel>\n";
|
||||
$output .= ' <title>' . check_plain($title) . "</title>\n";
|
||||
|
@ -1806,7 +1806,7 @@ function format_size($size, $langcode = NULL) {
|
|||
/**
|
||||
* Formats a time interval with the requested granularity.
|
||||
*
|
||||
* @param $timestamp
|
||||
* @param $interval
|
||||
* The length of the interval in seconds.
|
||||
* @param $granularity
|
||||
* How many different units to display in the string.
|
||||
|
@ -1817,7 +1817,7 @@ function format_size($size, $langcode = NULL) {
|
|||
* @return
|
||||
* A translated string representation of the interval.
|
||||
*/
|
||||
function format_interval($timestamp, $granularity = 2, $langcode = NULL) {
|
||||
function format_interval($interval, $granularity = 2, $langcode = NULL) {
|
||||
$units = array(
|
||||
'1 year|@count years' => 31536000,
|
||||
'1 month|@count months' => 2592000,
|
||||
|
@ -1830,9 +1830,9 @@ function format_interval($timestamp, $granularity = 2, $langcode = NULL) {
|
|||
$output = '';
|
||||
foreach ($units as $key => $value) {
|
||||
$key = explode('|', $key);
|
||||
if ($timestamp >= $value) {
|
||||
$output .= ($output ? ' ' : '') . format_plural(floor($timestamp / $value), $key[0], $key[1], array(), array('langcode' => $langcode));
|
||||
$timestamp %= $value;
|
||||
if ($interval >= $value) {
|
||||
$output .= ($output ? ' ' : '') . format_plural(floor($interval / $value), $key[0], $key[1], array(), array('langcode' => $langcode));
|
||||
$interval %= $value;
|
||||
$granularity--;
|
||||
}
|
||||
|
||||
|
@ -1891,7 +1891,7 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL
|
|||
// Use the default langcode if none is set.
|
||||
global $language;
|
||||
if (empty($langcode)) {
|
||||
$langcode = isset($language->language) ? $language->language : LANGUAGE_SYSTEM;
|
||||
$langcode = isset($language->langcode) ? $language->langcode : LANGUAGE_SYSTEM;
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
|
@ -2141,8 +2141,8 @@ function url($path = NULL, array $options = array()) {
|
|||
$path = '';
|
||||
}
|
||||
elseif (!empty($path) && !$options['alias']) {
|
||||
$language = isset($options['language']) && isset($options['language']->language) ? $options['language']->language : '';
|
||||
$alias = drupal_get_path_alias($original_path, $language);
|
||||
$langcode = isset($options['language']) && isset($options['language']->langcode) ? $options['language']->langcode : '';
|
||||
$alias = drupal_get_path_alias($original_path, $langcode);
|
||||
if ($alias != $original_path) {
|
||||
$path = $alias;
|
||||
}
|
||||
|
@ -2314,7 +2314,7 @@ function l($text, $path, array $options = array()) {
|
|||
|
||||
// Append active class.
|
||||
if (($path == $_GET['q'] || ($path == '<front>' && drupal_is_front_page())) &&
|
||||
(empty($options['language']) || $options['language']->language == $language_url->language)) {
|
||||
(empty($options['language']) || $options['language']->langcode == $language_url->langcode)) {
|
||||
$options['attributes']['class'][] = 'active';
|
||||
}
|
||||
|
||||
|
@ -2336,7 +2336,7 @@ function l($text, $path, array $options = array()) {
|
|||
// rendering.
|
||||
if (variable_get('theme_link', TRUE)) {
|
||||
drupal_theme_initialize();
|
||||
$registry = theme_get_registry();
|
||||
$registry = theme_get_registry(FALSE);
|
||||
// We don't want to duplicate functionality that's in theme(), so any
|
||||
// hint of a module or theme doing anything at all special with the 'link'
|
||||
// theme hook should simply result in theme() being called. This includes
|
||||
|
@ -2466,7 +2466,7 @@ function drupal_deliver_html_page($page_callback_result) {
|
|||
|
||||
// Send appropriate HTTP-Header for browsers and search engines.
|
||||
global $language;
|
||||
drupal_add_http_header('Content-Language', $language->language);
|
||||
drupal_add_http_header('Content-Language', $language->langcode);
|
||||
|
||||
// Menu status constants are integers; page content is a string or array.
|
||||
if (is_int($page_callback_result)) {
|
||||
|
@ -2566,8 +2566,7 @@ function drupal_page_footer() {
|
|||
// Commit the user session, if needed.
|
||||
drupal_session_commit();
|
||||
|
||||
$config = config('system.performance');
|
||||
if ($config->get('cache') && ($cache = drupal_page_set_cache())) {
|
||||
if (variable_get('cache', 0) && ($cache = drupal_page_set_cache())) {
|
||||
drupal_serve_page_from_cache($cache);
|
||||
}
|
||||
else {
|
||||
|
@ -2941,7 +2940,7 @@ function drupal_get_css($css = NULL, $skip_alter = FALSE) {
|
|||
foreach ($css as $key => $item) {
|
||||
if ($item['type'] == 'file') {
|
||||
// If defined, force a unique basename for this file.
|
||||
$basename = isset($item['basename']) ? $item['basename'] : basename($item['data']);
|
||||
$basename = isset($item['basename']) ? $item['basename'] : drupal_basename($item['data']);
|
||||
if (isset($previous_item[$basename])) {
|
||||
// Remove the previous item that shared the same base name.
|
||||
unset($css[$previous_item[$basename]]);
|
||||
|
@ -2958,8 +2957,13 @@ function drupal_get_css($css = NULL, $skip_alter = FALSE) {
|
|||
|
||||
// Provide the page with information about the individual CSS files used,
|
||||
// information not otherwise available when CSS aggregation is enabled.
|
||||
$setting['ajaxPageState']['css'] = array_fill_keys(array_keys($css), 1);
|
||||
$styles['#attached']['js'][] = array('type' => 'setting', 'data' => $setting);
|
||||
// Skip if no files were added to the page or jQuery.extend() will overwrite
|
||||
// the Drupal.settings.ajaxPageState.css object with an empty array.
|
||||
// Cast the array to an object to be on the safe side even if not empty.
|
||||
if (!empty($css)) {
|
||||
$setting['ajaxPageState']['css'] = (object) array_fill_keys(array_keys($css), 1);
|
||||
$styles['#attached']['js'][] = array('type' => 'setting', 'data' => $setting);
|
||||
}
|
||||
|
||||
return drupal_render($styles);
|
||||
}
|
||||
|
@ -3135,14 +3139,7 @@ function drupal_group_css($css) {
|
|||
* @see system_element_info()
|
||||
*/
|
||||
function drupal_aggregate_css(&$css_groups) {
|
||||
// Only aggregate during normal site operation.
|
||||
if (defined('MAINTENANCE_MODE')) {
|
||||
$preprocess_css = FALSE;
|
||||
}
|
||||
else {
|
||||
$config = config('system.performance');
|
||||
$preprocess_css = $config->get('preprocess_css');
|
||||
}
|
||||
$preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
|
||||
|
||||
// For each group that needs aggregation, aggregate its items.
|
||||
foreach ($css_groups as $key => $group) {
|
||||
|
@ -4375,18 +4372,9 @@ function drupal_group_js($javascript) {
|
|||
* @see drupal_pre_render_scripts()
|
||||
*/
|
||||
function drupal_aggregate_js(&$js_groups) {
|
||||
// Only aggregate during normal site operation.
|
||||
if (defined('MAINTENANCE_MODE')) {
|
||||
$preprocess_js = FALSE;
|
||||
}
|
||||
else {
|
||||
$config = config('system.performance');
|
||||
$preprocess_js = $config->get('preprocess_js');
|
||||
}
|
||||
|
||||
// Only aggregate when the site is configured to do so, and not during an
|
||||
// update.
|
||||
if ($preprocess_js) {
|
||||
if (variable_get('preprocess_js', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update')) {
|
||||
foreach ($js_groups as $key => $group) {
|
||||
if ($group['type'] == 'file' && $group['preprocess']) {
|
||||
$js_groups[$key]['data'] = drupal_build_js_cache($group['items']);
|
||||
|
@ -5135,7 +5123,6 @@ function _drupal_bootstrap_full() {
|
|||
*/
|
||||
function drupal_page_set_cache() {
|
||||
global $base_root;
|
||||
$config = config('system.performance');
|
||||
|
||||
if (drupal_page_is_cacheable()) {
|
||||
$cache = (object) array(
|
||||
|
@ -5162,7 +5149,7 @@ function drupal_page_set_cache() {
|
|||
}
|
||||
|
||||
if ($cache->data['body']) {
|
||||
if ($config->get('page_compression') && extension_loaded('zlib')) {
|
||||
if (variable_get('page_compression', TRUE) && extension_loaded('zlib')) {
|
||||
$cache->data['body'] = gzencode($cache->data['body'], 9, FORCE_GZIP);
|
||||
}
|
||||
cache('page')->set($cache->cid, $cache->data, $cache->expire);
|
||||
|
@ -5779,8 +5766,11 @@ function drupal_render(&$elements) {
|
|||
}
|
||||
|
||||
// Try to fetch the element's markup from cache and return.
|
||||
if (isset($elements['#cache']) && $cached_output = drupal_render_cache_get($elements)) {
|
||||
return $cached_output;
|
||||
if (isset($elements['#cache'])) {
|
||||
$cached_output = drupal_render_cache_get($elements);
|
||||
if ($cached_output !== FALSE) {
|
||||
return $cached_output;
|
||||
}
|
||||
}
|
||||
|
||||
// If #markup is set, ensure #type is set. This allows to specify just #markup
|
||||
|
@ -6156,7 +6146,7 @@ function drupal_render_cid_parts($granularity = NULL) {
|
|||
// part.
|
||||
if (language_multilingual()) {
|
||||
foreach (language_types_configurable() as $language_type) {
|
||||
$cid_parts[] = $GLOBALS[$language_type]->language;
|
||||
$cid_parts[] = $GLOBALS[$language_type]->langcode;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6460,6 +6450,78 @@ function element_set_attributes(array &$element, array $map) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a value from a nested array with variable depth.
|
||||
*
|
||||
* This helper function should be used when the depth of the array element being
|
||||
* retrieved may vary (that is, the number of parent keys is variable). It is
|
||||
* primarily used for form structures and renderable arrays.
|
||||
*
|
||||
* Without this helper function the only way to get a nested array value with
|
||||
* variable depth in one line would be using eval(), which should be avoided:
|
||||
* @code
|
||||
* // Do not do this! Avoid eval().
|
||||
* // May also throw a PHP notice, if the variable array keys do not exist.
|
||||
* eval('$value = $array[\'' . implode("']['", $parents) . "'];");
|
||||
* @endcode
|
||||
*
|
||||
* Instead, use this helper function:
|
||||
* @code
|
||||
* $value = drupal_array_get_nested_value($form, $parents);
|
||||
* @endcode
|
||||
*
|
||||
* The return value will be NULL, regardless of whether the actual value is NULL
|
||||
* or whether the requested key does not exist. If it is required to know
|
||||
* whether the nested array key actually exists, pass a third argument that is
|
||||
* altered by reference:
|
||||
* @code
|
||||
* $key_exists = NULL;
|
||||
* $value = drupal_array_get_nested_value($form, $parents, $key_exists);
|
||||
* if ($key_exists) {
|
||||
* // ... do something with $value ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* However if the number of array parent keys is static, the value should always
|
||||
* be retrieved directly rather than calling this function. For instance:
|
||||
* @code
|
||||
* $value = $form['signature_settings']['signature'];
|
||||
* @endcode
|
||||
*
|
||||
* @param $array
|
||||
* The array from which to get the value.
|
||||
* @param $parents
|
||||
* An array of parent keys of the value, starting with the outermost key.
|
||||
* @param $key_exists
|
||||
* (optional) If given, an already defined variable that is altered by
|
||||
* reference.
|
||||
*
|
||||
* @return
|
||||
* The requested nested value. Possibly NULL if the value is NULL or not all
|
||||
* nested parent keys exist. $key_exists is altered by reference and is a
|
||||
* Boolean that indicates whether all nested parent keys exist (TRUE) or not
|
||||
* (FALSE). This allows to distinguish between the two possibilities when NULL
|
||||
* is returned.
|
||||
*
|
||||
* @see drupal_array_set_nested_value()
|
||||
* @see drupal_array_unset_nested_value()
|
||||
*/
|
||||
function &drupal_array_get_nested_value(array &$array, array $parents, &$key_exists = NULL) {
|
||||
$ref = &$array;
|
||||
foreach ($parents as $parent) {
|
||||
if (is_array($ref) && array_key_exists($parent, $ref)) {
|
||||
$ref = &$ref[$parent];
|
||||
}
|
||||
else {
|
||||
$key_exists = FALSE;
|
||||
$null = NULL;
|
||||
return $null;
|
||||
}
|
||||
}
|
||||
$key_exists = TRUE;
|
||||
return $ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in a nested array with variable depth.
|
||||
*
|
||||
|
@ -6518,6 +6580,7 @@ function element_set_attributes(array &$element, array $map) {
|
|||
* FALSE, PHP throws an error if trying to add into a value that is not an
|
||||
* array. Defaults to FALSE.
|
||||
*
|
||||
* @see drupal_array_unset_nested_value()
|
||||
* @see drupal_array_get_nested_value()
|
||||
*/
|
||||
function drupal_array_set_nested_value(array &$array, array $parents, $value, $force = FALSE) {
|
||||
|
@ -6584,87 +6647,23 @@ function drupal_array_set_nested_value(array &$array, array $parents, $value, $f
|
|||
* @param $parents
|
||||
* An array of parent keys, starting with the outermost key and including the
|
||||
* key to be unset.
|
||||
*
|
||||
* @see drupal_array_set_nested_value()
|
||||
*/
|
||||
function drupal_array_unset_nested_value(array &$array, array $parents) {
|
||||
$ref = &$array;
|
||||
$unset_key = array_pop($parents);
|
||||
foreach ($parents as $parent) {
|
||||
$ref = &$ref[$parent];
|
||||
}
|
||||
unset($ref[$unset_key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a value from a nested array with variable depth.
|
||||
*
|
||||
* This helper function should be used when the depth of the array element being
|
||||
* retrieved may vary (that is, the number of parent keys is variable). It is
|
||||
* primarily used for form structures and renderable arrays.
|
||||
*
|
||||
* Without this helper function the only way to get a nested array value with
|
||||
* variable depth in one line would be using eval(), which should be avoided:
|
||||
* @code
|
||||
* // Do not do this! Avoid eval().
|
||||
* // May also throw a PHP notice, if the variable array keys do not exist.
|
||||
* eval('$value = $array[\'' . implode("']['", $parents) . "'];");
|
||||
* @endcode
|
||||
*
|
||||
* Instead, use this helper function:
|
||||
* @code
|
||||
* $value = drupal_array_get_nested_value($form, $parents);
|
||||
* @endcode
|
||||
*
|
||||
* The return value will be NULL, regardless of whether the actual value is NULL
|
||||
* or whether the requested key does not exist. If it is required to know
|
||||
* whether the nested array key actually exists, pass a third argument that is
|
||||
* altered by reference:
|
||||
* @code
|
||||
* $key_exists = NULL;
|
||||
* $value = drupal_array_get_nested_value($form, $parents, $key_exists);
|
||||
* if ($key_exists) {
|
||||
* // ... do something with $value ...
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* However if the number of array parent keys is static, the value should always
|
||||
* be retrieved directly rather than calling this function. For instance:
|
||||
* @code
|
||||
* $value = $form['signature_settings']['signature'];
|
||||
* @endcode
|
||||
*
|
||||
* @param $array
|
||||
* The array from which to get the value.
|
||||
* @param $parents
|
||||
* An array of parent keys of the value, starting with the outermost key.
|
||||
* @param $key_exists
|
||||
* @param $key_existed
|
||||
* (optional) If given, an already defined variable that is altered by
|
||||
* reference.
|
||||
*
|
||||
* @return
|
||||
* The requested nested value. Possibly NULL if the value is NULL or not all
|
||||
* nested parent keys exist. $key_exists is altered by reference and is a
|
||||
* Boolean that indicates whether all nested parent keys exist (TRUE) or not
|
||||
* (FALSE). This allows to distinguish between the two possibilities when NULL
|
||||
* is returned.
|
||||
*
|
||||
* @see drupal_array_set_nested_value()
|
||||
* @see drupal_array_get_nested_value()
|
||||
*/
|
||||
function &drupal_array_get_nested_value(array &$array, array $parents, &$key_exists = NULL) {
|
||||
$ref = &$array;
|
||||
foreach ($parents as $parent) {
|
||||
if (is_array($ref) && array_key_exists($parent, $ref)) {
|
||||
$ref = &$ref[$parent];
|
||||
}
|
||||
else {
|
||||
$key_exists = FALSE;
|
||||
$null = NULL;
|
||||
return $null;
|
||||
}
|
||||
function drupal_array_unset_nested_value(array &$array, array $parents, &$key_existed = NULL) {
|
||||
$unset_key = array_pop($parents);
|
||||
$ref = &drupal_array_get_nested_value($array, $parents, $key_existed);
|
||||
if ($key_existed && is_array($ref) && array_key_exists($unset_key, $ref)) {
|
||||
$key_existed = TRUE;
|
||||
unset($ref[$unset_key]);
|
||||
}
|
||||
else {
|
||||
$key_existed = FALSE;
|
||||
}
|
||||
$key_exists = TRUE;
|
||||
return $ref;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6873,6 +6872,9 @@ function drupal_common_theme() {
|
|||
'textfield' => array(
|
||||
'render element' => 'element',
|
||||
),
|
||||
'tel' => array(
|
||||
'render element' => 'element',
|
||||
),
|
||||
'form' => array(
|
||||
'render element' => 'element',
|
||||
),
|
||||
|
@ -7448,7 +7450,13 @@ function drupal_flush_all_caches() {
|
|||
system_rebuild_theme_data();
|
||||
drupal_theme_rebuild();
|
||||
|
||||
node_types_rebuild();
|
||||
entity_info_cache_clear();
|
||||
|
||||
// @todo D8: Split cache flushing from rebuilding.
|
||||
// @see http://drupal.org/node/996236
|
||||
if (module_exists('node')) {
|
||||
node_types_rebuild();
|
||||
}
|
||||
// node_menu() defines menu items based on node types so it needs to come
|
||||
// after node types are rebuilt.
|
||||
menu_rebuild();
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
* The directory name.
|
||||
*/
|
||||
function config_get_config_directory() {
|
||||
global $drupal_config_directory_name;
|
||||
global $config_directory_name;
|
||||
|
||||
return conf_path() . '/files/' . $drupal_config_directory_name;
|
||||
return conf_path() . '/files/' . $config_directory_name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,11 +81,11 @@ function config_get_signed_file_storage_names_with_prefix($prefix = '') {
|
|||
*/
|
||||
function config_sign_data($data) {
|
||||
// The configuration key is loaded from settings.php and imported into the global namespace
|
||||
global $drupal_config_key;
|
||||
global $config_signature_key;
|
||||
|
||||
// SHA-512 is both secure and very fast on 64 bit CPUs.
|
||||
// @todo What about 32-bit CPUs?
|
||||
return hash_hmac('sha512', $data, $drupal_config_key);
|
||||
return hash_hmac('sha512', $data, $config_signature_key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -770,7 +770,7 @@ function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS
|
|||
$file = clone $source;
|
||||
$file->fid = NULL;
|
||||
$file->uri = $uri;
|
||||
$file->filename = basename($uri);
|
||||
$file->filename = drupal_basename($uri);
|
||||
// If we are replacing an existing file re-use its database record.
|
||||
if ($replace == FILE_EXISTS_REPLACE) {
|
||||
$existing_files = file_load_multiple(array(), array('uri' => $uri));
|
||||
|
@ -783,7 +783,7 @@ function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS
|
|||
// If we are renaming around an existing file (rather than a directory),
|
||||
// use its basename for the filename.
|
||||
elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
|
||||
$file->filename = basename($destination);
|
||||
$file->filename = drupal_basename($destination);
|
||||
}
|
||||
|
||||
$file = file_save($file);
|
||||
|
@ -871,14 +871,14 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
|
|||
|
||||
// Build a destination URI if necessary.
|
||||
if (!isset($destination)) {
|
||||
$destination = file_build_uri(basename($source));
|
||||
$destination = file_build_uri(drupal_basename($source));
|
||||
}
|
||||
|
||||
|
||||
// Prepare the destination directory.
|
||||
if (file_prepare_directory($destination)) {
|
||||
// The destination is already a directory, so append the source basename.
|
||||
$destination = file_stream_wrapper_uri_normalize($destination . '/' . basename($source));
|
||||
$destination = file_stream_wrapper_uri_normalize($destination . '/' . drupal_basename($source));
|
||||
}
|
||||
else {
|
||||
// Perhaps $destination is a dir/file?
|
||||
|
@ -958,7 +958,7 @@ function file_destination($destination, $replace) {
|
|||
break;
|
||||
|
||||
case FILE_EXISTS_RENAME:
|
||||
$basename = basename($destination);
|
||||
$basename = drupal_basename($destination);
|
||||
$directory = drupal_dirname($destination);
|
||||
$destination = file_create_filename($basename, $directory);
|
||||
break;
|
||||
|
@ -1033,7 +1033,7 @@ function file_move(stdClass $source, $destination = NULL, $replace = FILE_EXISTS
|
|||
// If we are renaming around an existing file (rather than a directory),
|
||||
// use its basename for the filename.
|
||||
elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
|
||||
$file->filename = basename($destination);
|
||||
$file->filename = drupal_basename($destination);
|
||||
}
|
||||
|
||||
$file = file_save($file);
|
||||
|
@ -1457,7 +1457,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
|
|||
$file = new stdClass();
|
||||
$file->uid = $user->uid;
|
||||
$file->status = 0;
|
||||
$file->filename = trim(basename($_FILES['files']['name'][$source]), '.');
|
||||
$file->filename = trim(drupal_basename($_FILES['files']['name'][$source]), '.');
|
||||
$file->uri = $_FILES['files']['tmp_name'][$source];
|
||||
$file->filemime = file_get_mimetype($file->filename);
|
||||
$file->filesize = $_FILES['files']['size'][$source];
|
||||
|
@ -1855,7 +1855,7 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM
|
|||
$file = new stdClass();
|
||||
$file->fid = NULL;
|
||||
$file->uri = $uri;
|
||||
$file->filename = basename($uri);
|
||||
$file->filename = drupal_basename($uri);
|
||||
$file->filemime = file_get_mimetype($file->uri);
|
||||
$file->uid = $user->uid;
|
||||
$file->status = FILE_STATUS_PERMANENT;
|
||||
|
@ -1871,7 +1871,7 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM
|
|||
// If we are renaming around an existing file (rather than a directory),
|
||||
// use its basename for the filename.
|
||||
elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
|
||||
$file->filename = basename($destination);
|
||||
$file->filename = drupal_basename($destination);
|
||||
}
|
||||
|
||||
return file_save($file);
|
||||
|
@ -2274,6 +2274,35 @@ function drupal_dirname($uri) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filename from a given path.
|
||||
*
|
||||
* PHP's basename() does not properly support streams or filenames beginning
|
||||
* with a non-US-ASCII character.
|
||||
*
|
||||
* @see http://bugs.php.net/bug.php?id=37738
|
||||
* @see basename()
|
||||
*
|
||||
* @ingroup php_wrappers
|
||||
*/
|
||||
function drupal_basename($uri, $suffix = NULL) {
|
||||
$separators = '/';
|
||||
if (DIRECTORY_SEPARATOR != '/') {
|
||||
// For Windows OS add special separator.
|
||||
$separators .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
// Remove right-most slashes when $uri points to directory.
|
||||
$uri = rtrim($uri, $separators);
|
||||
// Returns the trailing part of the $uri starting after one of the directory
|
||||
// separators.
|
||||
$filename = preg_match('@[^' . preg_quote($separators, '@') . ']+$@', $uri, $matches) ? $matches[0] : '';
|
||||
// Cuts off a suffix from the filename.
|
||||
if ($suffix) {
|
||||
$filename = preg_replace('@' . preg_quote($suffix, '@') . '$@', '', $filename);
|
||||
}
|
||||
return $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a directory using Drupal's default mode.
|
||||
*
|
||||
|
@ -2370,7 +2399,7 @@ function drupal_tempnam($directory, $prefix) {
|
|||
$wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
|
||||
|
||||
if ($filename = tempnam($wrapper->getDirectoryPath(), $prefix)) {
|
||||
return $scheme . '://' . basename($filename);
|
||||
return $scheme . '://' . drupal_basename($filename);
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
|
|
|
@ -212,7 +212,7 @@ abstract class FileTransfer {
|
|||
*/
|
||||
protected function copyDirectoryJailed($source, $destination) {
|
||||
if ($this->isDirectory($destination)) {
|
||||
$destination = $destination . '/' . basename($source);
|
||||
$destination = $destination . '/' . drupal_basename($source);
|
||||
}
|
||||
$this->createDirectory($destination);
|
||||
foreach (new RecursiveIteratorIterator(new SkipDotsRecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST) as $filename => $file) {
|
||||
|
@ -303,7 +303,7 @@ abstract class FileTransfer {
|
|||
$chroot = '';
|
||||
while (count($parts)) {
|
||||
$check = implode($parts, '/');
|
||||
if ($this->isFile($check . '/' . basename(__FILE__))) {
|
||||
if ($this->isFile($check . '/' . drupal_basename(__FILE__))) {
|
||||
// Remove the trailing slash.
|
||||
return substr($chroot, 0, -1);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
* generate the same form (or very similar forms) using different $form_ids
|
||||
* can implement hook_forms(), which maps different $form_id values to the
|
||||
* proper form constructor function. Examples may be found in node_forms(),
|
||||
* search_forms(), and user_forms().
|
||||
* and search_forms().
|
||||
* @param ...
|
||||
* Any additional arguments are passed on to the functions called by
|
||||
* drupal_get_form(), including the unique form constructor function. For
|
||||
|
@ -136,7 +136,7 @@ function drupal_get_form($form_id) {
|
|||
* generate the same form (or very similar forms) using different $form_ids
|
||||
* can implement hook_forms(), which maps different $form_id values to the
|
||||
* proper form constructor function. Examples may be found in node_forms(),
|
||||
* search_forms(), and user_forms().
|
||||
* and search_forms().
|
||||
* @param $form_state
|
||||
* An array which stores information about the form. This is passed as a
|
||||
* reference so that the caller can use it to examine what in the form changed
|
||||
|
@ -421,7 +421,7 @@ function form_state_defaults() {
|
|||
* Modules that need to generate the same form (or very similar forms)
|
||||
* using different $form_ids can implement hook_forms(), which maps
|
||||
* different $form_id values to the proper form constructor function. Examples
|
||||
* may be found in node_forms(), search_forms(), and user_forms().
|
||||
* may be found in node_forms() and search_forms().
|
||||
* @param $form_state
|
||||
* A keyed array containing the current state of the form.
|
||||
* @param $old_form
|
||||
|
@ -627,7 +627,7 @@ function form_load_include(&$form_state, $type, $module, $name = NULL) {
|
|||
* Modules that need to generate the same form (or very similar forms)
|
||||
* using different $form_ids can implement hook_forms(), which maps
|
||||
* different $form_id values to the proper form constructor function. Examples
|
||||
* may be found in node_forms(), search_forms(), and user_forms().
|
||||
* may be found in node_forms() and search_forms().
|
||||
* @param $form_state
|
||||
* A keyed array containing the current state of the form. Most important is
|
||||
* the $form_state['values'] collection, a tree of data used to simulate the
|
||||
|
@ -856,7 +856,8 @@ function drupal_process_form($form_id, &$form, &$form_state) {
|
|||
// We'll clear out the cached copies of the form and its stored data
|
||||
// here, as we've finished with them. The in-memory copies are still
|
||||
// here, though.
|
||||
if (!variable_get('cache', 0) && !empty($form_state['values']['form_build_id'])) {
|
||||
$config = config('system.performance');
|
||||
if (!$config->get('cache') && !empty($form_state['values']['form_build_id'])) {
|
||||
cache('form')->delete('form_' . $form_state['values']['form_build_id']);
|
||||
cache('form')->delete('form_state_' . $form_state['values']['form_build_id']);
|
||||
}
|
||||
|
@ -3722,6 +3723,42 @@ function theme_textfield($variables) {
|
|||
return $output . $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for a tel form element.
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
* - element: An associative array containing the properties of the element.
|
||||
* Properties used: #title, #value, #description, #size, #maxlength,
|
||||
* #placeholder, #required, #attributes, #autocomplete_path.
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_tel($variables) {
|
||||
$element = $variables['element'];
|
||||
$element['#attributes']['type'] = 'tel';
|
||||
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder'));
|
||||
_form_set_class($element, array('form-tel'));
|
||||
|
||||
$extra = '';
|
||||
if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
|
||||
drupal_add_library('system', 'drupal.autocomplete');
|
||||
$element['#attributes']['class'][] = 'form-autocomplete';
|
||||
|
||||
$attributes = array();
|
||||
$attributes['type'] = 'hidden';
|
||||
$attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
|
||||
$attributes['value'] = url($element['#autocomplete_path'], array('absolute' => TRUE));
|
||||
$attributes['disabled'] = 'disabled';
|
||||
$attributes['class'][] = 'autocomplete';
|
||||
$extra = '<input' . drupal_attributes($attributes) . ' />';
|
||||
}
|
||||
|
||||
$output = '<input' . drupal_attributes($element['#attributes']) . ' />';
|
||||
|
||||
return $output . $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for a form.
|
||||
*
|
||||
|
|
|
@ -875,7 +875,7 @@ function _locale_import_parse_quoted($string) {
|
|||
*/
|
||||
function _locale_export_get_strings($language = NULL) {
|
||||
if (isset($language)) {
|
||||
$result = db_query("SELECT s.lid, s.source, s.context, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language ORDER BY t.plid, t.plural", array(':language' => $language->language));
|
||||
$result = db_query("SELECT s.lid, s.source, s.context, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language ORDER BY t.plid, t.plural", array(':language' => $language->langcode));
|
||||
}
|
||||
else {
|
||||
$result = db_query("SELECT s.lid, s.source, s.context, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid ORDER BY t.plid, t.plural");
|
||||
|
@ -934,8 +934,8 @@ function _locale_export_po_generate($language = NULL, $strings = array(), $heade
|
|||
$header .= "\"MIME-Version: 1.0\\n\"\n";
|
||||
$header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
|
||||
$header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
|
||||
if (!empty($locale_plurals[$language->language]['formula'])) {
|
||||
$header .= "\"Plural-Forms: nplurals=" . $locale_plurals[$language->language]['plurals'] . "; plural=" . strtr($locale_plurals[$language->language]['formula'], array('$' => '')) . ";\\n\"\n";
|
||||
if (!empty($locale_plurals[$language->langcode]['formula'])) {
|
||||
$header .= "\"Plural-Forms: nplurals=" . $locale_plurals[$language->langcode]['plurals'] . "; plural=" . strtr($locale_plurals[$language->langcode]['formula'], array('$' => '')) . ";\\n\"\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -973,7 +973,7 @@ function _locale_export_po_generate($language = NULL, $strings = array(), $heade
|
|||
$output .= 'msgid_plural ' . _locale_export_string($strings[$plural]['source']);
|
||||
if (isset($language)) {
|
||||
$translation = $string['translation'];
|
||||
for ($i = 0; $i < $locale_plurals[$language->language]['plurals']; $i++) {
|
||||
for ($i = 0; $i < $locale_plurals[$language->langcode]['plurals']; $i++) {
|
||||
$output .= 'msgstr[' . $i . '] ' . _locale_export_string($translation);
|
||||
if ($plural) {
|
||||
$translation = _locale_export_remove_plural($strings[$plural]['translation']);
|
||||
|
@ -1011,7 +1011,7 @@ function _locale_export_po_generate($language = NULL, $strings = array(), $heade
|
|||
function _locale_export_po($language = NULL, $output = NULL) {
|
||||
// Log the export event.
|
||||
if (isset($language)) {
|
||||
$filename = $language->language . '.po';
|
||||
$filename = $language->langcode . '.po';
|
||||
watchdog('locale', 'Exported %locale translation file: %filename.', array('%locale' => $language->name, '%filename' => $filename));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -277,8 +277,7 @@ function install_begin_request(&$install_state) {
|
|||
// because any data put in the cache during the installer is inherently
|
||||
// suspect, due to the fact that Drupal is not fully set up yet.
|
||||
require_once DRUPAL_ROOT . '/core/includes/cache.inc';
|
||||
require_once DRUPAL_ROOT . '/core/includes/cache-install.inc';
|
||||
$conf['cache_default_class'] = 'DrupalFakeCache';
|
||||
$conf['cache_default_class'] = 'Drupal\\Cache\\InstallBackend';
|
||||
|
||||
// Prepare for themed output. We need to run this at the beginning of the
|
||||
// page request to avoid a different theme accidentally getting set. (We also
|
||||
|
@ -993,7 +992,7 @@ function install_settings_form_submit($form, &$form_state) {
|
|||
'required' => TRUE,
|
||||
);
|
||||
|
||||
$settings['drupal_config_key'] = array(
|
||||
$settings['config_signature_key'] = array(
|
||||
'value' => drupal_hash_base64(drupal_random_bytes(55)),
|
||||
'required' => TRUE,
|
||||
);
|
||||
|
@ -1006,14 +1005,14 @@ function install_settings_form_submit($form, &$form_state) {
|
|||
// without hitting install_settings_form_submit() if your settings.php
|
||||
// already has the db stuff in it, and right now in that case your
|
||||
// config directory never gets created. So this needs to be moved elsewhere.
|
||||
$settings['drupal_config_directory_name'] = array(
|
||||
'value' => 'config_' . drupal_hmac_base64('', session_id() . $settings['drupal_config_key']['value'] . $settings['drupal_hash_salt']['value']),
|
||||
$settings['config_directory_name'] = array(
|
||||
'value' => 'config_' . drupal_hmac_base64('', session_id() . $settings['config_signature_key']['value'] . $settings['drupal_hash_salt']['value']),
|
||||
'required' => TRUE,
|
||||
);
|
||||
|
||||
drupal_rewrite_settings($settings);
|
||||
// Actually create the config directory named above.
|
||||
$config_path = conf_path() . '/files/' . $settings['drupal_config_directory_name']['value'];
|
||||
$config_path = conf_path() . '/files/' . $settings['config_directory_name']['value'];
|
||||
if (!file_prepare_directory($config_path, FILE_CREATE_DIRECTORY)) {
|
||||
// How best to handle errors here?
|
||||
};
|
||||
|
@ -1184,10 +1183,21 @@ function install_find_translations() {
|
|||
|
||||
/**
|
||||
* Find installer translations either for a specific langcode or all languages.
|
||||
*
|
||||
* @param $langcode
|
||||
* (optional) The language code corresponding to the language for which we
|
||||
* want to find translation files. If omitted, information on all available
|
||||
* files will be returned.
|
||||
*
|
||||
* @return
|
||||
* An associative array of file information objects keyed by file URIs as
|
||||
* returned by file_scan_directory().
|
||||
*
|
||||
* @see file_scan_directory()
|
||||
*/
|
||||
function install_find_translation_files($langcode = NULL) {
|
||||
$directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations');
|
||||
$files = file_scan_directory($directory, '!install\.' . (!empty($langcode) ? '\.' . preg_quote($langcode, '!') : '[^\.]+') . '\.po$!', array('recurse' => FALSE));
|
||||
$files = file_scan_directory($directory, '!install\.' . (!empty($langcode) ? preg_quote($langcode, '!') : '[^\.]+') . '\.po$!', array('recurse' => FALSE));
|
||||
return $files;
|
||||
}
|
||||
|
||||
|
@ -1296,7 +1306,7 @@ function install_select_language_form($form, &$form_state, $files) {
|
|||
}
|
||||
// Build a list of languages simulated for browser detection.
|
||||
$languages[$file->langcode] = (object) array(
|
||||
'language' => $file->langcode,
|
||||
'langcode' => $file->langcode,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1442,7 +1452,7 @@ function install_import_translations(&$install_state) {
|
|||
// Drupal does not know about this language, so we prefill its values with
|
||||
// our best guess. The user will be able to edit afterwards.
|
||||
$language = (object) array(
|
||||
'language' => $langcode,
|
||||
'langcode' => $langcode,
|
||||
'name' => $langcode,
|
||||
'default' => TRUE,
|
||||
);
|
||||
|
@ -1451,7 +1461,7 @@ function install_import_translations(&$install_state) {
|
|||
else {
|
||||
// A known predefined language, details will be filled in properly.
|
||||
$language = (object) array(
|
||||
'language' => $langcode,
|
||||
'langcode' => $langcode,
|
||||
'default' => TRUE,
|
||||
);
|
||||
language_save($language);
|
||||
|
|
|
@ -329,9 +329,8 @@ function language_provider_invoke($provider_id, $provider = NULL) {
|
|||
if (!isset($results[$provider_id])) {
|
||||
global $user;
|
||||
|
||||
// Get languages grouped by status and select only the enabled ones.
|
||||
$languages = language_list('enabled');
|
||||
$languages = $languages[1];
|
||||
// Get the enabled languages only.
|
||||
$languages = language_list(TRUE);
|
||||
|
||||
if (!isset($provider)) {
|
||||
$providers = language_negotiation_info();
|
||||
|
@ -405,7 +404,7 @@ function language_initialize($type) {
|
|||
* The default language code.
|
||||
*/
|
||||
function language_from_default() {
|
||||
return language_default()->language;
|
||||
return language_default()->langcode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -432,7 +431,7 @@ function language_url_split_prefix($path, $languages) {
|
|||
// Search prefix within enabled languages.
|
||||
$prefixes = locale_language_negotiation_url_prefixes();
|
||||
foreach ($languages as $language) {
|
||||
if (isset($prefixes[$language->language]) && $prefixes[$language->language] == $prefix) {
|
||||
if (isset($prefixes[$language->langcode]) && $prefixes[$language->langcode] == $prefix) {
|
||||
// Rebuild $path with the language removed.
|
||||
return array($language, implode('/', $args));
|
||||
}
|
||||
|
@ -454,17 +453,8 @@ function language_fallback_get_candidates($type = LANGUAGE_TYPE_CONTENT) {
|
|||
$fallback_candidates = &drupal_static(__FUNCTION__);
|
||||
|
||||
if (!isset($fallback_candidates)) {
|
||||
$fallback_candidates = array();
|
||||
|
||||
// Get languages ordered by weight.
|
||||
// Use array keys to avoid duplicated entries.
|
||||
foreach (language_list('weight') as $languages) {
|
||||
foreach ($languages as $language) {
|
||||
$fallback_candidates[$language->language] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$fallback_candidates = array_keys($fallback_candidates);
|
||||
// Get languages ordered by weight, add LANGUAGE_NONE as the last one.
|
||||
$fallback_candidates = array_keys(language_list());
|
||||
$fallback_candidates[] = LANGUAGE_NONE;
|
||||
|
||||
// Let other modules hook in and add/change candidates.
|
||||
|
|
|
@ -113,7 +113,7 @@ const LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN = 1;
|
|||
*/
|
||||
function locale_language_from_interface() {
|
||||
global $language;
|
||||
return isset($language->language) ? $language->language : FALSE;
|
||||
return isset($language->langcode) ? $language->langcode : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,7 +193,7 @@ function locale_language_from_browser($languages) {
|
|||
|
||||
// Find the best match.
|
||||
if ($qvalue > $max_qvalue) {
|
||||
$best_match_langcode = $language->language;
|
||||
$best_match_langcode = $language->langcode;
|
||||
$max_qvalue = $qvalue;
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ function locale_language_from_url($languages) {
|
|||
// path initialization runs after the language bootstrap phase.
|
||||
list($language, $_GET['q']) = language_url_split_prefix(isset($_GET['q']) ? $_GET['q'] : NULL, $languages);
|
||||
if ($language !== FALSE) {
|
||||
$language_url = $language->language;
|
||||
$language_url = $language->langcode;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -282,13 +282,13 @@ function locale_language_from_url($languages) {
|
|||
$domains = locale_language_negotiation_url_domains();
|
||||
foreach ($languages as $language) {
|
||||
// Skip check if the language doesn't have a domain.
|
||||
if (!empty($domains[$language->language])) {
|
||||
if (!empty($domains[$language->langcode])) {
|
||||
// Only compare the domains not the protocols or ports.
|
||||
// Remove protocol and add http:// so parse_url works
|
||||
$host = 'http://' . str_replace(array('http://', 'https://'), '', $domains[$language->language]);
|
||||
$host = 'http://' . str_replace(array('http://', 'https://'), '', $domains[$language->langcode]);
|
||||
$host = parse_url($host, PHP_URL_HOST);
|
||||
if ($_SERVER['HTTP_HOST'] == $host) {
|
||||
$language_url = $language->language;
|
||||
$language_url = $language->langcode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -340,24 +340,26 @@ function locale_language_url_fallback($language = NULL, $language_type = LANGUAG
|
|||
// the default one, otherwise we fall back to an already detected language.
|
||||
$domains = locale_language_negotiation_url_domains();
|
||||
$prefixes = locale_language_negotiation_url_prefixes();
|
||||
if (($prefix && empty($prefixes[$default->language])) || (!$prefix && empty($domains[$default->language]))) {
|
||||
return $default->language;
|
||||
if (($prefix && empty($prefixes[$default->langcode])) || (!$prefix && empty($domains[$default->langcode]))) {
|
||||
return $default->langcode;
|
||||
}
|
||||
else {
|
||||
return $GLOBALS[$language_type]->language;
|
||||
return $GLOBALS[$language_type]->langcode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL language switcher block. Translation links may be provided by
|
||||
* other modules.
|
||||
* Return links for the URL language switcher block.
|
||||
*
|
||||
* Translation links may be provided by other modules.
|
||||
*/
|
||||
function locale_language_switcher_url($type, $path) {
|
||||
$languages = language_list('enabled');
|
||||
// Get the enabled languages only.
|
||||
$languages = language_list(TRUE);
|
||||
$links = array();
|
||||
|
||||
foreach ($languages[1] as $language) {
|
||||
$links[$language->language] = array(
|
||||
foreach ($languages as $language) {
|
||||
$links[$language->langcode] = array(
|
||||
'href' => $path,
|
||||
'title' => $language->name,
|
||||
'language' => $language,
|
||||
|
@ -375,16 +377,17 @@ function locale_language_switcher_session($type, $path) {
|
|||
drupal_add_css(drupal_get_path('module', 'locale') . '/locale.css');
|
||||
|
||||
$param = variable_get('locale_language_negotiation_session_param', 'language');
|
||||
$language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : $GLOBALS[$type]->language;
|
||||
$language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : $GLOBALS[$type]->langcode;
|
||||
|
||||
$languages = language_list('enabled');
|
||||
// Get the enabled languages only.
|
||||
$languages = language_list(TRUE);
|
||||
$links = array();
|
||||
|
||||
$query = $_GET;
|
||||
unset($query['q']);
|
||||
|
||||
foreach ($languages[1] as $language) {
|
||||
$langcode = $language->language;
|
||||
foreach ($languages as $language) {
|
||||
$langcode = $language->langcode;
|
||||
$links[$langcode] = array(
|
||||
'href' => $path,
|
||||
'title' => $language->name,
|
||||
|
@ -413,8 +416,9 @@ function locale_language_url_rewrite_url(&$path, &$options) {
|
|||
$languages = &$drupal_static_fast['languages'];
|
||||
|
||||
if (!isset($languages)) {
|
||||
$languages = language_list('enabled');
|
||||
$languages = array_flip(array_keys($languages[1]));
|
||||
// Get the enabled languages only.
|
||||
$languages = language_list(TRUE);
|
||||
$languages = array_flip(array_keys($languages));
|
||||
}
|
||||
|
||||
// Language can be passed as an option, or we go for current URL language.
|
||||
|
@ -423,7 +427,7 @@ function locale_language_url_rewrite_url(&$path, &$options) {
|
|||
$options['language'] = $language_url;
|
||||
}
|
||||
// We allow only enabled languages here.
|
||||
elseif (!isset($languages[$options['language']->language])) {
|
||||
elseif (!isset($languages[$options['language']->langcode])) {
|
||||
unset($options['language']);
|
||||
return;
|
||||
}
|
||||
|
@ -432,17 +436,17 @@ function locale_language_url_rewrite_url(&$path, &$options) {
|
|||
switch (variable_get('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX)) {
|
||||
case LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN:
|
||||
$domains = locale_language_negotiation_url_domains();
|
||||
if (!empty($domains[$options['language']->language])) {
|
||||
if (!empty($domains[$options['language']->langcode])) {
|
||||
// Ask for an absolute URL with our modified base_url.
|
||||
$options['absolute'] = TRUE;
|
||||
$options['base_url'] = $domains[$options['language']->language];
|
||||
$options['base_url'] = $domains[$options['language']->langcode];
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX:
|
||||
$prefixes = locale_language_negotiation_url_prefixes();
|
||||
if (!empty($prefixes[$options['language']->language])) {
|
||||
$options['prefix'] = $prefixes[$options['language']->language] . '/';
|
||||
if (!empty($prefixes[$options['language']->langcode])) {
|
||||
$options['prefix'] = $prefixes[$options['language']->langcode] . '/';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -488,8 +492,8 @@ function locale_language_url_rewrite_session(&$path, &$options) {
|
|||
if (!isset($query_rewrite)) {
|
||||
global $user;
|
||||
if (!$user->uid) {
|
||||
$languages = language_list('enabled');
|
||||
$languages = $languages[1];
|
||||
// Get the enabled languages only.
|
||||
$languages = language_list(TRUE);
|
||||
$query_param = check_plain(variable_get('locale_language_negotiation_session_param', 'language'));
|
||||
$query_value = isset($_GET[$query_param]) ? check_plain($_GET[$query_param]) : NULL;
|
||||
$query_rewrite = isset($languages[$query_value]) && language_negotiation_get_any(LOCALE_LANGUAGE_NEGOTIATION_SESSION);
|
||||
|
@ -709,7 +713,7 @@ function _locale_rebuild_js($langcode = NULL) {
|
|||
|
||||
// Construct the array for JavaScript translations.
|
||||
// Only add strings with a translation to the translations array.
|
||||
$result = db_query("SELECT s.lid, s.source, s.context, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.location LIKE '%.js%'", array(':language' => $language->language));
|
||||
$result = db_query("SELECT s.lid, s.source, s.context, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.location LIKE '%.js%'", array(':language' => $language->langcode));
|
||||
|
||||
$translations = array();
|
||||
foreach ($result as $data) {
|
||||
|
@ -724,8 +728,8 @@ function _locale_rebuild_js($langcode = NULL) {
|
|||
$data = "Drupal.locale = { ";
|
||||
|
||||
$locale_plurals = variable_get('locale_translation_plurals', array());
|
||||
if (!empty($locale_plurals[$language->language])) {
|
||||
$data .= "'pluralFormula': function (\$n) { return Number({$locale_plurals[$language->language]['formula']}); }, ";
|
||||
if (!empty($locale_plurals[$language->langcode])) {
|
||||
$data .= "'pluralFormula': function (\$n) { return Number({$locale_plurals[$language->langcode]['formula']}); }, ";
|
||||
}
|
||||
|
||||
$data .= "'strings': " . drupal_json_encode($translations) . " };";
|
||||
|
@ -738,23 +742,23 @@ function _locale_rebuild_js($langcode = NULL) {
|
|||
|
||||
// Delete old file, if we have no translations anymore, or a different file to be saved.
|
||||
$locale_javascripts = variable_get('locale_translation_javascript', array());
|
||||
$changed_hash = !isset($locale_javascripts[$language->language]) || ($locale_javascripts[$language->language] != $data_hash);
|
||||
if (!empty($locale_javascripts[$language->language]) && (!$data || $changed_hash)) {
|
||||
file_unmanaged_delete($dir . '/' . $language->language . '_' . $locale_javascripts[$language->language] . '.js');
|
||||
$locale_javascripts[$language->language] = '';
|
||||
$changed_hash = !isset($locale_javascripts[$language->langcode]) || ($locale_javascripts[$language->langcode] != $data_hash);
|
||||
if (!empty($locale_javascripts[$language->langcode]) && (!$data || $changed_hash)) {
|
||||
file_unmanaged_delete($dir . '/' . $language->langcode . '_' . $locale_javascripts[$language->langcode] . '.js');
|
||||
$locale_javascripts[$language->langcode] = '';
|
||||
$status = 'deleted';
|
||||
}
|
||||
|
||||
// Only create a new file if the content has changed or the original file got
|
||||
// lost.
|
||||
$dest = $dir . '/' . $language->language . '_' . $data_hash . '.js';
|
||||
$dest = $dir . '/' . $language->langcode . '_' . $data_hash . '.js';
|
||||
if ($data && ($changed_hash || !file_exists($dest))) {
|
||||
// Ensure that the directory exists and is writable, if possible.
|
||||
file_prepare_directory($dir, FILE_CREATE_DIRECTORY);
|
||||
|
||||
// Save the file.
|
||||
if (file_unmanaged_save_data($data, $dest)) {
|
||||
$locale_javascripts[$language->language] = $data_hash;
|
||||
$locale_javascripts[$language->langcode] = $data_hash;
|
||||
// If we deleted a previous version of the file and we replace it with a
|
||||
// new one we have an update.
|
||||
if ($status == 'deleted') {
|
||||
|
@ -772,7 +776,7 @@ function _locale_rebuild_js($langcode = NULL) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
$locale_javascripts[$language->language] = '';
|
||||
$locale_javascripts[$language->langcode] = '';
|
||||
$status = 'error';
|
||||
}
|
||||
}
|
||||
|
@ -790,7 +794,7 @@ function _locale_rebuild_js($langcode = NULL) {
|
|||
watchdog('locale', 'Updated JavaScript translation file for the language %language.', array('%language' => $language->name));
|
||||
return TRUE;
|
||||
case 'rebuilt':
|
||||
watchdog('locale', 'JavaScript translation file %file.js was lost.', array('%file' => $locale_javascripts[$language->language]), WATCHDOG_WARNING);
|
||||
watchdog('locale', 'JavaScript translation file %file.js was lost.', array('%file' => $locale_javascripts[$language->langcode]), WATCHDOG_WARNING);
|
||||
// Proceed to the 'created' case as the JavaScript translation file has
|
||||
// been created again.
|
||||
case 'created':
|
||||
|
|
|
@ -63,7 +63,7 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
|
|||
* $message['send'] = FALSE;
|
||||
* break;
|
||||
* }
|
||||
* $langcode = $message['language']->language;
|
||||
* $langcode = $message['language']->langcode;
|
||||
* $message['subject'] = t('Notification from !site', $variables, array('langcode' => $langcode));
|
||||
* $message['body'][] = t("Dear !username\n\nThere is new content available on the site.", $variables, array('langcode' => $langcode));
|
||||
* break;
|
||||
|
|
|
@ -1100,7 +1100,7 @@ function menu_tree_all_data($menu_name, $link = NULL, $max_depth = NULL) {
|
|||
// Use $mlid as a flag for whether the data being loaded is for the whole tree.
|
||||
$mlid = isset($link['mlid']) ? $link['mlid'] : 0;
|
||||
// Generate a cache ID (cid) specific for this $menu_name, $link, $language, and depth.
|
||||
$cid = 'links:' . $menu_name . ':all:' . $mlid . ':' . $GLOBALS['language']->language . ':' . (int) $max_depth;
|
||||
$cid = 'links:' . $menu_name . ':all:' . $mlid . ':' . $GLOBALS['language']->langcode . ':' . (int) $max_depth;
|
||||
|
||||
if (!isset($tree[$cid])) {
|
||||
// If the static variable doesn't have the data, check {cache_menu}.
|
||||
|
@ -1214,7 +1214,7 @@ function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail =
|
|||
$max_depth = min($max_depth, MENU_MAX_DEPTH);
|
||||
}
|
||||
// Generate a cache ID (cid) specific for this page.
|
||||
$cid = 'links:' . $menu_name . ':page:' . $item['href'] . ':' . $GLOBALS['language']->language . ':' . (int) $item['access'] . ':' . (int) $max_depth;
|
||||
$cid = 'links:' . $menu_name . ':page:' . $item['href'] . ':' . $GLOBALS['language']->langcode . ':' . (int) $item['access'] . ':' . (int) $max_depth;
|
||||
// If we are asked for the active trail only, and $menu_name has not been
|
||||
// built and cached for this page yet, then this likely means that it
|
||||
// won't be built anymore, as this function is invoked from
|
||||
|
@ -1366,7 +1366,7 @@ function _menu_build_tree($menu_name, array $parameters = array()) {
|
|||
if (isset($parameters['expanded'])) {
|
||||
sort($parameters['expanded']);
|
||||
}
|
||||
$tree_cid = 'links:' . $menu_name . ':tree-data:' . $GLOBALS['language']->language . ':' . hash('sha256', serialize($parameters));
|
||||
$tree_cid = 'links:' . $menu_name . ':tree-data:' . $GLOBALS['language']->langcode . ':' . hash('sha256', serialize($parameters));
|
||||
|
||||
// If we do not have this tree in the static cache, check {cache_menu}.
|
||||
if (!isset($trees[$tree_cid])) {
|
||||
|
|
|
@ -523,11 +523,6 @@ function module_disable($module_list, $disable_dependents = TRUE) {
|
|||
|
||||
foreach ($module_list as $module) {
|
||||
if (module_exists($module)) {
|
||||
// Check if node_access table needs rebuilding.
|
||||
if (!node_access_needs_rebuild() && module_hook($module, 'node_grants')) {
|
||||
node_access_needs_rebuild(TRUE);
|
||||
}
|
||||
|
||||
module_load_install($module);
|
||||
module_invoke($module, 'disable');
|
||||
db_update('system')
|
||||
|
@ -552,12 +547,6 @@ function module_disable($module_list, $disable_dependents = TRUE) {
|
|||
registry_update();
|
||||
_system_update_bootstrap_status();
|
||||
}
|
||||
|
||||
// If there remains no more node_access module, rebuilding will be
|
||||
// straightforward, we can do it right now.
|
||||
if (node_access_needs_rebuild() && count(module_implements('node_grants')) == 0) {
|
||||
node_access_rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,7 +16,7 @@ function drupal_path_initialize() {
|
|||
// Ensure $_GET['q'] is set before calling drupal_normal_path(), to support
|
||||
// path caching with hook_url_inbound_alter().
|
||||
if (empty($_GET['q'])) {
|
||||
$_GET['q'] = variable_get('site_frontpage', 'node');
|
||||
$_GET['q'] = variable_get('site_frontpage', 'user');
|
||||
}
|
||||
$_GET['q'] = drupal_get_normal_path($_GET['q']);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ function drupal_path_initialize() {
|
|||
* - source: return the Drupal system URL for a path alias (if one exists).
|
||||
* @param $path
|
||||
* The path to investigate for corresponding aliases or system URLs.
|
||||
* @param $path_language
|
||||
* @param $langcode
|
||||
* Optional language code to search the path with. Defaults to the page language.
|
||||
* If there's no path defined for that language it will search paths without
|
||||
* language.
|
||||
|
@ -42,7 +42,7 @@ function drupal_path_initialize() {
|
|||
* Either a Drupal system path, an aliased path, or FALSE if no path was
|
||||
* found.
|
||||
*/
|
||||
function drupal_lookup_path($action, $path = '', $path_language = NULL) {
|
||||
function drupal_lookup_path($action, $path = '', $langcode = NULL) {
|
||||
global $language_url;
|
||||
// Use the advanced drupal_static() pattern, since this is called very often.
|
||||
static $drupal_static_fast;
|
||||
|
@ -74,7 +74,7 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) {
|
|||
// language. If we used a language different from the one conveyed by the
|
||||
// requested URL, we might end up being unable to check if there is a path
|
||||
// alias matching the URL path.
|
||||
$path_language = $path_language ? $path_language : $language_url->language;
|
||||
$langcode = $langcode ? $langcode : $language_url->langcode;
|
||||
|
||||
if ($action == 'wipe') {
|
||||
$cache = array();
|
||||
|
@ -87,7 +87,7 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) {
|
|||
if (!empty($cache['first_call'])) {
|
||||
$cache['first_call'] = FALSE;
|
||||
|
||||
$cache['map'][$path_language] = array();
|
||||
$cache['map'][$langcode] = array();
|
||||
// Load system paths from cache.
|
||||
$cid = current_path();
|
||||
if ($cached = cache('path')->get($cid)) {
|
||||
|
@ -95,7 +95,7 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) {
|
|||
// Now fetch the aliases corresponding to these system paths.
|
||||
$args = array(
|
||||
':system' => $cache['system_paths'],
|
||||
':language' => $path_language,
|
||||
':langcode' => $langcode,
|
||||
':language_none' => LANGUAGE_NONE,
|
||||
);
|
||||
// Always get the language-specific alias before the language-neutral
|
||||
|
@ -105,25 +105,25 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) {
|
|||
// the most recently created alias for each source. Subsequent queries
|
||||
// using fetchField() must use pid DESC to have the same effect.
|
||||
// For performance reasons, the query builder is not used here.
|
||||
if ($path_language == LANGUAGE_NONE) {
|
||||
if ($langcode == LANGUAGE_NONE) {
|
||||
// Prevent PDO from complaining about a token the query doesn't use.
|
||||
unset($args[':language']);
|
||||
$result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language = :language_none ORDER BY pid ASC', $args);
|
||||
unset($args[':langcode']);
|
||||
$result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode = :language_none ORDER BY pid ASC', $args);
|
||||
}
|
||||
elseif ($path_language < LANGUAGE_NONE) {
|
||||
$result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language IN (:language, :language_none) ORDER BY language ASC, pid ASC', $args);
|
||||
elseif ($langcode < LANGUAGE_NONE) {
|
||||
$result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :language_none) ORDER BY langcode ASC, pid ASC', $args);
|
||||
}
|
||||
else {
|
||||
$result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language IN (:language, :language_none) ORDER BY language DESC, pid ASC', $args);
|
||||
$result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :language_none) ORDER BY langcode DESC, pid ASC', $args);
|
||||
}
|
||||
$cache['map'][$path_language] = $result->fetchAllKeyed();
|
||||
$cache['map'][$langcode] = $result->fetchAllKeyed();
|
||||
// Keep a record of paths with no alias to avoid querying twice.
|
||||
$cache['no_aliases'][$path_language] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$path_language])));
|
||||
$cache['no_aliases'][$langcode] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$langcode])));
|
||||
}
|
||||
}
|
||||
// If the alias has already been loaded, return it.
|
||||
if (isset($cache['map'][$path_language][$path])) {
|
||||
return $cache['map'][$path_language][$path];
|
||||
if (isset($cache['map'][$langcode][$path])) {
|
||||
return $cache['map'][$langcode][$path];
|
||||
}
|
||||
// Check the path whitelist, if the top_level part before the first /
|
||||
// is not in the list, then there is no need to do anything further,
|
||||
|
@ -132,57 +132,57 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) {
|
|||
return FALSE;
|
||||
}
|
||||
// For system paths which were not cached, query aliases individually.
|
||||
elseif (!isset($cache['no_aliases'][$path_language][$path])) {
|
||||
elseif (!isset($cache['no_aliases'][$langcode][$path])) {
|
||||
$args = array(
|
||||
':source' => $path,
|
||||
':language' => $path_language,
|
||||
':langcode' => $langcode,
|
||||
':language_none' => LANGUAGE_NONE,
|
||||
);
|
||||
// See the queries above.
|
||||
if ($path_language == LANGUAGE_NONE) {
|
||||
unset($args[':language']);
|
||||
$alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language = :language_none ORDER BY pid DESC", $args)->fetchField();
|
||||
if ($langcode == LANGUAGE_NONE) {
|
||||
unset($args[':langcode']);
|
||||
$alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode = :language_none ORDER BY pid DESC", $args)->fetchField();
|
||||
}
|
||||
elseif ($path_language > LANGUAGE_NONE) {
|
||||
$alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language IN (:language, :language_none) ORDER BY language DESC, pid DESC", $args)->fetchField();
|
||||
elseif ($langcode > LANGUAGE_NONE) {
|
||||
$alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :language_none) ORDER BY langcode DESC, pid DESC", $args)->fetchField();
|
||||
}
|
||||
else {
|
||||
$alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language IN (:language, :language_none) ORDER BY language ASC, pid DESC", $args)->fetchField();
|
||||
$alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :language_none) ORDER BY langcode ASC, pid DESC", $args)->fetchField();
|
||||
}
|
||||
$cache['map'][$path_language][$path] = $alias;
|
||||
$cache['map'][$langcode][$path] = $alias;
|
||||
return $alias;
|
||||
}
|
||||
}
|
||||
// Check $no_source for this $path in case we've already determined that there
|
||||
// isn't a path that has this alias
|
||||
elseif ($action == 'source' && !isset($cache['no_source'][$path_language][$path])) {
|
||||
elseif ($action == 'source' && !isset($cache['no_source'][$langcode][$path])) {
|
||||
// Look for the value $path within the cached $map
|
||||
$source = FALSE;
|
||||
if (!isset($cache['map'][$path_language]) || !($source = array_search($path, $cache['map'][$path_language]))) {
|
||||
if (!isset($cache['map'][$langcode]) || !($source = array_search($path, $cache['map'][$langcode]))) {
|
||||
$args = array(
|
||||
':alias' => $path,
|
||||
':language' => $path_language,
|
||||
':langcode' => $langcode,
|
||||
':language_none' => LANGUAGE_NONE,
|
||||
);
|
||||
// See the queries above.
|
||||
if ($path_language == LANGUAGE_NONE) {
|
||||
unset($args[':language']);
|
||||
$result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language = :language_none ORDER BY pid DESC", $args);
|
||||
if ($langcode == LANGUAGE_NONE) {
|
||||
unset($args[':langcode']);
|
||||
$result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode = :language_none ORDER BY pid DESC", $args);
|
||||
}
|
||||
elseif ($path_language > LANGUAGE_NONE) {
|
||||
$result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language IN (:language, :language_none) ORDER BY language DESC, pid DESC", $args);
|
||||
elseif ($langcode > LANGUAGE_NONE) {
|
||||
$result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :language_none) ORDER BY langcode DESC, pid DESC", $args);
|
||||
}
|
||||
else {
|
||||
$result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language IN (:language, :language_none) ORDER BY language ASC, pid DESC", $args);
|
||||
$result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :language_none) ORDER BY langcode ASC, pid DESC", $args);
|
||||
}
|
||||
if ($source = $result->fetchField()) {
|
||||
$cache['map'][$path_language][$source] = $path;
|
||||
$cache['map'][$langcode][$source] = $path;
|
||||
}
|
||||
else {
|
||||
// We can't record anything into $map because we do not have a valid
|
||||
// index and there is no need because we have not learned anything
|
||||
// about any Drupal path. Thus cache to $no_source.
|
||||
$cache['no_source'][$path_language][$path] = TRUE;
|
||||
$cache['no_source'][$langcode][$path] = TRUE;
|
||||
}
|
||||
}
|
||||
return $source;
|
||||
|
@ -225,20 +225,20 @@ function drupal_cache_system_paths() {
|
|||
*
|
||||
* @param $path
|
||||
* An internal Drupal path.
|
||||
* @param $path_language
|
||||
* @param $langcode
|
||||
* An optional language code to look up the path in.
|
||||
*
|
||||
* @return
|
||||
* An aliased path if one was found, or the original path if no alias was
|
||||
* found.
|
||||
*/
|
||||
function drupal_get_path_alias($path = NULL, $path_language = NULL) {
|
||||
function drupal_get_path_alias($path = NULL, $langcode = NULL) {
|
||||
// If no path is specified, use the current page's path.
|
||||
if ($path == NULL) {
|
||||
$path = $_GET['q'];
|
||||
}
|
||||
$result = $path;
|
||||
if ($alias = drupal_lookup_path('alias', $path, $path_language)) {
|
||||
if ($alias = drupal_lookup_path('alias', $path, $langcode)) {
|
||||
$result = $alias;
|
||||
}
|
||||
return $result;
|
||||
|
@ -249,18 +249,18 @@ function drupal_get_path_alias($path = NULL, $path_language = NULL) {
|
|||
*
|
||||
* @param $path
|
||||
* A Drupal path alias.
|
||||
* @param $path_language
|
||||
* @param $langcode
|
||||
* An optional language code to look up the path in.
|
||||
*
|
||||
* @return
|
||||
* The internal path represented by the alias, or the original alias if no
|
||||
* internal path was found.
|
||||
*/
|
||||
function drupal_get_normal_path($path, $path_language = NULL) {
|
||||
function drupal_get_normal_path($path, $langcode = NULL) {
|
||||
$original_path = $path;
|
||||
|
||||
// Lookup the path alias first.
|
||||
if ($source = drupal_lookup_path('source', $path, $path_language)) {
|
||||
if ($source = drupal_lookup_path('source', $path, $langcode)) {
|
||||
$path = $source;
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ function drupal_get_normal_path($path, $path_language = NULL) {
|
|||
// of hook_url_outbound_alter().
|
||||
foreach (array_reverse(module_implements('url_inbound_alter')) as $module) {
|
||||
$function = $module . '_url_inbound_alter';
|
||||
$function($path, $original_path, $path_language);
|
||||
$function($path, $original_path, $langcode);
|
||||
}
|
||||
|
||||
return $path;
|
||||
|
@ -292,7 +292,7 @@ function drupal_is_front_page() {
|
|||
if (!isset($is_front_page)) {
|
||||
// As drupal_path_initialize updates $_GET['q'] with the 'site_frontpage' path,
|
||||
// we can check it against the 'site_frontpage' variable.
|
||||
$is_front_page = ($_GET['q'] == variable_get('site_frontpage', 'node'));
|
||||
$is_front_page = ($_GET['q'] == variable_get('site_frontpage', 'user'));
|
||||
}
|
||||
|
||||
return $is_front_page;
|
||||
|
@ -323,7 +323,7 @@ function drupal_match_path($path, $patterns) {
|
|||
$replacements = array(
|
||||
'|',
|
||||
'.*',
|
||||
'\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\2'
|
||||
'\1' . preg_quote(variable_get('site_frontpage', 'user'), '/') . '\2'
|
||||
);
|
||||
$patterns_quoted = preg_quote($patterns, '/');
|
||||
$regexps[$patterns] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/';
|
||||
|
@ -398,7 +398,7 @@ function drupal_path_alias_whitelist_rebuild($source = NULL) {
|
|||
* - source: The internal system path.
|
||||
* - alias: The URL alias.
|
||||
* - pid: Unique path alias identifier.
|
||||
* - language: The language of the alias.
|
||||
* - langcode: The language code of the alias.
|
||||
*/
|
||||
function path_load($conditions) {
|
||||
if (is_numeric($conditions)) {
|
||||
|
@ -428,10 +428,10 @@ function path_load($conditions) {
|
|||
* - source: The internal system path.
|
||||
* - alias: The URL alias.
|
||||
* - pid: (optional) Unique path alias identifier.
|
||||
* - language: (optional) The language of the alias.
|
||||
* - langcode: (optional) The language code of the alias.
|
||||
*/
|
||||
function path_save(&$path) {
|
||||
$path += array('pid' => NULL, 'language' => LANGUAGE_NONE);
|
||||
$path += array('pid' => NULL, 'langcode' => LANGUAGE_NONE);
|
||||
|
||||
// Insert or update the alias.
|
||||
$status = drupal_write_record('url_alias', $path, (!empty($path['pid']) ? 'pid' : array()));
|
||||
|
|
|
@ -317,7 +317,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
}
|
||||
|
||||
$extension = '';
|
||||
$file_parts = explode('.', basename($uri));
|
||||
$file_parts = explode('.', drupal_basename($uri));
|
||||
|
||||
// Remove the first part: a full filename should not match an extension.
|
||||
array_shift($file_parts);
|
||||
|
@ -377,7 +377,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
|
|||
$realpath = realpath($path);
|
||||
if (!$realpath) {
|
||||
// This file does not yet exist.
|
||||
$realpath = realpath(dirname($path)) . '/' . basename($path);
|
||||
$realpath = realpath(dirname($path)) . '/' . drupal_basename($path);
|
||||
}
|
||||
$directory = realpath($this->getDirectoryPath());
|
||||
if (!$realpath || !$directory || strpos($realpath, $directory) !== 0) {
|
||||
|
|
|
@ -372,23 +372,31 @@ class ThemeRegistry Extends DrupalCacheArray {
|
|||
$data = $cached->data;
|
||||
}
|
||||
else {
|
||||
$complete_registry = theme_get_registry();
|
||||
// If there is no runtime cache stored, fetch the full theme registry,
|
||||
// but then initialize each value to NULL. This allows offsetExists()
|
||||
// to function correctly on non-registered theme hooks without triggering
|
||||
// a call to resolveCacheMiss().
|
||||
$data = $this->initializeRegistry();
|
||||
if ($this->persistable) {
|
||||
// If there is no runtime cache stored, fetch the full theme registry,
|
||||
// but then initialize each value to NULL. This allows
|
||||
// offsetExists() to function correctly on non-registered theme hooks
|
||||
// without triggering a call to resolveCacheMiss().
|
||||
$data = array_fill_keys(array_keys($complete_registry), NULL);
|
||||
$this->set($this->cid, $data, $this->bin);
|
||||
$this->completeRegistry = $complete_registry;
|
||||
}
|
||||
else {
|
||||
$data = $complete_registry;
|
||||
$this->set($data);
|
||||
}
|
||||
}
|
||||
$this->storage = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the full theme registry.
|
||||
*
|
||||
* @return
|
||||
* An array with the keys of the full theme registry, but the values
|
||||
* initialized to NULL.
|
||||
*/
|
||||
function initializeRegistry() {
|
||||
$this->completeRegistry = theme_get_registry();
|
||||
|
||||
return array_fill_keys(array_keys($this->completeRegistry), NULL);
|
||||
}
|
||||
|
||||
public function offsetExists($offset) {
|
||||
// Since the theme registry allows for theme hooks to be requested that
|
||||
// are not registered, just check the existence of the key in the registry.
|
||||
|
@ -420,15 +428,19 @@ class ThemeRegistry Extends DrupalCacheArray {
|
|||
return $this->storage[$offset];
|
||||
}
|
||||
|
||||
public function set($cid, $data, $bin, $lock = TRUE) {
|
||||
$lock_name = $cid . ':' . $bin;
|
||||
public function set($data, $lock = TRUE) {
|
||||
$lock_name = $this->cid . ':' . $this->bin;
|
||||
if (!$lock || lock_acquire($lock_name)) {
|
||||
if ($cached = cache($bin)->get($cid)) {
|
||||
if ($cached = cache($this->bin)->get($this->cid)) {
|
||||
// Use array merge instead of union so that filled in values in $data
|
||||
// overwrite empty values in the current cache.
|
||||
$data = array_merge($cached->data, $data);
|
||||
}
|
||||
cache($bin)->set($cid, $data);
|
||||
else {
|
||||
$registry = $this->initializeRegistry();
|
||||
$data = array_merge($registry, $data);
|
||||
}
|
||||
cache($this->bin)->set($this->cid, $data);
|
||||
if ($lock) {
|
||||
lock_release($lock_name);
|
||||
}
|
||||
|
@ -1531,7 +1543,7 @@ function theme_link($variables) {
|
|||
* @param $variables
|
||||
* An associative array containing:
|
||||
* - links: An associative array of links to be themed. The key for each link
|
||||
* is used as its css class. Each link should be itself an array, with the
|
||||
* is used as its CSS class. Each link should be itself an array, with the
|
||||
* following elements:
|
||||
* - title: The link text.
|
||||
* - href: The link URL. If omitted, the 'title' is shown as a plain text
|
||||
|
@ -1612,7 +1624,7 @@ function theme_links($variables) {
|
|||
// Handle links.
|
||||
if (isset($link['href'])) {
|
||||
$is_current_path = ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()));
|
||||
$is_current_language = (empty($link['language']) || $link['language']->language == $language_url->language);
|
||||
$is_current_language = (empty($link['language']) || $link['language']->langcode == $language_url->langcode);
|
||||
if ($is_current_path && $is_current_language) {
|
||||
$class[] = 'active';
|
||||
}
|
||||
|
@ -2341,7 +2353,7 @@ function template_preprocess_html(&$variables) {
|
|||
$variables['body_attributes_array'] = array();
|
||||
|
||||
// HTML element attributes.
|
||||
$variables['html_attributes_array']['lang'] = $GLOBALS['language']->language;
|
||||
$variables['html_attributes_array']['lang'] = $GLOBALS['language']->langcode;
|
||||
$variables['html_attributes_array']['dir'] = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
|
||||
|
||||
// Add favicon.
|
||||
|
|
|
@ -77,8 +77,13 @@
|
|||
* Text with tokens replaced.
|
||||
*/
|
||||
function token_replace($text, array $data = array(), array $options = array()) {
|
||||
$text_tokens = token_scan($text);
|
||||
if (empty($text_tokens)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$replacements = array();
|
||||
foreach (token_scan($text) as $type => $tokens) {
|
||||
foreach ($text_tokens as $type => $tokens) {
|
||||
$replacements += token_generate($type, $tokens, $data, $options);
|
||||
if (!empty($options['clear'])) {
|
||||
$replacements += array_fill_keys($tokens, '');
|
||||
|
|
|
@ -321,7 +321,7 @@ function truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis =
|
|||
|
||||
if ($add_ellipsis) {
|
||||
// Truncate ellipsis in case $max_length is small.
|
||||
$ellipsis = drupal_substr(t('...'), 0, $max_length);
|
||||
$ellipsis = drupal_substr(t('…'), 0, $max_length);
|
||||
$max_length -= drupal_strlen($ellipsis);
|
||||
$max_length = max($max_length, 0);
|
||||
}
|
||||
|
@ -349,6 +349,9 @@ function truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis =
|
|||
}
|
||||
|
||||
if ($add_ellipsis) {
|
||||
// If we're adding an ellipsis, remove any trailing periods.
|
||||
$string = rtrim($string, '.');
|
||||
|
||||
$string .= $ellipsis;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,26 @@ function update_prepare_d8_bootstrap() {
|
|||
if ($has_required_schema) {
|
||||
// Update the environment for the language bootstrap if needed.
|
||||
update_prepare_d8_language();
|
||||
|
||||
// Change language column to langcode in url_alias.
|
||||
if (db_table_exists('url_alias') && db_field_exists('url_alias', 'language')) {
|
||||
db_drop_index('url_alias', 'alias_language_pid');
|
||||
db_drop_index('url_alias', 'source_language_pid');
|
||||
$langcode_spec = array(
|
||||
'description' => "The language code this alias is for; if 'und', the alias will be used for unknown languages. Each Drupal path can have an alias for each supported language.",
|
||||
'type' => 'varchar',
|
||||
'length' => 12,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
);
|
||||
$langcode_indexes = array('indexes' =>
|
||||
array(
|
||||
'alias_langcode_pid' => array('alias', 'langcode', 'pid'),
|
||||
'source_langcode_pid' => array('source', 'langcode', 'pid'),
|
||||
),
|
||||
);
|
||||
db_change_field('url_alias', 'language', 'langcode', $langcode_spec, $langcode_indexes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +161,17 @@ function update_prepare_d8_language() {
|
|||
db_drop_field('languages', 'domain');
|
||||
db_drop_field('languages', 'native');
|
||||
|
||||
// Rename language column to langcode and set it again as the primary key.
|
||||
db_drop_primary_key('languages');
|
||||
$langcode_spec = array(
|
||||
'type' => 'varchar',
|
||||
'length' => 12,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => "Language code, e.g. 'de' or 'en-US'.",
|
||||
);
|
||||
db_change_field('languages', 'language', 'langcode', $langcode_spec, array('primary key' => array('langcode')));
|
||||
|
||||
// Rename the languages table to language.
|
||||
db_rename_table('languages', 'language');
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ class Updater {
|
|||
return FALSE;
|
||||
}
|
||||
foreach ($info_files as $info_file) {
|
||||
if (drupal_substr($info_file->filename, 0, -5) == basename($directory)) {
|
||||
if (drupal_substr($info_file->filename, 0, -5) == drupal_basename($directory)) {
|
||||
// Info file Has the same name as the directory, return it.
|
||||
return $info_file->uri;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ class Updater {
|
|||
* The name of the project.
|
||||
*/
|
||||
public static function getProjectName($directory) {
|
||||
return basename($directory);
|
||||
return drupal_basename($directory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -318,7 +318,7 @@ Drupal.ajax.prototype.beforeSerialize = function (element, options) {
|
|||
Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) {
|
||||
// This function is left empty to make it simple to override for modules
|
||||
// that wish to add functionality here.
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare the Ajax request before it is sent.
|
||||
|
|
|
@ -164,7 +164,7 @@ Drupal.formatString = function(str, args) {
|
|||
str = str.replace(key, args[key]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate strings to the page language or a given language.
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
// iepp v2.1pre @jon_neal & @aFarkas github.com/aFarkas/iepp
|
||||
// html5shiv @rem remysharp.com/html5-enabling-script
|
||||
// Dual licensed under the MIT or GPL Version 2 licenses
|
||||
/*@cc_on(function(a,b){function r(a){var b=-1;while(++b<f)a.createElement(e[b])}if(!window.attachEvent||!b.createStyleSheet||!function(){var a=document.createElement("div");return a.innerHTML="<elem></elem>",a.childNodes.length!==1}())return;a.iepp=a.iepp||{};var c=a.iepp,d=c.html5elements||"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|subline|summary|time|video",e=d.split("|"),f=e.length,g=new RegExp("(^|\\s)("+d+")","gi"),h=new RegExp("<(/*)("+d+")","gi"),i=/^\s*[\{\}]\s*$/,j=new RegExp("(^|[^\\n]*?\\s)("+d+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),k=b.createDocumentFragment(),l=b.documentElement,m=b.getElementsByTagName("script")[0].parentNode,n=b.createElement("body"),o=b.createElement("style"),p=/print|all/,q;c.getCSS=function(a,b){try{if(a+""===undefined)return""}catch(d){return""}var e=-1,f=a.length,g,h=[];while(++e<f){g=a[e];if(g.disabled)continue;b=g.media||b,p.test(b)&&h.push(c.getCSS(g.imports,b),g.cssText),b="all"}return h.join("")},c.parseCSS=function(a){var b=[],c;while((c=j.exec(a))!=null)b.push(((i.exec(c[1])?"\n":c[1])+c[2]+c[3]).replace(g,"$1.iepp-$2")+c[4]);return b.join("\n")},c.writeHTML=function(){var a=-1;q=q||b.body;while(++a<f){var c=b.getElementsByTagName(e[a]),d=c.length,g=-1;while(++g<d)c[g].className.indexOf("iepp-")<0&&(c[g].className+=" iepp-"+e[a])}k.appendChild(q),l.appendChild(n),n.className=q.className,n.id=q.id,n.innerHTML=q.innerHTML.replace(h,"<$1font")},c._beforePrint=function(){if(c.disablePP)return;o.styleSheet.cssText=c.parseCSS(c.getCSS(b.styleSheets,"all")),c.writeHTML()},c.restoreHTML=function(){if(c.disablePP)return;n.swapNode(q)},c._afterPrint=function(){c.restoreHTML(),o.styleSheet.cssText=""},r(b),r(k);if(c.disablePP)return;m.insertBefore(o,m.firstChild),o.media="print",o.className="iepp-printshim",a.attachEvent("onbeforeprint",c._beforePrint),a.attachEvent("onafterprint",c._afterPrint)})(this,document)@*/
|
||||
// HTML5 Shiv v3 | @jon_neal @afarkas @rem | MIT/GPL2 Licensed
|
||||
// Uncompressed source: https://github.com/aFarkas/html5shiv
|
||||
(function(a,b){var c=function(a){return a.innerHTML="<x-element></x-element>",a.childNodes.length===1}(b.createElement("a")),d=function(a,b,c){return b.appendChild(a),(c=(c?c(a):a.currentStyle).display)&&b.removeChild(a)&&c==="block"}(b.createElement("nav"),b.documentElement,a.getComputedStyle),e={elements:"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),shivDocument:function(a){a=a||b;if(a.documentShived)return;a.documentShived=!0;var f=a.createElement,g=a.createDocumentFragment,h=a.getElementsByTagName("head")[0],i=function(a){f(a)};c||(e.elements.join(" ").replace(/\w+/g,i),a.createElement=function(a){var b=f(a);return b.canHaveChildren&&e.shivDocument(b.document),b},a.createDocumentFragment=function(){return e.shivDocument(g())});if(!d&&h){var j=f("div");j.innerHTML=["x<style>","article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}","audio{display:none}","canvas,video{display:inline-block;*display:inline;*zoom:1}","[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}","mark{background:#FF0;color:#000}","</style>"].join(""),h.insertBefore(j.lastChild,h.firstChild)}return a}};e.shivDocument(b),a.html5=e})(this,document)
|
||||
|
|
|
@ -26,7 +26,7 @@ Drupal.behaviors.machineName = {
|
|||
var $source = $(source_id, context).addClass('machine-name-source');
|
||||
var $target = $(options.target, context).addClass('machine-name-target');
|
||||
var $suffix = $(options.suffix, context);
|
||||
var $wrapper = $target.parents('.form-item:first');
|
||||
var $wrapper = $target.closest('.form-item');
|
||||
// All elements have to exist.
|
||||
if (!$source.length || !$target.length || !$suffix.length || !$wrapper.length) {
|
||||
return;
|
||||
|
|
|
@ -249,9 +249,18 @@ states.Trigger.states = {
|
|||
|
||||
checked: {
|
||||
'change': function () {
|
||||
// Use prop() here as we want a boolean of the checkbox state. See
|
||||
// http://api.jquery.com/prop/ for more information.
|
||||
return this.prop('checked');
|
||||
// prop() and attr() only takes the first element into account. To support
|
||||
// selectors matching multiple checkboxes, iterate over all and return
|
||||
// whether any is checked.
|
||||
var checked = false;
|
||||
this.each(function () {
|
||||
// Use prop() here as we want a boolean of the checkbox state.
|
||||
// @see http://api.jquery.com/prop/
|
||||
checked = $(this).prop('checked');
|
||||
// Break the each() loop if this is checked.
|
||||
return !checked;
|
||||
});
|
||||
return checked;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ Drupal.tableDrag.prototype.initColumns = function () {
|
|||
var field = $('.' + this.tableSettings[group][d].target + ':first', this.table);
|
||||
if (field.size() && this.tableSettings[group][d].hidden) {
|
||||
var hidden = this.tableSettings[group][d].hidden;
|
||||
var cell = field.parents('td:first');
|
||||
var cell = field.closest('td');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -744,7 +744,7 @@ Drupal.tableDrag.prototype.updateField = function (changedRow, group) {
|
|||
switch (rowSettings.action) {
|
||||
case 'depth':
|
||||
// Get the depth of the target row.
|
||||
targetElement.value = $('.indentation', $(sourceElement).parents('tr:first')).size();
|
||||
targetElement.value = $('.indentation', $(sourceElement).closest('tr')).size();
|
||||
break;
|
||||
case 'match':
|
||||
// Update the value.
|
||||
|
@ -876,7 +876,7 @@ Drupal.tableDrag.prototype.row = function (tableRow, method, indentEnabled, maxD
|
|||
this.group = [tableRow];
|
||||
this.groupDepth = $('.indentation', tableRow).size();
|
||||
this.changed = false;
|
||||
this.table = $(tableRow).parents('table:first').get(0);
|
||||
this.table = $(tableRow).closest('table').get(0);
|
||||
this.indentEnabled = indentEnabled;
|
||||
this.maxDepth = maxDepth;
|
||||
this.direction = ''; // Direction the row is being moved.
|
||||
|
|
|
@ -98,10 +98,6 @@ Drupal.tableHeader.prototype.eventhandlerRecalculateStickyHeader = function (eve
|
|||
// Resize header and its cell widths.
|
||||
this.stickyHeaderCells.each(function (index) {
|
||||
var cellWidth = self.originalHeaderCells.eq(index).css('width');
|
||||
// Exception for IE7.
|
||||
if (cellWidth == 'auto') {
|
||||
cellWidth = self.originalHeaderCells.get(index).clientWidth + 'px';
|
||||
}
|
||||
$(this).css('width', cellWidth);
|
||||
});
|
||||
this.stickyTable.css('width', this.originalTable.css('width'));
|
||||
|
|
|
@ -29,7 +29,7 @@ Drupal.tableSelect = function () {
|
|||
checkboxes.each(function () {
|
||||
this.checked = event.target.checked;
|
||||
// Either add or remove the selected class based on the state of the check all checkbox.
|
||||
$(this).parents('tr:first')[ this.checked ? 'addClass' : 'removeClass' ]('selected');
|
||||
$(this).closest('tr').toggleClass('selected', this.checked);
|
||||
});
|
||||
// Update the title and the state of the check all box.
|
||||
updateSelectAll(event.target.checked);
|
||||
|
@ -39,14 +39,14 @@ Drupal.tableSelect = function () {
|
|||
// For each of the checkboxes within the table that are not disabled.
|
||||
checkboxes = $('td input:checkbox:enabled', table).click(function (e) {
|
||||
// Either add or remove the selected class based on the state of the check all checkbox.
|
||||
$(this).parents('tr:first')[ this.checked ? 'addClass' : 'removeClass' ]('selected');
|
||||
$(this).closest('tr').toggleClass('selected', this.checked);
|
||||
|
||||
// If this is a shift click, we need to highlight everything in the range.
|
||||
// Also make sure that we are actually checking checkboxes over a range and
|
||||
// that a checkbox has been checked or unchecked before.
|
||||
if (e.shiftKey && lastChecked && lastChecked != e.target) {
|
||||
// We use the checkbox's parent TR to do our range searching.
|
||||
Drupal.tableSelectRange($(e.target).parents('tr')[0], $(lastChecked).parents('tr')[0], e.target.checked);
|
||||
Drupal.tableSelectRange($(e.target).closest('tr')[0], $(lastChecked).closest('tr')[0], e.target.checked);
|
||||
}
|
||||
|
||||
// If all checkboxes are checked, make sure the select-all one is checked too, otherwise keep unchecked.
|
||||
|
|
|
@ -2,12 +2,10 @@
|
|||
div.vertical-tabs {
|
||||
margin: 1em 0 1em 15em; /* LTR */
|
||||
border: 1px solid #ccc;
|
||||
position: relative; /* IE7 */
|
||||
}
|
||||
.vertical-tabs ul.vertical-tabs-list {
|
||||
width: 15em;
|
||||
list-style: none;
|
||||
list-style-image: none; /* IE7 */
|
||||
border-top: 1px solid #ccc;
|
||||
padding: 0;
|
||||
margin: -1px 0 -1px -15em; /* LTR */
|
||||
|
@ -18,7 +16,7 @@ div.vertical-tabs {
|
|||
padding: 0 1em;
|
||||
border: 0;
|
||||
}
|
||||
.vertical-tabs legend {
|
||||
fieldset.vertical-tabs-pane > legend {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -29,7 +27,6 @@ div.vertical-tabs {
|
|||
border-top: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-width: 0; /* IE7 */
|
||||
}
|
||||
.vertical-tabs ul.vertical-tabs-list li a {
|
||||
display: block;
|
||||
|
|
|
@ -786,3 +786,12 @@ function aggregator_sanitize_configuration() {
|
|||
function _aggregator_items($count) {
|
||||
return format_plural($count, '1 item', '@count items');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_block().
|
||||
*/
|
||||
function aggregator_preprocess_block(&$variables) {
|
||||
if ($variables['block']->module == 'aggregator') {
|
||||
$variables['attributes_array']['role'] = 'complementary';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -266,6 +266,10 @@ EOF;
|
|||
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_atom.xml';
|
||||
}
|
||||
|
||||
function getHtmlEntitiesSample() {
|
||||
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_title_entities.xml';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates sample article nodes.
|
||||
*
|
||||
|
@ -308,6 +312,7 @@ class AggregatorConfigurationTestCase extends AggregatorTestCase {
|
|||
'aggregator_teaser_length' => 200,
|
||||
);
|
||||
$this->drupalPost('admin/config/services/aggregator/settings', $edit, t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'));
|
||||
|
||||
foreach ($edit as $name => $value) {
|
||||
$this->assertFieldByName($name, $value, t('"@name" has correct default value.', array('@name' => $name)));
|
||||
|
@ -914,4 +919,15 @@ class FeedParserTestCase extends AggregatorTestCase {
|
|||
$this->assertText('Some text.');
|
||||
$this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a', db_query('SELECT guid FROM {aggregator_item} WHERE link = :link', array(':link' => 'http://example.org/2003/12/13/atom03'))->fetchField(), 'Atom entry id element is parsed correctly.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a feed that uses HTML entities in item titles.
|
||||
*/
|
||||
function testHtmlEntitiesSample() {
|
||||
$feed = $this->createFeed($this->getHtmlEntitiesSample());
|
||||
aggregator_refresh($feed);
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed %name exists.', array('%name' => $feed->title)));
|
||||
$this->assertText("Quote" Amp&");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ Drupal.behaviors.blockDrag = {
|
|||
$('select.block-region-select', context).once('block-region-select', function () {
|
||||
$(this).change(function (event) {
|
||||
// Make our new row and select field.
|
||||
var row = $(this).parents('tr:first');
|
||||
var row = $(this).closest('tr');
|
||||
var select = $(this);
|
||||
tableDrag.rowObject = new tableDrag.row(row);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0"?>
|
||||
<config>
|
||||
<block_cache>0</block_cache>
|
||||
<block_cache>0</block_cache>
|
||||
</config>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* Available variables:
|
||||
* - $title: Top level node title.
|
||||
* - $head: Header tags.
|
||||
* - $language: Language code. e.g. "en" for english.
|
||||
* - $language: Language object.
|
||||
* - $language_rtl: TRUE or FALSE depending on right to left language scripts.
|
||||
* - $base_url: URL to home page.
|
||||
* - $contents: Nodes within the current outline rendered through
|
||||
|
@ -18,8 +18,8 @@
|
|||
* @ingroup themeable
|
||||
*/
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $language->language; ?>" xml:lang="<?php print $language->language; ?>">
|
||||
<!DOCTYPE html >
|
||||
<html<?php print $html_attributes; ?>>
|
||||
<head>
|
||||
<title><?php print $title; ?></title>
|
||||
<?php print $head; ?>
|
||||
|
|
|
@ -3,6 +3,7 @@ description = Allows users to create and organize related content in an outline.
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
dependencies[] = node
|
||||
files[] = book.test
|
||||
configure = admin/content/book/settings
|
||||
stylesheets[all][] = book.theme.css
|
||||
|
|
|
@ -1058,6 +1058,15 @@ function _book_link_defaults($nid) {
|
|||
return array('original_bid' => 0, 'menu_name' => '', 'nid' => $nid, 'bid' => 0, 'router_path' => 'node/%', 'plid' => 0, 'mlid' => 0, 'has_children' => 0, 'weight' => 0, 'module' => 'book', 'options' => array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_block().
|
||||
*/
|
||||
function book_preprocess_block(&$variables) {
|
||||
if ($variables['block']-> module == 'book') {
|
||||
$variables['attributes_array']['role'] = 'navigation';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes variables for book-all-books-block.tpl.php.
|
||||
*
|
||||
|
@ -1199,7 +1208,7 @@ function book_toc($bid, $depth_limit, $exclude = array()) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Processes variables for book-export-html.tpl.php.
|
||||
* Preprocesses variables for book-export-html.tpl.php.
|
||||
*
|
||||
* The $variables array contains the following elements:
|
||||
* - title
|
||||
|
@ -1216,6 +1225,20 @@ function template_preprocess_book_export_html(&$variables) {
|
|||
$variables['language'] = $language;
|
||||
$variables['language_rtl'] = ($language->direction == LANGUAGE_RTL);
|
||||
$variables['head'] = drupal_get_html_head();
|
||||
|
||||
// HTML element attributes.
|
||||
$variables['html_attributes_array']['lang'] = $language->langcode;
|
||||
$variables['html_attributes_array']['dir'] = $language->direction ? 'rtl' : 'ltr';
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes variables for book-export-html.tpl.php.
|
||||
*
|
||||
* @see book-export-html.tpl.php
|
||||
*/
|
||||
function template_process_book_export_html(&$variables) {
|
||||
// Flatten out html_attributes
|
||||
$variables['html_attributes'] = drupal_attributes($variables['html_attributes_array']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
.book-pager .up {
|
||||
*float: right;
|
||||
}
|
||||
.book-pager .next {
|
||||
float: left;
|
||||
text-align: left;
|
||||
|
|
|
@ -18,12 +18,8 @@
|
|||
}
|
||||
.book-pager li {
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
/* Prevents a line break caused by the float in .page-next in IE7. */
|
||||
*float: left; /* LTR */
|
||||
list-style-type: none;
|
||||
vertical-align: top;
|
||||
zoom: 1;
|
||||
}
|
||||
.book-pager .previous {
|
||||
text-align: left; /* LTR */
|
||||
|
|
|
@ -43,6 +43,6 @@
|
|||
float: right;
|
||||
right: -10px;
|
||||
}
|
||||
html.js #preview {
|
||||
.js #preview {
|
||||
float: right;
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
#preview {
|
||||
display: none;
|
||||
}
|
||||
html.js #preview {
|
||||
.js #preview {
|
||||
display: block;
|
||||
position: relative;
|
||||
float: left; /* LTR */
|
||||
|
|
|
@ -51,28 +51,6 @@ function color_form_system_theme_settings_alter(&$form, &$form_state) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
*/
|
||||
function color_form_system_themes_alter(&$form, &$form_state) {
|
||||
_color_theme_select_form_alter($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for hook_form_FORM_ID_alter() implementations.
|
||||
*/
|
||||
function _color_theme_select_form_alter(&$form, &$form_state) {
|
||||
// Use the generated screenshot in the theme list.
|
||||
$themes = list_themes();
|
||||
foreach (element_children($form) as $theme) {
|
||||
if ($screenshot = variable_get('color_' . $theme . '_screenshot')) {
|
||||
if (isset($form[$theme]['screenshot'])) {
|
||||
$form[$theme]['screenshot']['#markup'] = theme('image', array('uri' => $screenshot, 'title' => '', 'attributes' => array('class' => array('screenshot'))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces style sheets with color-altered style sheets.
|
||||
*
|
||||
|
@ -96,7 +74,7 @@ function _color_html_alter(&$vars) {
|
|||
foreach ($color_paths as $color_path) {
|
||||
// Color module currently requires unique file names to be used,
|
||||
// which allows us to compare different file paths.
|
||||
if (basename($old_path) == basename($color_path)) {
|
||||
if (drupal_basename($old_path) == drupal_basename($color_path)) {
|
||||
// Replace the path to the new css file.
|
||||
// This keeps the order of the stylesheets intact.
|
||||
$vars['css'][$old_path]['data'] = $color_path;
|
||||
|
@ -389,7 +367,7 @@ function color_scheme_form_submit($form, &$form_state) {
|
|||
|
||||
// Copy over neutral images.
|
||||
foreach ($info['copy'] as $file) {
|
||||
$base = basename($file);
|
||||
$base = drupal_basename($file);
|
||||
$source = $paths['source'] . $file;
|
||||
$filepath = file_unmanaged_copy($source, $paths['target'] . $base);
|
||||
$paths['map'][$file] = $base;
|
||||
|
@ -431,7 +409,7 @@ function color_scheme_form_submit($form, &$form_state) {
|
|||
|
||||
// Rewrite stylesheet with new colors.
|
||||
$style = _color_rewrite_stylesheet($theme, $info, $paths, $palette, $style);
|
||||
$base_file = basename($file);
|
||||
$base_file = drupal_basename($file);
|
||||
$css[] = $paths['target'] . $base_file;
|
||||
_color_save_stylesheet($paths['target'] . $base_file, $style, $paths);
|
||||
}
|
||||
|
@ -571,7 +549,7 @@ function _color_render_images($theme, &$info, &$paths, $palette) {
|
|||
// Cut out slices.
|
||||
foreach ($info['slices'] as $file => $coord) {
|
||||
list($x, $y, $width, $height) = $coord;
|
||||
$base = basename($file);
|
||||
$base = drupal_basename($file);
|
||||
$image = drupal_realpath($paths['target'] . $base);
|
||||
|
||||
// Cut out slice.
|
||||
|
|
|
@ -92,7 +92,9 @@ class ColorTestCase extends DrupalWebTestCase {
|
|||
$this->assertTrue(strpos($stylesheet_content, 'color: ' . $test_values['scheme_color']) !== FALSE, 'Make sure the color we changed is in the color stylesheet. (' . $theme . ')');
|
||||
|
||||
// Test with aggregated CSS turned on.
|
||||
variable_set('preprocess_css', 1);
|
||||
$config = config('system.performance');
|
||||
$config->set('preprocess_css', 1);
|
||||
$config->save();
|
||||
$this->drupalGet('<front>');
|
||||
$stylesheets = variable_get('drupal_css_cache_files', array());
|
||||
$stylesheet_content = '';
|
||||
|
@ -100,7 +102,8 @@ class ColorTestCase extends DrupalWebTestCase {
|
|||
$stylesheet_content .= join("\n", file(drupal_realpath($uri)));
|
||||
}
|
||||
$this->assertTrue(strpos($stylesheet_content, 'public://') === FALSE, 'Make sure the color paths have been translated to local paths. (' . $theme . ')');
|
||||
variable_set('preprocess_css', 0);
|
||||
$config->set('preprocess_css', 0);
|
||||
$config->save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@ description = Allows users to comment on and discuss published content.
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
dependencies[] = node
|
||||
dependencies[] = text
|
||||
dependencies[] = entity
|
||||
files[] = comment.entity.inc
|
||||
|
|
|
@ -168,7 +168,7 @@ function comment_schema() {
|
|||
'description' => "The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on.",
|
||||
),
|
||||
'language' => array(
|
||||
'description' => 'The {language}.language of this comment.',
|
||||
'description' => 'The {language}.langcode of this comment.',
|
||||
'type' => 'varchar',
|
||||
'length' => 12,
|
||||
'not null' => TRUE,
|
||||
|
|
|
@ -945,7 +945,7 @@ function comment_prepare_thread(&$comments) {
|
|||
*/
|
||||
function comment_view($comment, $node, $view_mode = 'full', $langcode = NULL) {
|
||||
if (!isset($langcode)) {
|
||||
$langcode = $GLOBALS['language_content']->language;
|
||||
$langcode = $GLOBALS['language_content']->langcode;
|
||||
}
|
||||
|
||||
// Populate $comment->content with a render() array.
|
||||
|
@ -1012,7 +1012,7 @@ function comment_view($comment, $node, $view_mode = 'full', $langcode = NULL) {
|
|||
*/
|
||||
function comment_build_content($comment, $node, $view_mode = 'full', $langcode = NULL) {
|
||||
if (!isset($langcode)) {
|
||||
$langcode = $GLOBALS['language_content']->language;
|
||||
$langcode = $GLOBALS['language_content']->langcode;
|
||||
}
|
||||
|
||||
// Remove previously built content, if exists.
|
||||
|
@ -1260,8 +1260,8 @@ function comment_form_node_form_alter(&$form, $form_state) {
|
|||
// If the node doesn't have any comments, the "hidden" option makes no
|
||||
// sense, so don't even bother presenting it to the user.
|
||||
if (empty($comment_count)) {
|
||||
unset($form['comment_settings']['comment']['#options'][COMMENT_NODE_HIDDEN]);
|
||||
unset($form['comment_settings']['comment'][COMMENT_NODE_HIDDEN]);
|
||||
$form['comment_settings']['comment'][COMMENT_NODE_HIDDEN]['#access'] = FALSE;
|
||||
// Also adjust the description of the "closed" option.
|
||||
$form['comment_settings']['comment'][COMMENT_NODE_CLOSED]['#description'] = t('Users cannot post comments.');
|
||||
}
|
||||
}
|
||||
|
@ -2089,6 +2089,15 @@ function comment_form_submit($form, &$form_state) {
|
|||
cache_clear_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_block().
|
||||
*/
|
||||
function comment_preprocess_block(&$variables) {
|
||||
if ($variables['block']->module == 'comment') {
|
||||
$variables['attributes_array']['role'] = 'navigation';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Preprocesses variables for comment.tpl.php.
|
||||
*
|
||||
|
|
|
@ -261,56 +261,6 @@ class CommentHelperCase extends DrupalWebTestCase {
|
|||
|
||||
return $match[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests new comment marker.
|
||||
*/
|
||||
public function testCommentNewCommentsIndicator() {
|
||||
// Test if the right links are displayed when no comment is present for the
|
||||
// node.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_OPEN));
|
||||
$this->drupalGet('node');
|
||||
$this->assertNoLink(t('@count comments', array('@count' => 0)));
|
||||
$this->assertNoLink(t('@count new comments', array('@count' => 0)));
|
||||
$this->assertLink(t('Read more'));
|
||||
$count = $this->xpath('//div[@id=:id]/div[@class=:class]/ul/li', array(':id' => 'node-' . $this->node->nid, ':class' => 'link-wrapper'));
|
||||
$this->assertTrue(count($count) == 1, t('One child found'));
|
||||
|
||||
// Create a new comment. This helper function may be run with different
|
||||
// comment settings so use comment_save() to avoid complex setup.
|
||||
$comment = entity_create('comment', array(
|
||||
'cid' => NULL,
|
||||
'nid' => $this->node->nid,
|
||||
'node_type' => $this->node->type,
|
||||
'pid' => 0,
|
||||
'uid' => $this->loggedInUser->uid,
|
||||
'status' => COMMENT_PUBLISHED,
|
||||
'subject' => $this->randomName(),
|
||||
'hostname' => ip_address(),
|
||||
'language' => LANGUAGE_NONE,
|
||||
'comment_body' => array(LANGUAGE_NONE => array($this->randomName())),
|
||||
));
|
||||
comment_save($comment);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Log in with 'web user' and check comment links.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node');
|
||||
$this->assertLink(t('1 new comment'));
|
||||
$this->clickLink(t('1 new comment'));
|
||||
$this->assertRaw('<a id="new"></a>', t('Found "new" marker.'));
|
||||
$this->assertTrue($this->xpath('//a[@id=:new]/following-sibling::a[1][@id=:comment_id]', array(':new' => 'new', ':comment_id' => 'comment-1')), t('The "new" anchor is positioned at the right comment.'));
|
||||
|
||||
// Test if "new comment" link is correctly removed.
|
||||
$this->drupalGet('node');
|
||||
$this->assertLink(t('1 comment'));
|
||||
$this->assertLink(t('Read more'));
|
||||
$this->assertNoLink(t('1 new comment'));
|
||||
$this->assertNoLink(t('@count new comments', array('@count' => 0)));
|
||||
$count = $this->xpath('//div[@id=:id]/div[@class=:class]/ul/li', array(':id' => 'node-' . $this->node->nid, ':class' => 'link-wrapper'));
|
||||
$this->assertTrue(count($count) == 2, print_r($count, TRUE));
|
||||
}
|
||||
}
|
||||
|
||||
class CommentInterfaceTest extends CommentHelperCase {
|
||||
|
@ -482,6 +432,56 @@ class CommentInterfaceTest extends CommentHelperCase {
|
|||
$this->setCommentForm(FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests new comment marker.
|
||||
*/
|
||||
public function testCommentNewCommentsIndicator() {
|
||||
// Test if the right links are displayed when no comment is present for the
|
||||
// node.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_OPEN));
|
||||
$this->drupalGet('node');
|
||||
$this->assertNoLink(t('@count comments', array('@count' => 0)));
|
||||
$this->assertNoLink(t('@count new comments', array('@count' => 0)));
|
||||
$this->assertLink(t('Read more'));
|
||||
$count = $this->xpath('//div[@id=:id]/div[@class=:class]/ul/li', array(':id' => 'node-' . $this->node->nid, ':class' => 'link-wrapper'));
|
||||
$this->assertTrue(count($count) == 1, t('One child found'));
|
||||
|
||||
// Create a new comment. This helper function may be run with different
|
||||
// comment settings so use comment_save() to avoid complex setup.
|
||||
$comment = entity_create('comment', array(
|
||||
'cid' => NULL,
|
||||
'nid' => $this->node->nid,
|
||||
'node_type' => $this->node->type,
|
||||
'pid' => 0,
|
||||
'uid' => $this->loggedInUser->uid,
|
||||
'status' => COMMENT_PUBLISHED,
|
||||
'subject' => $this->randomName(),
|
||||
'hostname' => ip_address(),
|
||||
'language' => LANGUAGE_NONE,
|
||||
'comment_body' => array(LANGUAGE_NONE => array($this->randomName())),
|
||||
));
|
||||
comment_save($comment);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Log in with 'web user' and check comment links.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node');
|
||||
$this->assertLink(t('1 new comment'));
|
||||
$this->clickLink(t('1 new comment'));
|
||||
$this->assertRaw('<a id="new"></a>', t('Found "new" marker.'));
|
||||
$this->assertTrue($this->xpath('//a[@id=:new]/following-sibling::a[1][@id=:comment_id]', array(':new' => 'new', ':comment_id' => 'comment-1')), t('The "new" anchor is positioned at the right comment.'));
|
||||
|
||||
// Test if "new comment" link is correctly removed.
|
||||
$this->drupalGet('node');
|
||||
$this->assertLink(t('1 comment'));
|
||||
$this->assertLink(t('Read more'));
|
||||
$this->assertNoLink(t('1 new comment'));
|
||||
$this->assertNoLink(t('@count new comments', array('@count' => 0)));
|
||||
$count = $this->xpath('//div[@id=:id]/div[@class=:class]/ul/li', array(':id' => 'node-' . $this->node->nid, ':class' => 'link-wrapper'));
|
||||
$this->assertTrue(count($count) == 2, print_r($count, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node comment statistics.
|
||||
*/
|
||||
|
@ -1779,8 +1779,8 @@ class CommentTokenReplaceTestCase extends CommentHelperCase {
|
|||
$tests['[comment:body]'] = _text_sanitize($instance, LANGUAGE_NONE, $comment->comment_body[LANGUAGE_NONE][0], 'value');
|
||||
$tests['[comment:url]'] = url('comment/' . $comment->cid, $url_options + array('fragment' => 'comment-' . $comment->cid));
|
||||
$tests['[comment:edit-url]'] = url('comment/' . $comment->cid . '/edit', $url_options);
|
||||
$tests['[comment:created:since]'] = format_interval(REQUEST_TIME - $comment->created, 2, $language->language);
|
||||
$tests['[comment:changed:since]'] = format_interval(REQUEST_TIME - $comment->changed, 2, $language->language);
|
||||
$tests['[comment:created:since]'] = format_interval(REQUEST_TIME - $comment->created, 2, $language->langcode);
|
||||
$tests['[comment:changed:since]'] = format_interval(REQUEST_TIME - $comment->changed, 2, $language->langcode);
|
||||
$tests['[comment:parent:cid]'] = $comment->pid;
|
||||
$tests['[comment:parent:title]'] = check_plain($parent_comment->subject);
|
||||
$tests['[comment:node:nid]'] = $comment->nid;
|
||||
|
|
|
@ -106,7 +106,7 @@ function comment_tokens($type, $tokens, array $data = array(), array $options =
|
|||
$url_options = array('absolute' => TRUE);
|
||||
if (isset($options['language'])) {
|
||||
$url_options['language'] = $options['language'];
|
||||
$language_code = $options['language']->language;
|
||||
$language_code = $options['language']->langcode;
|
||||
}
|
||||
else {
|
||||
$language_code = NULL;
|
||||
|
|
|
@ -176,34 +176,34 @@ function contact_mail($key, &$message, $params) {
|
|||
'!subject' => $params['subject'],
|
||||
'!category' => isset($params['category']['category']) ? $params['category']['category'] : '',
|
||||
'!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)),
|
||||
'!sender-name' => format_username($params['sender']),
|
||||
'!sender-name' => user_format_name($params['sender']),
|
||||
'!sender-url' => $params['sender']->uid ? url('user/' . $params['sender']->uid, array('absolute' => TRUE, 'language' => $language)) : $params['sender']->mail,
|
||||
);
|
||||
|
||||
switch ($key) {
|
||||
case 'page_mail':
|
||||
case 'page_copy':
|
||||
$message['subject'] .= t('[!category] !subject', $variables, array('langcode' => $language->language));
|
||||
$message['body'][] = t("!sender-name (!sender-url) sent a message using the contact form at !form-url.", $variables, array('langcode' => $language->language));
|
||||
$message['subject'] .= t('[!category] !subject', $variables, array('langcode' => $language->langcode));
|
||||
$message['body'][] = t("!sender-name (!sender-url) sent a message using the contact form at !form-url.", $variables, array('langcode' => $language->langcode));
|
||||
$message['body'][] = $params['message'];
|
||||
break;
|
||||
|
||||
case 'page_autoreply':
|
||||
$message['subject'] .= t('[!category] !subject', $variables, array('langcode' => $language->language));
|
||||
$message['subject'] .= t('[!category] !subject', $variables, array('langcode' => $language->langcode));
|
||||
$message['body'][] = $params['category']['reply'];
|
||||
break;
|
||||
|
||||
case 'user_mail':
|
||||
case 'user_copy':
|
||||
$variables += array(
|
||||
'!recipient-name' => format_username($params['recipient']),
|
||||
'!recipient-name' => user_format_name($params['recipient']),
|
||||
'!recipient-edit-url' => url('user/' . $params['recipient']->uid . '/edit', array('absolute' => TRUE, 'language' => $language)),
|
||||
);
|
||||
$message['subject'] .= t('[!site-name] !subject', $variables, array('langcode' => $language->language));
|
||||
$message['body'][] = t('Hello !recipient-name,', $variables, array('langcode' => $language->language));
|
||||
$message['body'][] = t("!sender-name (!sender-url) has sent you a message via your contact form (!form-url) at !site-name.", $variables, array('langcode' => $language->language));
|
||||
$message['body'][] = t("If you don't want to receive such e-mails, you can change your settings at !recipient-edit-url.", $variables, array('langcode' => $language->language));
|
||||
$message['body'][] = t('Message:', array(), array('langcode' => $language->language));
|
||||
$message['subject'] .= t('[!site-name] !subject', $variables, array('langcode' => $language->langcode));
|
||||
$message['body'][] = t('Hello !recipient-name,', $variables, array('langcode' => $language->langcode));
|
||||
$message['body'][] = t("!sender-name (!sender-url) has sent you a message via your contact form (!form-url) at !site-name.", $variables, array('langcode' => $language->langcode));
|
||||
$message['body'][] = t("If you don't want to receive such e-mails, you can change your settings at !recipient-edit-url.", $variables, array('langcode' => $language->langcode));
|
||||
$message['body'][] = t('Message:', array(), array('langcode' => $language->langcode));
|
||||
$message['body'][] = $params['message'];
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ function contact_site_form($form, &$form_state) {
|
|||
'#type' => 'textfield',
|
||||
'#title' => t('Your name'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $user->uid ? format_username($user) : '',
|
||||
'#default_value' => $user->uid ? user_format_name($user) : '',
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['mail'] = array(
|
||||
|
@ -195,7 +195,7 @@ function contact_personal_form($form, &$form_state, $recipient) {
|
|||
drupal_exit();
|
||||
}
|
||||
|
||||
drupal_set_title(t('Contact @username', array('@username' => format_username($recipient))), PASS_THROUGH);
|
||||
drupal_set_title(t('Contact @username', array('@username' => user_format_name($recipient))), PASS_THROUGH);
|
||||
|
||||
if (!$user->uid) {
|
||||
$form['#attached']['library'][] = array('system', 'jquery.cookie');
|
||||
|
@ -211,7 +211,7 @@ function contact_personal_form($form, &$form_state, $recipient) {
|
|||
'#type' => 'textfield',
|
||||
'#title' => t('Your name'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $user->uid ? format_username($user) : '',
|
||||
'#default_value' => $user->uid ? user_format_name($user) : '',
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['mail'] = array(
|
||||
|
|
|
@ -25,7 +25,7 @@ div.contextual-links-wrapper {
|
|||
top: 2px;
|
||||
z-index: 999;
|
||||
}
|
||||
html.js div.contextual-links-wrapper {
|
||||
.js div.contextual-links-wrapper {
|
||||
display: block;
|
||||
}
|
||||
a.contextual-links-trigger {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/**
|
||||
* @file
|
||||
* Right-to-left specific stylesheet for the Dashboard module.
|
||||
*/
|
||||
|
||||
#dashboard div.dashboard-region {
|
||||
float: right;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Adds regions to the dashboard.
|
||||
* Add regions to the dashboard.
|
||||
*
|
||||
* @return
|
||||
* An array whose keys are the names of the dashboard regions and whose
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/**
|
||||
* @file
|
||||
* Stylesheet for the Dashboard module.
|
||||
*/
|
||||
|
||||
#dashboard div.dashboard-region {
|
||||
float: left;
|
||||
min-height: 1px;
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
/**
|
||||
* @file
|
||||
* Attaches behaviors for the Dashboard module.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
/**
|
||||
* Implementation of Drupal.behaviors for dashboard.
|
||||
* Implements Drupal.behaviors for the Dashboard module.
|
||||
*/
|
||||
Drupal.behaviors.dashboard = {
|
||||
attach: function (context, settings) {
|
||||
|
@ -39,7 +44,7 @@ Drupal.behaviors.dashboard = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Enter "customize" mode by displaying disabled blocks.
|
||||
* Enters "customize" mode by displaying disabled blocks.
|
||||
*/
|
||||
enterCustomizeMode: function () {
|
||||
$('#dashboard').addClass('customize-mode customize-inactive');
|
||||
|
@ -51,7 +56,7 @@ Drupal.behaviors.dashboard = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Exit "customize" mode by simply forcing a page refresh.
|
||||
* Exits "customize" mode by simply forcing a page refresh.
|
||||
*/
|
||||
exitCustomizeMode: function () {
|
||||
$('#dashboard').removeClass('customize-mode customize-inactive');
|
||||
|
@ -60,7 +65,7 @@ Drupal.behaviors.dashboard = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Helper for enterCustomizeMode; sets up drag-and-drop and close button.
|
||||
* Sets up the drag-and-drop behavior and the 'close' button.
|
||||
*/
|
||||
setupDrawer: function () {
|
||||
$('div.customize .canvas-content input').click(Drupal.behaviors.dashboard.exitCustomizeMode);
|
||||
|
@ -84,7 +89,7 @@ Drupal.behaviors.dashboard = {
|
|||
},
|
||||
|
||||
/**
|
||||
* While dragging, make the block appear as a disabled block
|
||||
* Makes the block appear as a disabled block while dragging.
|
||||
*
|
||||
* This function is called on the jQuery UI Sortable "start" event.
|
||||
*
|
||||
|
@ -104,8 +109,7 @@ Drupal.behaviors.dashboard = {
|
|||
},
|
||||
|
||||
/**
|
||||
* While dragging, adapt block's width to the width of the region it is moved
|
||||
* into.
|
||||
* Adapts block's width to the region it is moved into while dragging.
|
||||
*
|
||||
* This function is called on the jQuery UI Sortable "over" event.
|
||||
*
|
||||
|
@ -127,8 +131,7 @@ Drupal.behaviors.dashboard = {
|
|||
},
|
||||
|
||||
/**
|
||||
* While dragging, adapt block's position to stay connected with the position
|
||||
* of the mouse pointer.
|
||||
* Adapts a block's position to stay connected with the mouse pointer.
|
||||
*
|
||||
* This function is called on the jQuery UI Sortable "sort" event.
|
||||
*
|
||||
|
@ -146,7 +149,7 @@ Drupal.behaviors.dashboard = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Send block order to the server, and expand previously disabled blocks.
|
||||
* Sends block order to the server, and expands previously disabled blocks.
|
||||
*
|
||||
* This function is called on the jQuery UI Sortable "update" event.
|
||||
*
|
||||
|
@ -198,8 +201,10 @@ Drupal.behaviors.dashboard = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Return the current order of the blocks in each of the sortable regions,
|
||||
* in query string format.
|
||||
* Returns the current order of the blocks in each of the sortable regions.
|
||||
*
|
||||
* @return
|
||||
* The current order of the blocks, in query string format.
|
||||
*/
|
||||
getOrder: function () {
|
||||
var order = [];
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides a dashboard page in the administrative interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
|
@ -263,10 +268,12 @@ function dashboard_forms() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Dashboard page callback.
|
||||
* Page callback: Displays the dashboard.
|
||||
*
|
||||
* @param $launch_customize
|
||||
* Whether to launch in customization mode right away. TRUE or FALSE.
|
||||
*
|
||||
* @see dashboard_menu()
|
||||
*/
|
||||
function dashboard_admin($launch_customize = FALSE) {
|
||||
$js_settings = array(
|
||||
|
@ -298,11 +305,12 @@ function dashboard_admin($launch_customize = FALSE) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Menu page callback: builds the page for administering dashboard blocks.
|
||||
* Page callback: Builds the page for administering dashboard blocks.
|
||||
*
|
||||
* This page reuses the Block module's administration form but limits editing
|
||||
* to blocks that are available to appear on the dashboard.
|
||||
*
|
||||
* @see dashboard_menu()
|
||||
* @see block_admin_display()
|
||||
* @see block_admin_display_form()
|
||||
* @see dashboard_form_dashboard_admin_display_form_alter()
|
||||
|
@ -454,7 +462,7 @@ function dashboard_is_visible() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return an array of dashboard region descriptions, keyed by region name.
|
||||
* Returns an array of dashboard region descriptions, keyed by region name.
|
||||
*/
|
||||
function dashboard_region_descriptions() {
|
||||
$regions = module_invoke_all('dashboard_regions');
|
||||
|
@ -463,7 +471,7 @@ function dashboard_region_descriptions() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return an array of dashboard region names.
|
||||
* Returns an array of dashboard region names.
|
||||
*/
|
||||
function dashboard_regions() {
|
||||
$regions = &drupal_static(__FUNCTION__);
|
||||
|
@ -485,7 +493,9 @@ function dashboard_dashboard_regions() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to show disabled blocks in the dashboard customization mode.
|
||||
* Ajax callback: Shows disabled blocks in the dashboard customization mode.
|
||||
*
|
||||
* @see dashboard_menu()
|
||||
*/
|
||||
function dashboard_show_disabled() {
|
||||
global $theme_key;
|
||||
|
@ -506,12 +516,14 @@ function dashboard_show_disabled() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to display the rendered contents of a specific block.
|
||||
* Ajax callback: Displays the rendered contents of a specific block.
|
||||
*
|
||||
* @param $module
|
||||
* The block's module name.
|
||||
* @param $delta
|
||||
* The block's delta.
|
||||
*
|
||||
* @see dashboard_menu()
|
||||
*/
|
||||
function dashboard_show_block_content($module, $delta) {
|
||||
drupal_theme_initialize();
|
||||
|
@ -533,7 +545,7 @@ function dashboard_show_block_content($module, $delta) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the new weight of each region according to the drag-and-drop order.
|
||||
* Sets the new weight of each region according to the drag-and-drop order.
|
||||
*/
|
||||
function dashboard_update() {
|
||||
drupal_theme_initialize();
|
||||
|
@ -630,7 +642,7 @@ function theme_dashboard_region($variables) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for a set of disabled blocks, for display in dashboard customization mode.
|
||||
* Returns HTML for disabled blocks, for use in dashboard customization mode.
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
|
@ -652,7 +664,7 @@ function theme_dashboard_disabled_blocks($variables) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for a disabled block, for display in dashboard customization mode.
|
||||
* Returns HTML for a disabled block, for use in dashboard customization mode.
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
* Tests for dashboard.module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests the Dashboard module blocks.
|
||||
*/
|
||||
class DashboardBlocksTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
|
@ -33,7 +36,7 @@ class DashboardBlocksTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test adding a block to the dashboard and checking access to it.
|
||||
* Tests adding a block to the dashboard and checking access to it.
|
||||
*/
|
||||
function testDashboardAccess() {
|
||||
// Add a new custom block to a dashboard region.
|
||||
|
@ -58,7 +61,7 @@ class DashboardBlocksTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test that dashboard regions are displayed or hidden properly.
|
||||
* Tests that dashboard regions are displayed or hidden properly.
|
||||
*/
|
||||
function testDashboardRegions() {
|
||||
$dashboard_regions = dashboard_region_descriptions();
|
||||
|
@ -80,8 +83,7 @@ class DashboardBlocksTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test that the dashboard module can be disabled and enabled again,
|
||||
* retaining its blocks.
|
||||
* Tests that the dashboard module can be re-enabled, retaining its blocks.
|
||||
*/
|
||||
function testDisableEnable() {
|
||||
// Add a new custom block to a dashboard region.
|
||||
|
@ -113,8 +115,7 @@ class DashboardBlocksTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test that defining a block with ['properties']['administrative'] = TRUE
|
||||
* adds it as an available block for the dashboard.
|
||||
* Tests that administrative blocks are available for the dashboard.
|
||||
*/
|
||||
function testBlockAvailability() {
|
||||
// Test "Recent comments", which should be available (defined as
|
||||
|
|
|
@ -35,12 +35,12 @@ function entity_modules_disabled() {
|
|||
/**
|
||||
* Gets the entity info array of an entity type.
|
||||
*
|
||||
* @see hook_entity_info()
|
||||
* @see hook_entity_info_alter()
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type, e.g. node, for which the info shall be returned, or NULL
|
||||
* to return an array with info about all types.
|
||||
*
|
||||
* @see hook_entity_info()
|
||||
* @see hook_entity_info_alter()
|
||||
*/
|
||||
function entity_get_info($entity_type = NULL) {
|
||||
global $language;
|
||||
|
@ -54,7 +54,7 @@ function entity_get_info($entity_type = NULL) {
|
|||
|
||||
// hook_entity_info() includes translated strings, so each language is cached
|
||||
// separately.
|
||||
$langcode = $language->language;
|
||||
$langcode = $language->langcode;
|
||||
|
||||
if (empty($entity_info)) {
|
||||
if ($cache = cache()->get("entity_info:$langcode")) {
|
||||
|
@ -122,18 +122,19 @@ function entity_info_cache_clear() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper function to extract id, vid, and bundle name from an entity.
|
||||
* Extracts ID, revision ID, and bundle name from an entity.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type; e.g. 'node' or 'user'.
|
||||
* @param $entity
|
||||
* The entity from which to extract values.
|
||||
*
|
||||
* @return
|
||||
* A numerically indexed array (not a hash table) containing these
|
||||
* elements:
|
||||
* 0: primary id of the entity
|
||||
* 1: revision id of the entity, or NULL if $entity_type is not versioned
|
||||
* 2: bundle name of the entity
|
||||
* - 0: Primary ID of the entity.
|
||||
* - 1: Revision ID of the entity, or NULL if $entity_type is not versioned.
|
||||
* - 2: Bundle name of the entity.
|
||||
*/
|
||||
function entity_extract_ids($entity_type, $entity) {
|
||||
$info = entity_get_info($entity_type);
|
||||
|
@ -159,7 +160,7 @@ function entity_extract_ids($entity_type, $entity) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper function to assemble an object structure with initial ids.
|
||||
* Assembles an object structure with initial IDs.
|
||||
*
|
||||
* This function can be seen as reciprocal to entity_extract_ids().
|
||||
*
|
||||
|
@ -168,9 +169,9 @@ function entity_extract_ids($entity_type, $entity) {
|
|||
* @param $ids
|
||||
* A numerically indexed array, as returned by entity_extract_ids(),
|
||||
* containing these elements:
|
||||
* 0: primary id of the entity
|
||||
* 1: revision id of the entity, or NULL if $entity_type is not versioned
|
||||
* 2: bundle name of the entity, or NULL if $entity_type has no bundles
|
||||
* - 0: Primary ID of the entity.
|
||||
* - 1: Revision ID of the entity, or NULL if $entity_type is not versioned.
|
||||
* - 2: Bundle name of the entity, or NULL if $entity_type has no bundles.
|
||||
*
|
||||
* @return
|
||||
* An entity object, initialized with the IDs provided.
|
||||
|
@ -205,11 +206,6 @@ function entity_create_stub_entity($entity_type, $ids) {
|
|||
* DrupalDefaultEntityController class. See node_entity_info() and the
|
||||
* NodeController in node.module as an example.
|
||||
*
|
||||
* @see hook_entity_info()
|
||||
* @see DrupalEntityControllerInterface
|
||||
* @see DrupalDefaultEntityController
|
||||
* @see EntityFieldQuery
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type to load, e.g. node or user.
|
||||
* @param $ids
|
||||
|
@ -226,6 +222,11 @@ function entity_create_stub_entity($entity_type, $ids) {
|
|||
* An array of entity objects indexed by their ids.
|
||||
*
|
||||
* @todo Remove $conditions in Drupal 8.
|
||||
*
|
||||
* @see hook_entity_info()
|
||||
* @see DrupalEntityControllerInterface
|
||||
* @see DrupalDefaultEntityController
|
||||
* @see EntityFieldQuery
|
||||
*/
|
||||
function entity_load($entity_type, $ids = FALSE, $conditions = array(), $reset = FALSE) {
|
||||
if ($reset) {
|
||||
|
@ -245,7 +246,7 @@ function entity_load($entity_type, $ids = FALSE, $conditions = array(), $reset =
|
|||
* @param $entity_type
|
||||
* The entity type to load, e.g. node or user.
|
||||
* @param $id
|
||||
* The id of the entity to load.
|
||||
* The ID of the entity to load.
|
||||
*
|
||||
* @return
|
||||
* The unchanged entity, or FALSE if the entity cannot be loaded.
|
||||
|
@ -313,12 +314,12 @@ function entity_get_controller($entity_type) {
|
|||
* field_attach_prepare_view() to allow entity level hooks to act on content
|
||||
* loaded by field API.
|
||||
*
|
||||
* @see hook_entity_prepare_view()
|
||||
*
|
||||
* @param $entity_type
|
||||
* The type of entity, i.e. 'node', 'user'.
|
||||
* @param $entities
|
||||
* The entity objects which are being prepared for view, keyed by object ID.
|
||||
*
|
||||
* @see hook_entity_prepare_view()
|
||||
*/
|
||||
function entity_prepare_view($entity_type, $entities) {
|
||||
// To ensure hooks are only run once per entity, check for an
|
||||
|
@ -414,7 +415,7 @@ function entity_label($entity_type, $entity) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper function for attaching field API validation to entity forms.
|
||||
* Attaches field API validation to entity forms.
|
||||
*/
|
||||
function entity_form_field_validate($entity_type, $form, &$form_state) {
|
||||
// All field attach API functions act on an entity object, but during form
|
||||
|
@ -427,7 +428,7 @@ function entity_form_field_validate($entity_type, $form, &$form_state) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper function for copying submitted values to entity properties for simple entity forms.
|
||||
* Copies submitted values to entity properties for simple entity forms.
|
||||
*
|
||||
* During the submission handling of an entity form's "Save", "Preview", and
|
||||
* possibly other buttons, the form state's entity needs to be updated with the
|
||||
|
@ -473,6 +474,6 @@ function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_st
|
|||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when a malformed entity is passed.
|
||||
* Defines an exception thrown when a malformed entity is passed.
|
||||
*/
|
||||
class EntityMalformedException extends Exception { }
|
||||
|
|
|
@ -43,6 +43,7 @@ class EntityFieldQueryException extends Exception {}
|
|||
* other storage engines might not do this.
|
||||
*/
|
||||
class EntityFieldQuery {
|
||||
|
||||
/**
|
||||
* Indicates that both deleted and non-deleted fields should be returned.
|
||||
*
|
||||
|
@ -590,7 +591,8 @@ class EntityFieldQuery {
|
|||
* Enables sortable tables for this query.
|
||||
*
|
||||
* @param $headers
|
||||
* An EFQ Header array based on which the order clause is added to the query.
|
||||
* An EFQ Header array based on which the order clause is added to the
|
||||
* query.
|
||||
*
|
||||
* @return EntityFieldQuery
|
||||
* The called object.
|
||||
|
|
|
@ -66,3 +66,50 @@ class EntityAPITestCase extends DrupalWebTestCase {
|
|||
$this->assertTrue(empty($all), 'Deleted all entities.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Entity API base functionality.
|
||||
*/
|
||||
class EntityAPIInfoTestCase extends DrupalWebTestCase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Entity info',
|
||||
'description' => 'Makes sure entity info is accurately cached.',
|
||||
'group' => 'Entity API',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures entity info cache is updated after changes.
|
||||
*/
|
||||
function testEntityInfoChanges() {
|
||||
module_enable(array('entity_cache_test'));
|
||||
$entity_info = entity_get_info();
|
||||
$this->assertTrue(isset($entity_info['entity_cache_test']), 'Test entity type found.');
|
||||
|
||||
// Change the label of the test entity type and make sure changes appear
|
||||
// after flushing caches.
|
||||
variable_set('entity_cache_test_label', 'New label.');
|
||||
drupal_flush_all_caches();
|
||||
$info = entity_get_info('entity_cache_test');
|
||||
$this->assertEqual($info['label'], 'New label.', 'New label appears in entity info.');
|
||||
|
||||
// Disable the providing module and make sure the entity type is gone.
|
||||
module_disable(array('entity_cache_test', 'entity_cache_test_dependency'));
|
||||
$entity_info = entity_get_info();
|
||||
$this->assertFalse(isset($entity_info['entity_cache_test']), 'Entity type of the providing module is gone.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests entity info cache after enabling a module with a dependency on an entity providing module.
|
||||
*
|
||||
* @see entity_cache_test_watchdog()
|
||||
*/
|
||||
function testEntityInfoCacheWatchdog() {
|
||||
module_enable(array('entity_cache_test'));
|
||||
$info = variable_get('entity_cache_test');
|
||||
$this->assertEqual($info['label'], 'Entity Cache Test', 'Entity info label is correct.');
|
||||
$this->assertEqual($info['controller class'], 'DrupalDefaultEntityController', 'Entity controller class info is correct.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
function entity_cache_test_dependency_entity_info() {
|
||||
return array(
|
||||
'entity_cache_test' => array(
|
||||
'label' => 'Entity Cache Test',
|
||||
'label' => variable_get('entity_cache_test_label', 'Entity Cache Test'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?php
|
||||
|
||||
//
|
||||
// Presave hooks
|
||||
//
|
||||
/**
|
||||
* @file
|
||||
* Test module for the Entity CRUD API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_entity_presave().
|
||||
|
@ -53,10 +54,6 @@ function entity_crud_hook_test_user_presave() {
|
|||
$_SESSION['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
//
|
||||
// Insert hooks
|
||||
//
|
||||
|
||||
/**
|
||||
* Implements hook_entity_insert().
|
||||
*/
|
||||
|
@ -106,10 +103,6 @@ function entity_crud_hook_test_user_insert() {
|
|||
$_SESSION['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
//
|
||||
// Load hooks
|
||||
//
|
||||
|
||||
/**
|
||||
* Implements hook_entity_load().
|
||||
*/
|
||||
|
@ -159,10 +152,6 @@ function entity_crud_hook_test_user_load() {
|
|||
$_SESSION['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
//
|
||||
// Update hooks
|
||||
//
|
||||
|
||||
/**
|
||||
* Implements hook_entity_update().
|
||||
*/
|
||||
|
@ -212,10 +201,6 @@ function entity_crud_hook_test_user_update() {
|
|||
$_SESSION['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
//
|
||||
// Predelete hooks
|
||||
//
|
||||
|
||||
/**
|
||||
* Implements hook_entity_predelete().
|
||||
*/
|
||||
|
@ -265,10 +250,6 @@ function entity_crud_hook_test_user_predelete() {
|
|||
$_SESSION['entity_crud_hook_test'][] = (__FUNCTION__ . ' called');
|
||||
}
|
||||
|
||||
//
|
||||
// Delete hooks
|
||||
//
|
||||
|
||||
/**
|
||||
* Implements hook_entity_delete().
|
||||
*/
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Test invocation of hooks when inserting, loading, updating or deleting an
|
||||
* entity. Tested hooks are:
|
||||
* @file
|
||||
* CRUD hook tests for the Entity CRUD API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests invocation of hooks when performing an action.
|
||||
*
|
||||
* Tested hooks are:
|
||||
* - hook_entity_insert()
|
||||
* - hook_entity_load()
|
||||
* - hook_entity_update()
|
||||
|
@ -53,7 +59,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test hook invocations for CRUD operations on comments.
|
||||
* Tests hook invocations for CRUD operations on comments.
|
||||
*/
|
||||
public function testCommentHooks() {
|
||||
$node = (object) array(
|
||||
|
@ -124,7 +130,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test hook invocations for CRUD operations on files.
|
||||
* Tests hook invocations for CRUD operations on files.
|
||||
*/
|
||||
public function testFileHooks() {
|
||||
$url = 'public://entity_crud_hook_test.file';
|
||||
|
@ -180,7 +186,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test hook invocations for CRUD operations on nodes.
|
||||
* Tests hook invocations for CRUD operations on nodes.
|
||||
*/
|
||||
public function testNodeHooks() {
|
||||
$node = (object) array(
|
||||
|
@ -236,7 +242,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test hook invocations for CRUD operations on taxonomy terms.
|
||||
* Tests hook invocations for CRUD operations on taxonomy terms.
|
||||
*/
|
||||
public function testTaxonomyTermHooks() {
|
||||
$vocabulary = (object) array(
|
||||
|
@ -294,7 +300,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test hook invocations for CRUD operations on taxonomy vocabularies.
|
||||
* Tests hook invocations for CRUD operations on taxonomy vocabularies.
|
||||
*/
|
||||
public function testTaxonomyVocabularyHooks() {
|
||||
$vocabulary = (object) array(
|
||||
|
@ -344,7 +350,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test hook invocations for CRUD operations on users.
|
||||
* Tests hook invocations for CRUD operations on users.
|
||||
*/
|
||||
public function testUserHooks() {
|
||||
$edit = array(
|
||||
|
|
|
@ -194,8 +194,10 @@ function _field_invoke($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $opti
|
|||
// Iterate through the instances and collect results.
|
||||
$return = array();
|
||||
foreach ($instances as $instance) {
|
||||
$field_name = $instance['field_name'];
|
||||
$field = field_info_field($field_name);
|
||||
// field_info_field() is not available for deleted fields, so use
|
||||
// field_info_field_by_id().
|
||||
$field = field_info_field_by_id($instance['field_id']);
|
||||
$field_name = $field['field_name'];
|
||||
$function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
|
||||
if (function_exists($function)) {
|
||||
// Determine the list of languages to iterate on.
|
||||
|
@ -703,7 +705,8 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
|
|||
}
|
||||
|
||||
// Invoke field-type module's hook_field_load().
|
||||
_field_invoke_multiple('load', $entity_type, $queried_entities, $age, $options);
|
||||
$null = NULL;
|
||||
_field_invoke_multiple('load', $entity_type, $queried_entities, $age, $null, $options);
|
||||
|
||||
// Invoke hook_field_attach_load(): let other modules act on loading the
|
||||
// entitiy.
|
||||
|
|
|
@ -79,7 +79,7 @@ function _field_info_collate_types() {
|
|||
|
||||
// The _info() hooks invoked below include translated strings, so each
|
||||
// language is cached separately.
|
||||
$langcode = $language->language;
|
||||
$langcode = $language->langcode;
|
||||
|
||||
if (!isset($info)) {
|
||||
if ($cached = cache('field')->get("field_info_types:$langcode")) {
|
||||
|
|
|
@ -103,10 +103,9 @@ function field_schema() {
|
|||
'active' => array('active'),
|
||||
'storage_active' => array('storage_active'),
|
||||
'deleted' => array('deleted'),
|
||||
// Used by field_modules_disabled().
|
||||
// Used by field_sync_field_status().
|
||||
'module' => array('module'),
|
||||
'storage_module' => array('storage_module'),
|
||||
// Used by field_associate_fields().
|
||||
'type' => array('type'),
|
||||
'storage_type' => array('storage_type'),
|
||||
),
|
||||
|
|
|
@ -362,11 +362,12 @@ function field_theme() {
|
|||
|
||||
/**
|
||||
* Implements hook_cron().
|
||||
*
|
||||
* Purges some deleted Field API data, if any exists.
|
||||
*/
|
||||
function field_cron() {
|
||||
// Refresh the 'active' status of fields.
|
||||
field_sync_field_status();
|
||||
|
||||
// Do a pass of purging on deleted Field API data, if any exists.
|
||||
$limit = variable_get('field_purge_batch_size', 10);
|
||||
field_purge_batch($limit);
|
||||
}
|
||||
|
@ -412,10 +413,29 @@ function field_system_info_alter(&$info, $file, $type) {
|
|||
* Implements hook_flush_caches().
|
||||
*/
|
||||
function field_flush_caches() {
|
||||
// Refresh the 'active' status of fields.
|
||||
field_sync_field_status();
|
||||
|
||||
// Request a flush of our cache table.
|
||||
return array('field');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_modules_enabled().
|
||||
*/
|
||||
function field_modules_enabled($modules) {
|
||||
// Refresh the 'active' status of fields.
|
||||
field_sync_field_status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_modules_disabled().
|
||||
*/
|
||||
function field_modules_disabled($modules) {
|
||||
// Refresh the 'active' status of fields.
|
||||
field_sync_field_status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the 'active' and 'storage_active' columns for fields.
|
||||
*/
|
||||
|
@ -449,18 +469,18 @@ function field_sync_field_status() {
|
|||
function field_associate_fields($module) {
|
||||
// Associate field types.
|
||||
$field_types = (array) module_invoke($module, 'field_info');
|
||||
foreach ($field_types as $name => $field_info) {
|
||||
if ($field_types) {
|
||||
db_update('field_config')
|
||||
->fields(array('module' => $module, 'active' => 1))
|
||||
->condition('type', $name)
|
||||
->condition('type', array_keys($field_types))
|
||||
->execute();
|
||||
}
|
||||
// Associate storage backends.
|
||||
$storage_types = (array) module_invoke($module, 'field_storage_info');
|
||||
foreach ($storage_types as $name => $storage_info) {
|
||||
if ($storage_types) {
|
||||
db_update('field_config')
|
||||
->fields(array('storage_module' => $module, 'storage_active' => 1))
|
||||
->condition('storage_type', $name)
|
||||
->condition('storage_type', array_keys($storage_types))
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
@ -975,18 +995,20 @@ function field_has_data($field) {
|
|||
/**
|
||||
* Determine whether the user has access to a given field.
|
||||
*
|
||||
* @param $op
|
||||
* @param string $op
|
||||
* The operation to be performed. Possible values:
|
||||
* - "edit"
|
||||
* - "view"
|
||||
* @param $field
|
||||
* The field on which the operation is to be performed.
|
||||
* @param $entity_type
|
||||
* - 'edit'
|
||||
* - 'view'
|
||||
* @param array $field
|
||||
* The full field structure array for the field on which the operation is to
|
||||
* be performed. See field_info_field().
|
||||
* @param string $entity_type
|
||||
* The type of $entity; e.g., 'node' or 'user'.
|
||||
* @param $entity
|
||||
* (optional) The entity for the operation.
|
||||
* @param $account
|
||||
* (optional) The account to check, if not given use currently logged in user.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the operation is allowed;
|
||||
* FALSE if the operation is denied.
|
||||
|
|
|
@ -245,7 +245,7 @@ function field_valid_language($langcode, $default = TRUE) {
|
|||
return $langcode;
|
||||
}
|
||||
global $language_content;
|
||||
return $default ? language_default()->language : $language_content->language;
|
||||
return $default ? language_default()->langcode : $language_content->langcode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2357,7 +2357,6 @@ class FieldCrudTestCase extends FieldTestCase {
|
|||
$this->assertTrue($field_definition <= $field, t('The field was properly read.'));
|
||||
|
||||
module_disable($modules, FALSE);
|
||||
drupal_flush_all_caches();
|
||||
|
||||
$fields = field_read_fields(array('field_name' => $field_name), array('include_inactive' => TRUE));
|
||||
$this->assertTrue(isset($fields[$field_name]) && $field_definition < $field, t('The field is properly read when explicitly fetching inactive fields.'));
|
||||
|
@ -2370,7 +2369,6 @@ class FieldCrudTestCase extends FieldTestCase {
|
|||
|
||||
$module = array_shift($modules);
|
||||
module_enable(array($module), FALSE);
|
||||
drupal_flush_all_caches();
|
||||
}
|
||||
|
||||
// Check that the field is active again after all modules have been
|
||||
|
@ -2646,7 +2644,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
|
|||
require_once DRUPAL_ROOT . '/core/includes/locale.inc';
|
||||
for ($i = 0; $i < 3; ++$i) {
|
||||
$language = (object) array(
|
||||
'language' => 'l' . $i,
|
||||
'langcode' => 'l' . $i,
|
||||
'name' => $this->randomString(),
|
||||
);
|
||||
language_save($language);
|
||||
|
@ -2994,22 +2992,54 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
|
|||
*/
|
||||
function _generateStubEntities($entity_type, $entities, $field_name = NULL) {
|
||||
$stubs = array();
|
||||
foreach ($entities as $entity) {
|
||||
foreach ($entities as $id => $entity) {
|
||||
$stub = entity_create_stub_entity($entity_type, entity_extract_ids($entity_type, $entity));
|
||||
if (isset($field_name)) {
|
||||
$stub->{$field_name} = $entity->{$field_name};
|
||||
}
|
||||
$stubs[] = $stub;
|
||||
$stubs[$id] = $stub;
|
||||
}
|
||||
return $stubs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the expected hooks have been invoked on the expected entities.
|
||||
*
|
||||
* @param $expected_hooks
|
||||
* An array keyed by hook name, with one entry per expected invocation.
|
||||
* Each entry is the value of the "$entity" parameter the hook is expected
|
||||
* to have been passed.
|
||||
* @param $actual_hooks
|
||||
* The array of actual hook invocations recorded by field_test_memorize().
|
||||
*/
|
||||
function checkHooksInvocations($expected_hooks, $actual_hooks) {
|
||||
foreach ($expected_hooks as $hook => $invocations) {
|
||||
$actual_invocations = $actual_hooks[$hook];
|
||||
|
||||
// Check that the number of invocations is correct.
|
||||
$this->assertEqual(count($actual_invocations), count($invocations), "$hook() was called the expected number of times.");
|
||||
|
||||
// Check that the hook was called for each expected argument.
|
||||
foreach ($invocations as $argument) {
|
||||
$found = FALSE;
|
||||
foreach ($actual_invocations as $actual_arguments) {
|
||||
if ($actual_arguments[1] == $argument) {
|
||||
$found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertTrue($found, "$hook() was called on expected argument");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('field_test');
|
||||
|
||||
// Clean up data from previous test cases.
|
||||
$this->fields = array();
|
||||
$this->instances = array();
|
||||
$this->entities = array();
|
||||
$this->entities_by_bundles = array();
|
||||
|
||||
// Create two bundles.
|
||||
$this->bundles = array('bb_1' => 'bb_1', 'bb_2' => 'bb_2');
|
||||
|
@ -3045,7 +3075,10 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
|
|||
foreach ($this->fields as $field) {
|
||||
$entity->{$field['field_name']}[LANGUAGE_NONE] = $this->_generateTestFieldValues($field['cardinality']);
|
||||
}
|
||||
|
||||
$this->entities[$id] = $entity;
|
||||
// Also keep track of the entities per bundle.
|
||||
$this->entities_by_bundles[$bundle][$id] = $entity;
|
||||
field_attach_insert($this->entity_type, $entity);
|
||||
$id++;
|
||||
}
|
||||
|
@ -3110,6 +3143,7 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
|
|||
* instance is deleted.
|
||||
*/
|
||||
function testPurgeInstance() {
|
||||
// Start recording hook invocations.
|
||||
field_test_memorize();
|
||||
|
||||
$bundle = reset($this->bundles);
|
||||
|
@ -3124,7 +3158,7 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
|
|||
$this->assertEqual(count($mem), 0, 'No field hooks were called');
|
||||
|
||||
$batch_size = 2;
|
||||
for ($count = 8; $count >= 0; $count -= 2) {
|
||||
for ($count = 8; $count >= 0; $count -= $batch_size) {
|
||||
// Purge two entities.
|
||||
field_purge_batch($batch_size);
|
||||
|
||||
|
@ -3138,19 +3172,21 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
|
|||
$this->assertEqual($count ? count($found['test_entity']) : count($found), $count, 'Correct number of entities found after purging 2');
|
||||
}
|
||||
|
||||
// hook_field_delete() was called on a pseudo-entity for each entity. Each
|
||||
// pseudo entity has a $field property that matches the original entity,
|
||||
// but no others.
|
||||
$mem = field_test_memorize();
|
||||
$this->assertEqual(count($mem['field_test_field_delete']), 10, 'hook_field_delete was called for the right number of entities');
|
||||
$stubs = $this->_generateStubEntities($this->entity_type, $this->entities, $field['field_name']);
|
||||
$count = count($stubs);
|
||||
foreach ($mem['field_test_field_delete'] as $args) {
|
||||
$entity = $args[1];
|
||||
$this->assertEqual($stubs[$entity->ftid], $entity, 'hook_field_delete() called with the correct stub');
|
||||
unset($stubs[$entity->ftid]);
|
||||
// Check hooks invocations.
|
||||
// - hook_field_load() (multiple hook) should have been called on all
|
||||
// entities by pairs of two.
|
||||
// - hook_field_delete() should have been called once for each entity in the
|
||||
// bundle.
|
||||
$actual_hooks = field_test_memorize();
|
||||
$hooks = array();
|
||||
$stubs = $this->_generateStubEntities($this->entity_type, $this->entities_by_bundles[$bundle], $field['field_name']);
|
||||
foreach (array_chunk($stubs, $batch_size, TRUE) as $chunk) {
|
||||
$hooks['field_test_field_load'][] = $chunk;
|
||||
}
|
||||
$this->assertEqual(count($stubs), $count-10, 'hook_field_delete was called with each entity once');
|
||||
foreach ($stubs as $stub) {
|
||||
$hooks['field_test_field_delete'][] = $stub;
|
||||
}
|
||||
$this->checkHooksInvocations($hooks, $actual_hooks);
|
||||
|
||||
// The instance still exists, deleted.
|
||||
$instances = field_read_instances(array('field_id' => $field['id'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1));
|
||||
|
@ -3173,15 +3209,37 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
|
|||
* instances are deleted and purged.
|
||||
*/
|
||||
function testPurgeField() {
|
||||
// Start recording hook invocations.
|
||||
field_test_memorize();
|
||||
|
||||
$field = reset($this->fields);
|
||||
|
||||
// Delete the first instance.
|
||||
$instance = field_info_instance($this->entity_type, $field['field_name'], 'bb_1');
|
||||
$bundle = reset($this->bundles);
|
||||
$instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
|
||||
field_delete_instance($instance);
|
||||
|
||||
// Assert that hook_field_delete() was not called yet.
|
||||
$mem = field_test_memorize();
|
||||
$this->assertEqual(count($mem), 0, 'No field hooks were called.');
|
||||
|
||||
// Purge the data.
|
||||
field_purge_batch(10);
|
||||
|
||||
// Check hooks invocations.
|
||||
// - hook_field_load() (multiple hook) should have been called once, for all
|
||||
// entities in the bundle.
|
||||
// - hook_field_delete() should have been called once for each entity in the
|
||||
// bundle.
|
||||
$actual_hooks = field_test_memorize();
|
||||
$hooks = array();
|
||||
$stubs = $this->_generateStubEntities($this->entity_type, $this->entities_by_bundles[$bundle], $field['field_name']);
|
||||
$hooks['field_test_field_load'][] = $stubs;
|
||||
foreach ($stubs as $stub) {
|
||||
$hooks['field_test_field_delete'][] = $stub;
|
||||
}
|
||||
$this->checkHooksInvocations($hooks, $actual_hooks);
|
||||
|
||||
// Purge again to purge the instance.
|
||||
field_purge_batch(0);
|
||||
|
||||
|
@ -3190,12 +3248,27 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
|
|||
$this->assertTrue(isset($fields[$field['id']]) && !$fields[$field['id']]['deleted'], 'The field exists and is not deleted');
|
||||
|
||||
// Delete the second instance.
|
||||
$instance = field_info_instance($this->entity_type, $field['field_name'], 'bb_2');
|
||||
$bundle = next($this->bundles);
|
||||
$instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
|
||||
field_delete_instance($instance);
|
||||
|
||||
// Assert that hook_field_delete() was not called yet.
|
||||
$mem = field_test_memorize();
|
||||
$this->assertEqual(count($mem), 0, 'No field hooks were called.');
|
||||
|
||||
// Purge the data.
|
||||
field_purge_batch(10);
|
||||
|
||||
// Check hooks invocations (same as above, for the 2nd bundle).
|
||||
$actual_hooks = field_test_memorize();
|
||||
$hooks = array();
|
||||
$stubs = $this->_generateStubEntities($this->entity_type, $this->entities_by_bundles[$bundle], $field['field_name']);
|
||||
$hooks['field_test_field_load'][] = $stubs;
|
||||
foreach ($stubs as $stub) {
|
||||
$hooks['field_test_field_delete'][] = $stub;
|
||||
}
|
||||
$this->checkHooksInvocations($hooks, $actual_hooks);
|
||||
|
||||
// The field still exists, deleted.
|
||||
$fields = field_read_fields(array('id' => $field['id']), array('include_deleted' => 1));
|
||||
$this->assertTrue(isset($fields[$field['id']]) && $fields[$field['id']]['deleted'], 'The field exists and is deleted');
|
||||
|
|
|
@ -58,6 +58,9 @@ function field_test_field_update_forbid($field, $prior_field, $has_data) {
|
|||
* Implements hook_field_load().
|
||||
*/
|
||||
function field_test_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
|
||||
$args = func_get_args();
|
||||
field_test_memorize(__FUNCTION__, $args);
|
||||
|
||||
foreach ($items as $id => $item) {
|
||||
// To keep the test non-intrusive, only act for instances with the
|
||||
// test_hook_field_load setting explicitly set to TRUE.
|
||||
|
@ -72,6 +75,30 @@ function field_test_field_load($entity_type, $entities, $field, $instances, $lan
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_insert().
|
||||
*/
|
||||
function field_test_field_insert($entity_type, $entity, $field, $instance, $items) {
|
||||
$args = func_get_args();
|
||||
field_test_memorize(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_update().
|
||||
*/
|
||||
function field_test_field_update($entity_type, $entity, $field, $instance, $items) {
|
||||
$args = func_get_args();
|
||||
field_test_memorize(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_delete().
|
||||
*/
|
||||
function field_test_field_delete($entity_type, $entity, $field, $instance, $items) {
|
||||
$args = func_get_args();
|
||||
field_test_memorize(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_validate().
|
||||
*
|
||||
|
@ -79,6 +106,9 @@ function field_test_field_load($entity_type, $entities, $field, $instances, $lan
|
|||
* - 'field_test_invalid': The value is invalid.
|
||||
*/
|
||||
function field_test_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
|
||||
$args = func_get_args();
|
||||
field_test_memorize(__FUNCTION__, $args);
|
||||
|
||||
foreach ($items as $delta => $item) {
|
||||
if ($item['value'] == -1) {
|
||||
$errors[$field['field_name']][$langcode][$delta][] = array(
|
||||
|
|
|
@ -182,30 +182,6 @@ function field_test_field_create_field($field) {
|
|||
field_test_memorize(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Memorize calls to hook_field_insert().
|
||||
*/
|
||||
function field_test_field_insert($entity_type, $entity, $field, $instance, $items) {
|
||||
$args = func_get_args();
|
||||
field_test_memorize(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Memorize calls to hook_field_update().
|
||||
*/
|
||||
function field_test_field_update($entity_type, $entity, $field, $instance, $items) {
|
||||
$args = func_get_args();
|
||||
field_test_memorize(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Memorize calls to hook_field_delete().
|
||||
*/
|
||||
function field_test_field_delete($entity_type, $entity, $field, $instance, $items) {
|
||||
$args = func_get_args();
|
||||
field_test_memorize(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_query_alter().
|
||||
*/
|
||||
|
|
|
@ -28,7 +28,7 @@ Drupal.fieldUIFieldOverview = {
|
|||
|
||||
// 'Field type' select updates its 'Widget' select.
|
||||
$('.field-type-select', table).each(function () {
|
||||
this.targetSelect = $('.widget-type-select', $(this).parents('tr').eq(0));
|
||||
this.targetSelect = $('.widget-type-select', $(this).closest('tr'));
|
||||
|
||||
$(this).bind('change keyup', function () {
|
||||
var selectedFieldType = this.options[this.selectedIndex].value;
|
||||
|
@ -43,8 +43,8 @@ Drupal.fieldUIFieldOverview = {
|
|||
|
||||
// 'Existing field' select updates its 'Widget' select and 'Label' textfield.
|
||||
$('.field-select', table).each(function () {
|
||||
this.targetSelect = $('.widget-type-select', $(this).parents('tr').eq(0));
|
||||
this.targetTextfield = $('.label-textfield', $(this).parents('tr').eq(0));
|
||||
this.targetSelect = $('.widget-type-select', $(this).closest('tr'));
|
||||
this.targetTextfield = $('.label-textfield', $(this).closest('tr'));
|
||||
this.targetTextfield
|
||||
.data('field_ui_edited', false)
|
||||
.bind('keyup', function (e) {
|
||||
|
@ -140,7 +140,7 @@ Drupal.fieldUIOverview = {
|
|||
*/
|
||||
onChange: function () {
|
||||
var $trigger = $(this);
|
||||
var row = $trigger.parents('tr:first').get(0);
|
||||
var row = $trigger.closest('tr').get(0);
|
||||
var rowHandler = $(row).data('fieldUIRowHandler');
|
||||
|
||||
var refreshRows = {};
|
||||
|
|
|
@ -18,6 +18,7 @@ class FieldUITestCase extends DrupalWebTestCase {
|
|||
if (isset($modules[0]) && is_array($modules[0])) {
|
||||
$modules = $modules[0];
|
||||
}
|
||||
$modules[] = 'node';
|
||||
$modules[] = 'field_ui';
|
||||
$modules[] = 'field_test';
|
||||
$modules[] = 'taxonomy';
|
||||
|
|
|
@ -77,7 +77,7 @@ Drupal.file = Drupal.file || {
|
|||
'%filename': this.value,
|
||||
'%extensions': extensionPattern.replace(/\|/g, ', ')
|
||||
});
|
||||
$(this).parents('div.form-managed-file').prepend('<div class="messages error file-upload-js-error">' + error + '</div>');
|
||||
$(this).closest('div.form-managed-file').prepend('<div class="messages error file-upload-js-error">' + error + '</div>');
|
||||
this.value = '';
|
||||
return false;
|
||||
}
|
||||
|
@ -96,8 +96,8 @@ Drupal.file = Drupal.file || {
|
|||
|
||||
// Check if we're working with an "Upload" button.
|
||||
var $enabledFields = [];
|
||||
if ($(this).parents('div.form-managed-file').size() > 0) {
|
||||
$enabledFields = $(this).parents('div.form-managed-file').find('input.form-file');
|
||||
if ($(this).closest('div.form-managed-file').size() > 0) {
|
||||
$enabledFields = $(this).closest('div.form-managed-file').find('input.form-file');
|
||||
}
|
||||
|
||||
// Temporarily disable upload fields other than the one we're currently
|
||||
|
@ -119,7 +119,7 @@ Drupal.file = Drupal.file || {
|
|||
*/
|
||||
progressBar: function (event) {
|
||||
var clickedButton = this;
|
||||
var $progressId = $(clickedButton).parents('div.form-managed-file').find('input.file-progress');
|
||||
var $progressId = $(clickedButton).closest('div.form-managed-file').find('input.file-progress');
|
||||
if ($progressId.size()) {
|
||||
var originalName = $progressId.attr('name');
|
||||
|
||||
|
@ -133,7 +133,7 @@ Drupal.file = Drupal.file || {
|
|||
}
|
||||
// Show the progress bar if the upload takes longer than half a second.
|
||||
setTimeout(function () {
|
||||
$(clickedButton).parents('div.form-managed-file').find('div.ajax-progress-bar').slideDown();
|
||||
$(clickedButton).closest('div.form-managed-file').find('div.ajax-progress-bar').slideDown();
|
||||
}, 500);
|
||||
},
|
||||
/**
|
||||
|
|
|
@ -172,7 +172,7 @@ function file_file_download($uri, $field_type = 'file') {
|
|||
// Find the field item with the matching URI.
|
||||
foreach ($field_items as $field_item) {
|
||||
if ($field_item['uri'] == $uri) {
|
||||
$field = $field_item;
|
||||
$field = field_info_field($field_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1065,6 +1065,9 @@ class FileTokenReplaceTestCase extends FileFieldTestCase {
|
|||
$instance = field_info_instance('node', $field_name, $type_name);
|
||||
|
||||
$test_file = $this->getTestFile('text');
|
||||
// Coping a file to test uploads with non-latin filenames.
|
||||
$filename = drupal_dirname($test_file->uri) . '/текстовый файл.txt';
|
||||
$test_file = file_copy($test_file, $filename);
|
||||
|
||||
// Create a new node with the uploaded file.
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
|
@ -1081,9 +1084,9 @@ class FileTokenReplaceTestCase extends FileFieldTestCase {
|
|||
$tests['[file:mime]'] = check_plain($file->filemime);
|
||||
$tests['[file:size]'] = format_size($file->filesize);
|
||||
$tests['[file:url]'] = check_plain(file_create_url($file->uri));
|
||||
$tests['[file:timestamp]'] = format_date($file->timestamp, 'medium', '', NULL, $language->language);
|
||||
$tests['[file:timestamp:short]'] = format_date($file->timestamp, 'short', '', NULL, $language->language);
|
||||
$tests['[file:owner]'] = check_plain(format_username($this->admin_user));
|
||||
$tests['[file:timestamp]'] = format_date($file->timestamp, 'medium', '', NULL, $language->langcode);
|
||||
$tests['[file:timestamp:short]'] = format_date($file->timestamp, 'short', '', NULL, $language->langcode);
|
||||
$tests['[file:owner]'] = check_plain(user_format_name($this->admin_user));
|
||||
$tests['[file:owner:uid]'] = $file->uid;
|
||||
|
||||
// Test to make sure that we generated something for each token.
|
||||
|
|
|
@ -69,3 +69,16 @@ function file_module_test_form_submit($form, &$form_state) {
|
|||
}
|
||||
drupal_set_message(t('The file id is %fid.', array('%fid' => $fid)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_download_access().
|
||||
*/
|
||||
function file_module_test_file_download_access($field, $entity_type, $entity) {
|
||||
list(,, $bundle) = entity_extract_ids($entity_type, $entity);
|
||||
$instance = field_info_instance($entity_type, $field['field_name'], $bundle);
|
||||
// Allow the file to be downloaded only if the given arguments are correct.
|
||||
// If any are wrong, $instance will be NULL.
|
||||
if (empty($instance)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ Drupal.behaviors.filterGuidelines = {
|
|||
attach: function (context) {
|
||||
$('.filter-guidelines', context).once('filter-guidelines')
|
||||
.find(':header').hide()
|
||||
.parents('.filter-wrapper').find('select.filter-list')
|
||||
.closest('.filter-wrapper').find('select.filter-list')
|
||||
.bind('change', function () {
|
||||
$(this).parents('.filter-wrapper')
|
||||
$(this).closest('.filter-wrapper')
|
||||
.find('.filter-guidelines-item').hide()
|
||||
.siblings('.filter-guidelines-' + this.value).show();
|
||||
})
|
||||
|
|
|
@ -395,7 +395,7 @@ function filter_formats($account = NULL) {
|
|||
|
||||
// All available formats are cached for performance.
|
||||
if (!isset($formats['all'])) {
|
||||
if ($cache = cache()->get("filter_formats:{$language->language}")) {
|
||||
if ($cache = cache()->get("filter_formats:{$language->langcode}")) {
|
||||
$formats['all'] = $cache->data;
|
||||
}
|
||||
else {
|
||||
|
@ -407,7 +407,7 @@ function filter_formats($account = NULL) {
|
|||
->execute()
|
||||
->fetchAllAssoc('format');
|
||||
|
||||
cache()->set("filter_formats:{$language->language}", $formats['all']);
|
||||
cache()->set("filter_formats:{$language->langcode}", $formats['all']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -245,13 +245,14 @@ function forum_overview($form, &$form_state) {
|
|||
if (isset($form[$key]['#term'])) {
|
||||
$term = $form[$key]['#term'];
|
||||
$form[$key]['view']['#href'] = 'forum/' . $term['tid'];
|
||||
unset($form[$key]['operations']['#links']['delete']);
|
||||
if (in_array($form[$key]['#term']['tid'], variable_get('forum_containers', array()))) {
|
||||
$form[$key]['edit']['#title'] = t('edit container');
|
||||
$form[$key]['edit']['#href'] = 'admin/structure/forum/edit/container/' . $term['tid'];
|
||||
$form[$key]['operations']['#links']['edit']['title'] = t('edit container');
|
||||
$form[$key]['operations']['#links']['edit']['href'] = 'admin/structure/forum/edit/container/' . $term['tid'];
|
||||
}
|
||||
else {
|
||||
$form[$key]['edit']['#title'] = t('edit forum');
|
||||
$form[$key]['edit']['#href'] = 'admin/structure/forum/edit/forum/' . $term['tid'];
|
||||
$form[$key]['operations']['#links']['edit']['title'] = t('edit forum');
|
||||
$form[$key]['operations']['#links']['edit']['href'] = 'admin/structure/forum/edit/forum/' . $term['tid'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +276,7 @@ function forum_overview($form, &$form_state) {
|
|||
*/
|
||||
function _forum_parent_select($tid, $title, $child_type) {
|
||||
|
||||
$parents = taxonomy_get_parents($tid);
|
||||
$parents = taxonomy_term_load_parents($tid);
|
||||
if ($parents) {
|
||||
$parent = array_shift($parents);
|
||||
$parent = $parent->tid;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
name = Forum
|
||||
description = Provides discussion forums.
|
||||
dependencies[] = node
|
||||
dependencies[] = taxonomy
|
||||
dependencies[] = comment
|
||||
package = Core
|
||||
|
|
|
@ -268,7 +268,7 @@ function forum_node_view($node, $view_mode) {
|
|||
// Breadcrumb navigation
|
||||
$breadcrumb[] = l(t('Home'), NULL);
|
||||
$breadcrumb[] = l($vocabulary->name, 'forum');
|
||||
if ($parents = taxonomy_get_parents_all($node->forum_tid)) {
|
||||
if ($parents = taxonomy_term_load_parents_all($node->forum_tid)) {
|
||||
$parents = array_reverse($parents);
|
||||
foreach ($parents as $parent) {
|
||||
$breadcrumb[] = l($parent->name, 'forum/' . $parent->tid);
|
||||
|
@ -765,7 +765,7 @@ function forum_forum_load($tid = NULL) {
|
|||
}
|
||||
|
||||
// Load parent terms.
|
||||
$forum_term->parents = taxonomy_get_parents_all($forum_term->tid);
|
||||
$forum_term->parents = taxonomy_term_load_parents_all($forum_term->tid);
|
||||
|
||||
// Load the tree below.
|
||||
$forums = array();
|
||||
|
@ -961,6 +961,15 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
|
|||
return $topics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_block().
|
||||
*/
|
||||
function forum_preprocess_block(&$variables) {
|
||||
if ($variables['block']->module == 'forum') {
|
||||
$variables['attributes_array']['role'] = 'navigation';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process variables for forums.tpl.php
|
||||
*
|
||||
|
|
|
@ -43,7 +43,10 @@ function help_help($path, $arg) {
|
|||
$output .= '<li>' . t('<strong>Configure your website</strong> Once logged in, visit the <a href="@admin">administration section</a>, where you can <a href="@config">customize and configure</a> all aspects of your website.', array('@admin' => url('admin'), '@config' => url('admin/config'))) . '</li>';
|
||||
$output .= '<li>' . t('<strong>Enable additional functionality</strong> Next, visit the <a href="@modules">module list</a> and enable features which suit your specific needs. You can find additional modules in the <a href="@download_modules">Drupal modules download section</a>.', array('@modules' => url('admin/modules'), '@download_modules' => 'http://drupal.org/project/modules')) . '</li>';
|
||||
$output .= '<li>' . t('<strong>Customize your website design</strong> To change the "look and feel" of your website, visit the <a href="@themes">themes section</a>. You may choose from one of the included themes or download additional themes from the <a href="@download_themes">Drupal themes download section</a>.', array('@themes' => url('admin/appearance'), '@download_themes' => 'http://drupal.org/project/themes')) . '</li>';
|
||||
$output .= '<li>' . t('<strong>Start posting content</strong> Finally, you can <a href="@content">add new content</a> for your website.', array('@content' => url('node/add'))) . '</li>';
|
||||
// Display a link to the create content page if Node module is enabled.
|
||||
if (module_exists('node')) {
|
||||
$output .= '<li>' . t('<strong>Start posting content</strong> Finally, you can <a href="@content">add new content</a> for your website.', array('@content' => url('node/add'))) . '</li>';
|
||||
}
|
||||
$output .= '</ol>';
|
||||
$output .= '<p>' . t('For more information, refer to the specific topics listed in the next section or to the <a href="@handbook">online Drupal handbooks</a>. You may also post at the <a href="@forum">Drupal forum</a> or view the wide range of <a href="@support">other support options</a> available.', array('@help' => url('admin/help'), '@handbook' => 'http://drupal.org/handbooks', '@forum' => 'http://drupal.org/forum', '@support' => 'http://drupal.org/support')) . '</p>';
|
||||
return $output;
|
||||
|
@ -61,3 +64,12 @@ function help_help($path, $arg) {
|
|||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_block().
|
||||
*/
|
||||
function help_preprocess_block(&$variables) {
|
||||
if ($variables['block']->module == 'help') {
|
||||
$variables['attributes_array']['role'] = 'complementary';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -842,7 +842,7 @@ function image_effect_definitions() {
|
|||
|
||||
// hook_image_effect_info() includes translated strings, so each language is
|
||||
// cached separately.
|
||||
$langcode = $language->language;
|
||||
$langcode = $language->langcode;
|
||||
|
||||
$effects = &drupal_static(__FUNCTION__);
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase {
|
|||
$this->assertNotIdentical(FALSE, $original_uri, t('Created the generated image file.'));
|
||||
|
||||
// Get the URL of a file that has not been generated and try to create it.
|
||||
$generated_uri = $scheme . '://styles/' . $this->style_name . '/' . $scheme . '/'. basename($original_uri);
|
||||
$generated_uri = $scheme . '://styles/' . $this->style_name . '/' . $scheme . '/'. drupal_basename($original_uri);
|
||||
$this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
|
||||
$generate_url = image_style_url($this->style_name, $original_uri);
|
||||
|
||||
|
@ -959,7 +959,7 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
|
|||
|
||||
// Create a style.
|
||||
$style = image_style_save(array('name' => 'test'));
|
||||
$generated_uri = 'public://styles/test/public/'. basename($original_uri);
|
||||
$generated_uri = 'public://styles/test/public/'. drupal_basename($original_uri);
|
||||
$url = image_style_url('test', $original_uri);
|
||||
|
||||
$variables = array(
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
function language_admin_overview_form($form, &$form_state) {
|
||||
drupal_static_reset('language_list');
|
||||
$languages = language_list('language');
|
||||
$languages = language_list();
|
||||
$default = language_default();
|
||||
|
||||
$form['languages'] = array(
|
||||
|
@ -37,7 +37,7 @@ function language_admin_overview_form($form, &$form_state) {
|
|||
'#title' => t('Enable @title', array('@title' => $language->name)),
|
||||
'#title_display' => 'invisible',
|
||||
'#default_value' => (int) $language->enabled,
|
||||
'#disabled' => $langcode == $default->language,
|
||||
'#disabled' => $langcode == $default->langcode,
|
||||
);
|
||||
$form['languages'][$langcode]['default'] = array(
|
||||
'#type' => 'radio',
|
||||
|
@ -45,7 +45,7 @@ function language_admin_overview_form($form, &$form_state) {
|
|||
'#title' => t('Set @title as default', array('@title' => $language->name)),
|
||||
'#title_display' => 'invisible',
|
||||
'#return_value' => $langcode,
|
||||
'#default_value' => ($langcode == $default->language ? $langcode : NULL),
|
||||
'#default_value' => ($langcode == $default->langcode ? $langcode : NULL),
|
||||
'#id' => 'edit-site-default-' . $langcode,
|
||||
);
|
||||
$form['languages'][$langcode]['weight'] = array(
|
||||
|
@ -70,7 +70,7 @@ function language_admin_overview_form($form, &$form_state) {
|
|||
'#type' => 'link',
|
||||
'#title' => t('delete'),
|
||||
'#href' => 'admin/config/regional/language/delete/' . $langcode,
|
||||
'#access' => $langcode != $default->language,
|
||||
'#access' => $langcode != $default->langcode,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,7 @@ function language_admin_overview_form_submit($form, &$form_state) {
|
|||
$language->default = ($form_state['values']['site_default'] == $langcode);
|
||||
$language->weight = $form_state['values']['languages'][$langcode]['weight'];
|
||||
|
||||
if ($language->default || $old_default->language == $langcode) {
|
||||
if ($language->default || $old_default->langcode == $langcode) {
|
||||
// Automatically enable the default language and the language
|
||||
// which was default previously (because we will not get the
|
||||
// value from that disabled checkbox).
|
||||
|
@ -244,15 +244,15 @@ function _language_admin_common_controls(&$form, $language = NULL) {
|
|||
if (!is_object($language)) {
|
||||
$language = new stdClass();
|
||||
}
|
||||
if (isset($language->language)) {
|
||||
if (isset($language->langcode)) {
|
||||
$form['langcode_view'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Language code'),
|
||||
'#markup' => $language->language
|
||||
'#markup' => $language->langcode
|
||||
);
|
||||
$form['langcode'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $language->language
|
||||
'#value' => $language->langcode
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -261,8 +261,8 @@ function _language_admin_common_controls(&$form, $language = NULL) {
|
|||
'#title' => t('Language code'),
|
||||
'#maxlength' => 12,
|
||||
'#required' => TRUE,
|
||||
'#default_value' => @$language->language,
|
||||
'#disabled' => (isset($language->language)),
|
||||
'#default_value' => @$language->langcode,
|
||||
'#disabled' => (isset($language->langcode)),
|
||||
'#description' => t('Use language codes as <a href="@w3ctags">defined by the W3C</a> for interoperability. <em>Examples: "en", "en-gb" and "zh-hant".</em>', array('@w3ctags' => 'http://www.w3.org/International/articles/language-tags/')),
|
||||
);
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ function language_admin_add_custom_form_submit($form, &$form_state) {
|
|||
$langcode = $form_state['values']['langcode'];
|
||||
// Custom language form.
|
||||
$language = (object) array(
|
||||
'language' => $langcode,
|
||||
'langcode' => $langcode,
|
||||
'name' => $form_state['values']['name'],
|
||||
'direction' => $form_state['values']['direction'],
|
||||
);
|
||||
|
@ -343,7 +343,7 @@ function language_admin_add_predefined_form_submit($form, &$form_state) {
|
|||
include_once DRUPAL_ROOT . '/core/includes/standard.inc';
|
||||
$predefined = standard_language_list();
|
||||
$language = (object) array(
|
||||
'language' => $langcode,
|
||||
'langcode' => $langcode,
|
||||
);
|
||||
language_save($language);
|
||||
drupal_set_message(t('The language %language has been created and can now be used.', array('%language' => t($predefined[$langcode][0]))));
|
||||
|
@ -381,9 +381,9 @@ function language_admin_edit_form_submit($form, &$form_state) {
|
|||
* User interface for the language deletion confirmation screen.
|
||||
*/
|
||||
function language_admin_delete_form($form, &$form_state, $language) {
|
||||
$langcode = $language->language;
|
||||
$langcode = $language->langcode;
|
||||
|
||||
if (language_default()->language == $langcode) {
|
||||
if (language_default()->langcode == $langcode) {
|
||||
drupal_set_message(t('The default language cannot be deleted.'));
|
||||
drupal_goto('admin/config/regional/language');
|
||||
}
|
||||
|
@ -412,7 +412,7 @@ function language_admin_delete_form_submit($form, &$form_state) {
|
|||
$success = language_delete($langcode);
|
||||
|
||||
if ($success) {
|
||||
$t_args = array('%language' => $language->name, '%langcode' => $language->language);
|
||||
$t_args = array('%language' => $language->name, '%langcode' => $language->langcode);
|
||||
drupal_set_message(t('The %language (%langcode) language has been removed.', $t_args));
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ function hook_language_delete($language) {
|
|||
// On nodes with this language, unset the language
|
||||
db_update('node')
|
||||
->fields(array('language' => ''))
|
||||
->condition('language', $language->language)
|
||||
->condition('language', $language->langcode)
|
||||
->execute();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ function language_schema() {
|
|||
$schema['language'] = array(
|
||||
'description' => 'List of all available languages in the system.',
|
||||
'fields' => array(
|
||||
'language' => array(
|
||||
'langcode' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 12,
|
||||
'not null' => TRUE,
|
||||
|
@ -66,7 +66,7 @@ function language_schema() {
|
|||
'description' => 'Weight, used in lists of languages.',
|
||||
),
|
||||
),
|
||||
'primary key' => array('language'),
|
||||
'primary key' => array('langcode'),
|
||||
'indexes' => array(
|
||||
'list' => array('weight', 'name'),
|
||||
),
|
||||
|
|
|
@ -121,14 +121,14 @@ function language_load($langcode) {
|
|||
* Language object with properties corresponding to 'language' table columns.
|
||||
*/
|
||||
function language_save($language) {
|
||||
$language->is_new = !(bool) db_query_range('SELECT 1 FROM {language} WHERE language = :language', 0, 1, array(':language' => $language->language))->fetchField();
|
||||
$language->is_new = !(bool) db_query_range('SELECT 1 FROM {language} WHERE langcode = :langcode', 0, 1, array(':langcode' => $language->langcode))->fetchField();
|
||||
|
||||
// If name was not set, we add a predefined language.
|
||||
if (!isset($language->name)) {
|
||||
include_once DRUPAL_ROOT . '/core/includes/standard.inc';
|
||||
$predefined = standard_language_list();
|
||||
$language->name = $predefined[$language->language][0];
|
||||
$language->direction = isset($predefined[$language->language][2]) ? $predefined[$language->language][2] : LANGUAGE_LTR;
|
||||
$language->name = $predefined[$language->langcode][0];
|
||||
$language->direction = isset($predefined[$language->langcode][2]) ? $predefined[$language->langcode][2] : LANGUAGE_LTR;
|
||||
}
|
||||
|
||||
// Set to enabled for the default language and unless specified otherwise.
|
||||
|
@ -139,14 +139,14 @@ function language_save($language) {
|
|||
module_invoke_all('language_presave', $language);
|
||||
|
||||
// Save the record and inform others about the change.
|
||||
$t_args = array('%language' => $language->name, '%langcode' => $language->language);
|
||||
$t_args = array('%language' => $language->name, '%langcode' => $language->langcode);
|
||||
if ($language->is_new) {
|
||||
drupal_write_record('language', $language);
|
||||
module_invoke_all('language_insert', $language);
|
||||
watchdog('language', 'The %language (%langcode) language has been created.', $t_args);
|
||||
}
|
||||
else {
|
||||
drupal_write_record('language', $language, array('language'));
|
||||
drupal_write_record('language', $language, array('langcode'));
|
||||
module_invoke_all('language_update', $language);
|
||||
watchdog('language', 'The %language (%langcode) language has been updated.', $t_args);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ function language_save($language) {
|
|||
}
|
||||
|
||||
// Update language count based on enabled language count.
|
||||
variable_set('language_count', db_query('SELECT COUNT(language) FROM {language} WHERE enabled = 1')->fetchField());
|
||||
variable_set('language_count', db_query('SELECT COUNT(langcode) FROM {language} WHERE enabled = 1')->fetchField());
|
||||
|
||||
// Kill the static cache in language_list().
|
||||
drupal_static_reset('language_list');
|
||||
|
@ -183,7 +183,7 @@ function language_delete($langcode) {
|
|||
|
||||
// Remove the language.
|
||||
db_delete('language')
|
||||
->condition('language', $language->language)
|
||||
->condition('langcode', $language->langcode)
|
||||
->execute();
|
||||
|
||||
if ($language->enabled) {
|
||||
|
@ -192,9 +192,36 @@ function language_delete($langcode) {
|
|||
|
||||
drupal_static_reset('language_list');
|
||||
|
||||
$t_args = array('%language' => $language->name, '%langcode' => $language->language);
|
||||
$t_args = array('%language' => $language->name, '%langcode' => $language->langcode);
|
||||
watchdog('language', 'The %language (%langcode) language has been removed.', $t_args);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_css_alter().
|
||||
*
|
||||
* This function checks all CSS files currently added via drupal_add_css() and
|
||||
* and checks to see if a related right to left CSS file should be included.
|
||||
*/
|
||||
function language_css_alter(&$css) {
|
||||
global $language;
|
||||
|
||||
// If the current language is RTL, add the CSS file with the RTL overrides.
|
||||
if ($language->direction == LANGUAGE_RTL) {
|
||||
foreach ($css as $data => $item) {
|
||||
// Only provide RTL overrides for files.
|
||||
if ($item['type'] == 'file') {
|
||||
$rtl_path = str_replace('.css', '-rtl.css', $item['data']);
|
||||
if (file_exists($rtl_path) && !isset($css[$rtl_path])) {
|
||||
// Replicate the same item, but with the RTL path and a little larger
|
||||
// weight so that it appears directly after the original CSS file.
|
||||
$item['data'] = $rtl_path;
|
||||
$item['weight'] += 0.01;
|
||||
$css[$rtl_path] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,8 +122,8 @@ class LanguageListTest extends DrupalWebTestCase {
|
|||
$this->assertResponse(404, t('Language no longer found.'));
|
||||
// Make sure the "language_count" variable has been updated correctly.
|
||||
drupal_static_reset('language_list');
|
||||
$enabled = language_list('enabled');
|
||||
$this->assertEqual(variable_get('language_count', 1), count($enabled[1]), t('Language count is correct.'));
|
||||
$enabled_languages = language_list(TRUE);
|
||||
$this->assertEqual(variable_get('language_count', 1), count($enabled_languages), t('Language count is correct.'));
|
||||
// Delete a disabled language.
|
||||
// Disable an enabled language.
|
||||
$edit = array(
|
||||
|
@ -133,7 +133,7 @@ class LanguageListTest extends DrupalWebTestCase {
|
|||
$this->assertNoFieldChecked('edit-languages-fr-enabled', t('French language disabled.'));
|
||||
// Get the count of enabled languages.
|
||||
drupal_static_reset('language_list');
|
||||
$enabled = language_list('enabled');
|
||||
$enabled_languages = language_list(TRUE);
|
||||
// Delete the disabled language.
|
||||
$this->drupalPost('admin/config/regional/language/delete/fr', array(), t('Delete'));
|
||||
// We need raw here because %language and %langcode will add HTML.
|
||||
|
@ -144,7 +144,7 @@ class LanguageListTest extends DrupalWebTestCase {
|
|||
$this->drupalGet('admin/config/regional/language/delete/fr');
|
||||
$this->assertResponse(404, t('Language no longer found.'));
|
||||
// Make sure the "language_count" variable has not changed.
|
||||
$this->assertEqual(variable_get('language_count', 1), count($enabled[1]), t('Language count is correct.'));
|
||||
$this->assertEqual(variable_get('language_count', 1), count($enabled_languages), t('Language count is correct.'));
|
||||
|
||||
// Ensure we can delete the English language. Right now English is the only
|
||||
// language so we must add a new language and make it the default before
|
||||
|
|
|
@ -256,20 +256,21 @@ function locale_language_providers_url_form($form, &$form_state) {
|
|||
),
|
||||
);
|
||||
|
||||
$languages = language_list('enabled');
|
||||
// Get the enabled languages only.
|
||||
$languages = language_list(TRUE);
|
||||
$prefixes = locale_language_negotiation_url_prefixes();
|
||||
$domains = locale_language_negotiation_url_domains();
|
||||
foreach ($languages[1] as $langcode => $language) {
|
||||
foreach ($languages as $langcode => $language) {
|
||||
$form['prefix'][$langcode] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('%language (%langcode) path prefix', array('%language' => $language->name, '%langcode' => $language->language)),
|
||||
'#title' => t('%language (%langcode) path prefix', array('%language' => $language->name, '%langcode' => $language->langcode)),
|
||||
'#maxlength' => 64,
|
||||
'#default_value' => isset($prefixes[$langcode]) ? $prefixes[$langcode] : '',
|
||||
'#field_prefix' => url('', array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
|
||||
);
|
||||
$form['domain'][$langcode] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('%language (%langcode) domain', array('%language' => $language->name, '%langcode' => $language->language)),
|
||||
'#title' => t('%language (%langcode) domain', array('%language' => $language->name, '%langcode' => $language->langcode)),
|
||||
'#maxlength' => 128,
|
||||
'#default_value' => isset($domains[$langcode]) ? $domains[$langcode] : '',
|
||||
);
|
||||
|
@ -292,40 +293,41 @@ function locale_language_providers_url_form($form, &$form_state) {
|
|||
* the prefix and domain are only blank for the default.
|
||||
*/
|
||||
function locale_language_providers_url_form_validate($form, &$form_state) {
|
||||
$languages = locale_language_list();
|
||||
// Get the enabled languages only.
|
||||
$languages = language_list(TRUE);
|
||||
$default = language_default();
|
||||
|
||||
// Count repeated values for uniqueness check.
|
||||
$count = array_count_values($form_state['values']['prefix']);
|
||||
foreach ($languages as $langcode => $name) {
|
||||
foreach ($languages as $langcode => $language) {
|
||||
$value = $form_state['values']['prefix'][$langcode];
|
||||
|
||||
if ($value === '') {
|
||||
if ($default->language != $langcode && $form_state['values']['locale_language_negotiation_url_part'] == LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX) {
|
||||
if (!$language->default && $form_state['values']['locale_language_negotiation_url_part'] == LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX) {
|
||||
// Validation error if the prefix is blank for a non-default language, and value is for selected negotiation type.
|
||||
form_error($form['prefix'][$langcode], t('The prefix may only be left blank for the default language.'));
|
||||
}
|
||||
}
|
||||
else if (isset($count[$value]) && $count[$value] > 1) {
|
||||
// Validation error if there are two languages with the same domain/prefix.
|
||||
form_error($form['prefix'][$langcode], t('The prefix for %language, %value, is not unique.', array( '%language' => $name, '%value' => $value )));
|
||||
form_error($form['prefix'][$langcode], t('The prefix for %language, %value, is not unique.', array('%language' => $language->name, '%value' => $value)));
|
||||
}
|
||||
}
|
||||
|
||||
// Count repeated values for uniqueness check.
|
||||
$count = array_count_values($form_state['values']['domain']);
|
||||
foreach ($languages as $langcode => $name) {
|
||||
foreach ($languages as $langcode => $language) {
|
||||
$value = $form_state['values']['domain'][$langcode];
|
||||
|
||||
if ($value === '') {
|
||||
if ($default->language != $langcode && $form_state['values']['locale_language_negotiation_url_part'] == LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN) {
|
||||
if (!$language->default && $form_state['values']['locale_language_negotiation_url_part'] == LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN) {
|
||||
// Validation error if the domain is blank for a non-default language, and value is for selected negotiation type.
|
||||
form_error($form['domain'][$langcode], t('The domain may only be left blank for the default language.'));
|
||||
}
|
||||
}
|
||||
else if (isset($count[$value]) && $count[$value] > 1) {
|
||||
// Validation error if there are two languages with the same domain/domain.
|
||||
form_error($form['domain'][$langcode], t('The domain for %language, %value, is not unique.', array( '%language' => $name, '%value' => $value )));
|
||||
form_error($form['domain'][$langcode], t('The domain for %language, %value, is not unique.', array('%language' => $language->name, '%value' => $value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,12 +407,12 @@ function locale_date_format_language_overview_page() {
|
|||
array('data' => t('Operations'), 'colspan' => '2'),
|
||||
);
|
||||
|
||||
// Get list of languages.
|
||||
$languages = locale_language_list();
|
||||
// Get the enabled languages only.
|
||||
$languages = language_list(TRUE);
|
||||
|
||||
foreach ($languages as $langcode => $info) {
|
||||
foreach ($languages as $langcode => $language) {
|
||||
$row = array();
|
||||
$row[] = $languages[$langcode];
|
||||
$row[] = $language->name;
|
||||
$row[] = l(t('edit'), 'admin/config/regional/date-time/locale/' . $langcode . '/edit');
|
||||
$row[] = l(t('reset'), 'admin/config/regional/date-time/locale/' . $langcode . '/reset');
|
||||
$rows[] = $row;
|
||||
|
@ -423,14 +425,11 @@ function locale_date_format_language_overview_page() {
|
|||
* Provide date localization configuration options to users.
|
||||
*/
|
||||
function locale_date_format_form($form, &$form_state, $langcode) {
|
||||
$languages = locale_language_list();
|
||||
$language_name = $languages[$langcode];
|
||||
|
||||
// Display the current language name.
|
||||
$form['language'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Language'),
|
||||
'#markup' => check_plain($language_name),
|
||||
'#markup' => language_load($langcode)->name,
|
||||
'#weight' => -10,
|
||||
);
|
||||
$form['langcode'] = array(
|
||||
|
@ -509,9 +508,8 @@ function locale_date_format_form_submit($form, &$form_state) {
|
|||
*/
|
||||
function locale_date_format_reset_form($form, &$form_state, $langcode) {
|
||||
$form['langcode'] = array('#type' => 'value', '#value' => $langcode);
|
||||
$languages = language_list();
|
||||
return confirm_form($form,
|
||||
t('Are you sure you want to reset the date formats for %language to the global defaults?', array('%language' => $languages[$langcode]->name)),
|
||||
t('Are you sure you want to reset the date formats for %language to the global defaults?', array('%language' => language_load($langcode)->name)),
|
||||
'admin/config/regional/date-time/locale',
|
||||
t('Resetting will remove all localized date formats for this language. This action cannot be undone.'),
|
||||
t('Reset'), t('Cancel'));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue