2001-12-01 15:20:48 +00:00
< ? php
2014-04-15 21:14:29 +00:00
/**
* @ file
* Common functions that many Drupal modules will need to reference .
*
* The functions that are critical and need to be available even when serving
* a cached page are instead located in bootstrap . inc .
*/
2014-04-18 15:32:47 +00:00
use Drupal\Component\Serialization\Json ;
2014-05-23 19:25:52 +00:00
use Drupal\Component\Utility\Bytes ;
2014-08-29 04:34:31 +00:00
use Drupal\Component\Utility\Html ;
2013-08-05 22:24:38 +00:00
use Drupal\Component\Utility\SortArray ;
2014-03-05 20:22:39 +00:00
use Drupal\Component\Utility\UrlHelper ;
2013-03-22 09:36:55 +00:00
use Drupal\Core\Cache\Cache ;
2018-10-08 11:28:07 +00:00
use Drupal\Core\Render\HtmlResponseAttachmentsProcessor ;
2016-04-30 14:11:15 +00:00
use Drupal\Core\Render\Element\Link ;
2015-10-01 23:25:03 +00:00
use Drupal\Core\Render\Markup ;
use Drupal\Core\StringTranslation\TranslatableMarkup ;
use Drupal\Core\StringTranslation\PluralTranslatableMarkup ;
2015-06-05 20:57:04 +00:00
use Drupal\Core\Render\BubbleableMetadata ;
2013-12-10 21:23:03 +00:00
use Drupal\Core\Render\Element ;
2011-12-27 21:17:19 +00:00
2009-09-28 22:22:54 +00:00
/**
* @ defgroup php_wrappers PHP wrapper functions
* @ {
* Functions that are wrappers or custom implementations of PHP functions .
*
* Certain PHP functions should not be used in Drupal . Instead , Drupal ' s
* replacement functions should be used .
*
* For example , for improved or more secure UTF8 - handling , or RFC - compliant
* handling of URLs in Drupal .
*
* For ease of use and memorizing , all these wrapper functions use the same name
* as the original PHP function , but prefixed with " drupal_ " . Beware , however ,
* that not all wrapper functions support the same arguments as the original
* functions .
*
* You should always use these wrapper functions in your code .
*
* Wrong :
* @ code
* $my_substring = substr ( $original_string , 0 , 5 );
* @ endcode
*
* Correct :
* @ code
2018-05-08 16:23:11 +00:00
* $my_substring = mb_substr ( $original_string , 0 , 5 );
2009-09-28 22:22:54 +00:00
* @ endcode
*
2010-12-15 03:00:40 +00:00
* @ }
2009-09-28 22:22:54 +00:00
*/
2005-05-07 01:48:06 +00:00
/**
* Return status for saving which involved creating a new item .
*/
2011-11-29 09:56:53 +00:00
const SAVED_NEW = 1 ;
2005-05-07 01:48:06 +00:00
/**
* Return status for saving which involved an update to an existing item .
*/
2011-11-29 09:56:53 +00:00
const SAVED_UPDATED = 2 ;
2005-05-07 01:48:06 +00:00
/**
* Return status for saving which deleted an existing item .
*/
2011-11-29 09:56:53 +00:00
const SAVED_DELETED = 3 ;
2005-05-07 01:48:06 +00:00
2009-07-30 19:57:10 +00:00
/**
2013-04-04 02:14:52 +00:00
* The default aggregation group for CSS files added to the page .
2009-07-30 19:57:10 +00:00
*/
2013-04-04 02:14:52 +00:00
const CSS_AGGREGATE_DEFAULT = 0 ;
2009-07-30 19:57:10 +00:00
/**
2013-04-04 02:14:52 +00:00
* The default aggregation group for theme CSS files added to the page .
2009-07-30 19:57:10 +00:00
*/
2013-04-04 02:14:52 +00:00
const CSS_AGGREGATE_THEME = 100 ;
/**
* The default weight for CSS rules that style HTML elements ( " base " styles ) .
*/
const CSS_BASE = - 200 ;
/**
* The default weight for CSS rules that layout a page .
*/
const CSS_LAYOUT = - 100 ;
/**
2014-03-04 18:04:01 +00:00
* The default weight for CSS rules that style design components ( and their associated states and themes . )
2013-04-04 02:14:52 +00:00
*/
const CSS_COMPONENT = 0 ;
/**
* The default weight for CSS rules that style states and are not included with components .
*/
const CSS_STATE = 100 ;
/**
2014-03-04 18:04:01 +00:00
* The default weight for CSS rules that style themes and are not included with components .
2013-04-04 02:14:52 +00:00
*/
2014-03-04 18:04:01 +00:00
const CSS_THEME = 200 ;
2009-07-30 19:57:10 +00:00
2012-09-24 13:12:09 +00:00
/**
* The default group for JavaScript settings added to the page .
*/
const JS_SETTING = - 200 ;
2008-11-10 05:23:01 +00:00
/**
2011-12-05 12:52:27 +00:00
* The default group for JavaScript and jQuery libraries added to the page .
2008-11-10 05:23:01 +00:00
*/
2011-11-29 09:56:53 +00:00
const JS_LIBRARY = - 100 ;
2008-11-10 05:23:01 +00:00
/**
2010-10-05 19:59:10 +00:00
* The default group for module JavaScript code added to the page .
2008-11-10 05:23:01 +00:00
*/
2011-11-29 09:56:53 +00:00
const JS_DEFAULT = 0 ;
2008-11-10 05:23:01 +00:00
/**
2010-10-05 19:59:10 +00:00
* The default group for theme JavaScript code added to the page .
2008-11-10 05:23:01 +00:00
*/
2011-11-29 09:56:53 +00:00
const JS_THEME = 100 ;
2008-11-10 05:23:01 +00:00
2012-03-11 02:35:21 +00:00
/**
* The delimiter used to split plural strings .
*
2015-09-20 17:37:52 +00:00
* @ deprecated in Drupal 8.0 . x - dev , will be removed before Drupal 9.0 . 0.
2015-10-01 23:25:03 +00:00
* Use \Drupal\Core\StringTranslation\PluralTranslatableMarkup :: DELIMITER
2015-09-20 17:37:52 +00:00
* instead .
2012-03-11 02:35:21 +00:00
*/
2015-10-01 23:25:03 +00:00
const LOCALE_PLURAL_DELIMITER = PluralTranslatableMarkup :: DELIMITER ;
2012-03-11 02:35:21 +00:00
2005-02-01 19:45:58 +00:00
/**
2016-03-10 16:05:49 +00:00
* Prepares a 'destination' URL query parameter .
2007-10-12 14:10:18 +00:00
*
2007-10-08 14:08:19 +00:00
* Used to direct the user back to the referring page after completing a form .
* By default the current URL is returned . If a destination exists in the
* previous request , that destination is returned . As such , a destination can
* persist across multiple pages .
2005-02-01 19:45:58 +00:00
*
2015-02-02 21:58:16 +00:00
* @ return array
2012-08-23 14:36:36 +00:00
* An associative array containing the key :
2015-02-02 21:58:16 +00:00
* - destination : The value of the current request 's ' destination ' query
* parameter , if present . This can be either a relative or absolute URL .
* However , for security , redirection to external URLs is not performed .
* If the query parameter isn ' t present , then the URL of the current
* request is returned .
2012-08-23 14:36:36 +00:00
*
2014-07-24 16:31:01 +00:00
* @ ingroup form_api
2015-03-10 12:15:11 +00:00
*
* @ deprecated in Drupal 8.0 . x - dev , will be removed before Drupal 9.0 . 0.
* Use the redirect . destination service .
2017-11-11 22:06:57 +00:00
*
* @ see \Drupal\Core\EventSubscriber\RedirectResponseSubscriber :: checkRedirectUrl ()
* @ see https :// www . drupal . org / node / 2448603
2005-02-01 19:45:58 +00:00
*/
function drupal_get_destination () {
2015-03-10 12:15:11 +00:00
return \Drupal :: destination () -> getAsArray ();
2009-09-29 15:31:17 +00:00
}
2004-01-06 19:52:14 +00:00
/**
2004-09-09 05:51:08 +00:00
* @ defgroup validation Input validation
2004-02-08 17:12:44 +00:00
* @ {
2004-09-09 05:51:08 +00:00
* Functions to validate user input .
2004-01-06 19:52:14 +00:00
*/
2003-03-28 10:55:27 +00:00
/**
2014-06-09 21:47:53 +00:00
* Verifies the syntax of the given email address .
2004-07-13 07:21:14 +00:00
*
2015-01-30 11:03:07 +00:00
* @ param string $mail
2014-06-09 21:47:53 +00:00
* A string containing an email address .
2011-12-05 12:52:27 +00:00
*
2015-01-30 11:03:07 +00:00
* @ return bool
2004-07-13 07:21:14 +00:00
* TRUE if the address is in a valid format .
2015-01-30 11:03:07 +00:00
*
* @ deprecated in Drupal 8.0 . x - dev , will be removed before Drupal 9.0 . 0.
* Use \Drupal :: service ( 'email.validator' ) -> isValid () .
2017-11-13 15:54:42 +00:00
*
* @ see https :// www . drupal . org / node / 2912661
2003-03-28 10:55:27 +00:00
*/
2003-04-13 13:42:51 +00:00
function valid_email_address ( $mail ) {
2015-01-30 11:03:07 +00:00
return \Drupal :: service ( 'email.validator' ) -> isValid ( $mail );
2003-03-28 10:55:27 +00:00
}
2008-01-28 16:05:17 +00:00
/**
* @ } End of " defgroup validation " .
*/
2009-05-24 07:17:14 +00:00
/**
* @ defgroup sanitization Sanitization functions
* @ {
* Functions to sanitize values .
2010-04-24 14:53:59 +00:00
*
2015-05-24 20:08:46 +00:00
* See https :// www . drupal . org / writing - secure - code for information
2010-04-24 14:53:59 +00:00
* on writing secure code .
2009-05-24 07:17:14 +00:00
*/
2010-07-07 17:00:43 +00:00
/**
2011-12-05 12:52:27 +00:00
* Strips dangerous protocols from a URI and encodes it for output to HTML .
2010-07-07 17:00:43 +00:00
*
* @ param $uri
* A plain - text URI that might contain dangerous protocols .
*
2015-08-31 07:51:38 +00:00
* @ return string
2010-07-07 17:00:43 +00:00
* A URI stripped of dangerous protocols and encoded for output to an HTML
* attribute value . Because it is already encoded , it should not be set as a
2012-09-04 13:32:47 +00:00
* value within a $attributes array passed to Drupal\Core\Template\Attribute ,
* because Drupal\Core\Template\Attribute expects those values to be
* plain - text strings . To pass a filtered URI to
2013-10-09 04:42:16 +00:00
* Drupal\Core\Template\Attribute , call
2014-03-05 20:22:39 +00:00
* \Drupal\Component\Utility\UrlHelper :: stripDangerousProtocols () instead .
2010-07-07 17:00:43 +00:00
*
2015-08-31 07:51:38 +00:00
* @ deprecated in Drupal 8.0 . x - dev , will be removed before Drupal 9.0 . 0.
* Use UrlHelper :: stripDangerousProtocols () or UrlHelper :: filterBadProtocol ()
* instead . UrlHelper :: stripDangerousProtocols () can be used in conjunction
2018-05-01 15:14:09 +00:00
* with \Drupal\Component\Render\FormattableMarkup and an @ variable
2015-08-31 07:51:38 +00:00
* placeholder which will perform the necessary escaping .
* UrlHelper :: filterBadProtocol () is functionality equivalent to check_url ()
* apart from the fact it is protected from double escaping bugs . Note that
* this method no longer marks its output as safe .
2017-11-10 15:10:12 +00:00
*
* @ see \Drupal\Component\Utility\UrlHelper :: stripDangerousProtocols ()
* @ see \Drupal\Component\Utility\UrlHelper :: filterBadProtocol ()
* @ see https :// www . drupal . org / node / 2560027
2005-11-30 10:27:13 +00:00
*/
function check_url ( $uri ) {
2015-08-31 07:51:38 +00:00
return Html :: escape ( UrlHelper :: stripDangerousProtocols ( $uri ));
2005-11-30 10:27:13 +00:00
}
2009-05-24 07:17:14 +00:00
/**
* @ } End of " defgroup sanitization " .
*/
2004-02-08 17:12:44 +00:00
/**
2004-09-09 05:51:08 +00:00
* @ defgroup format Formatting
2004-02-08 17:12:44 +00:00
* @ {
2004-09-09 05:51:08 +00:00
* Functions to format numbers , strings , dates , etc .
2004-02-08 17:12:44 +00:00
*/
/**
2011-12-05 12:52:27 +00:00
* Generates a string representation for the given byte count .
2004-02-08 17:12:44 +00:00
*
2004-07-13 07:21:14 +00:00
* @ param $size
2007-10-08 14:08:19 +00:00
* A size in bytes .
2007-05-29 14:37:49 +00:00
* @ param $langcode
2007-10-08 14:08:19 +00:00
* Optional language code to translate to a language other than what is used
* to display the page .
2011-12-05 12:52:27 +00:00
*
2015-10-01 23:25:03 +00:00
* @ return \Drupal\Core\StringTranslation\TranslatableMarkup
2004-07-13 07:21:14 +00:00
* A translated string representation of the size .
2004-02-08 17:12:44 +00:00
*/
2007-05-29 14:37:49 +00:00
function format_size ( $size , $langcode = NULL ) {
2014-05-23 19:25:52 +00:00
if ( $size < Bytes :: KILOBYTE ) {
2017-03-04 01:20:24 +00:00
return \Drupal :: translation () -> formatPlural ( $size , '1 byte' , '@count bytes' , [], [ 'langcode' => $langcode ]);
2001-12-01 15:20:48 +00:00
}
2006-12-30 21:33:04 +00:00
else {
2017-10-13 12:43:02 +00:00
// Convert bytes to kilobytes.
$size = $size / Bytes :: KILOBYTE ;
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
$units = [ 'KB' , 'MB' , 'GB' , 'TB' , 'PB' , 'EB' , 'ZB' , 'YB' ];
2008-08-14 09:21:49 +00:00
foreach ( $units as $unit ) {
2014-05-23 19:25:52 +00:00
if ( round ( $size , 2 ) >= Bytes :: KILOBYTE ) {
$size = $size / Bytes :: KILOBYTE ;
2008-06-09 08:11:45 +00:00
}
else {
break ;
}
2006-12-30 21:33:04 +00:00
}
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
$args = [ '@size' => round ( $size , 2 )];
$options = [ 'langcode' => $langcode ];
switch ( $unit ) {
case 'KB' :
2015-10-01 23:25:03 +00:00
return new TranslatableMarkup ( '@size KB' , $args , $options );
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
case 'MB' :
2015-10-01 23:25:03 +00:00
return new TranslatableMarkup ( '@size MB' , $args , $options );
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
case 'GB' :
2015-10-01 23:25:03 +00:00
return new TranslatableMarkup ( '@size GB' , $args , $options );
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
case 'TB' :
2015-10-01 23:25:03 +00:00
return new TranslatableMarkup ( '@size TB' , $args , $options );
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
case 'PB' :
2015-10-01 23:25:03 +00:00
return new TranslatableMarkup ( '@size PB' , $args , $options );
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
case 'EB' :
2015-10-01 23:25:03 +00:00
return new TranslatableMarkup ( '@size EB' , $args , $options );
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
case 'ZB' :
2015-10-01 23:25:03 +00:00
return new TranslatableMarkup ( '@size ZB' , $args , $options );
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
case 'YB' :
2015-10-01 23:25:03 +00:00
return new TranslatableMarkup ( '@size YB' , $args , $options );
Issue #2557113 by stefan.r, alexpott, dawehner, joelpittet, cilefen, lauriii, plach, catch, chx, xjm: Make t() return a TranslationWrapper object to remove reliance on a static, unpredictable safe list
2015-09-19 04:33:21 +00:00
}
2001-12-01 15:20:48 +00:00
}
}
2004-02-08 17:12:44 +00:00
/**
2010-11-30 06:30:21 +00:00
* Formats a date , using a date type or a custom date format string .
2004-02-08 17:12:44 +00:00
*
2004-07-13 07:21:14 +00:00
* @ param $timestamp
2010-11-30 06:30:21 +00:00
* A UNIX timestamp to format .
2004-07-13 07:21:14 +00:00
* @ param $type
2010-11-30 06:30:21 +00:00
* ( optional ) The format to use , one of :
2012-11-29 07:37:55 +00:00
* - One of the built - in formats : 'short' , 'medium' ,
* 'long' , 'html_datetime' , 'html_date' , 'html_time' ,
* 'html_yearless_date' , 'html_week' , 'html_month' , 'html_year' .
2014-09-09 13:22:57 +00:00
* - The name of a date type defined by a date format config entity .
2010-11-30 06:30:21 +00:00
* - The machine name of an administrator - defined date format .
* - 'custom' , to use $format .
* Defaults to 'medium' .
2004-07-13 07:21:14 +00:00
* @ param $format
2010-11-30 06:30:21 +00:00
* ( optional ) If $type is 'custom' , a PHP date format string suitable for
* input to date () . Use a backslash to escape ordinary text , so it does not
* get interpreted as date format characters .
2004-07-13 07:21:14 +00:00
* @ param $timezone
2010-11-30 06:30:21 +00:00
* ( optional ) Time zone identifier , as described at
2012-03-24 06:14:35 +00:00
* http :// php . net / manual / timezones . php Defaults to the time zone used to
2010-11-30 06:30:21 +00:00
* display the page .
2007-05-29 14:37:49 +00:00
* @ param $langcode
2010-11-30 06:30:21 +00:00
* ( optional ) Language code to translate to . Defaults to the language used to
* display the page .
*
2004-07-13 07:21:14 +00:00
* @ return
* A translated date string in the requested format .
2013-06-12 09:18:07 +00:00
*
2015-08-20 21:42:55 +00:00
* @ deprecated in Drupal 8.0 . 0 , will be removed before Drupal 9.0 . 0.
* Use \Drupal :: service ( 'date.formatter' ) -> format () .
2017-11-13 15:53:20 +00:00
*
* @ see \Drupal\Core\Datetime\DateFormatter :: format ()
* @ see https :// www . drupal . org / node / 1876852
2004-02-08 17:12:44 +00:00
*/
2007-05-29 14:37:49 +00:00
function format_date ( $timestamp , $type = 'medium' , $format = '' , $timezone = NULL , $langcode = NULL ) {
2014-08-05 10:39:21 +00:00
return \Drupal :: service ( 'date.formatter' ) -> format ( $timestamp , $type , $format , $timezone , $langcode );
2009-07-08 20:40:21 +00:00
}
2009-10-18 18:32:27 +00:00
/**
* Returns an ISO8601 formatted date based on the given date .
*
2018-11-15 15:00:30 +00:00
* @ param string $date
2009-10-18 18:32:27 +00:00
* A UNIX timestamp .
2011-12-05 12:52:27 +00:00
*
2009-10-18 18:32:27 +00:00
* @ return string
* An ISO8601 formatted date .
2018-11-15 15:00:30 +00:00
*
* @ deprecated in Drupal 8.7 . 0 and will be removed before Drupal 9.0 . 0. Use
* date ( 'c' , $date ) instead .
*
* @ see https :// www . drupal . org / node / 2999991
2009-10-18 18:32:27 +00:00
*/
function date_iso8601 ( $date ) {
2018-11-15 15:00:30 +00:00
@ trigger_error ( 'date_iso8601() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use date("c", $date) instead. See https://www.drupal.org/node/2999991.' , E_USER_DEPRECATED );
2009-10-18 18:32:27 +00:00
// The DATE_ISO8601 constant cannot be used here because it does not match
// date('c') and produces invalid RDF markup.
return date ( 'c' , $date );
}
2004-09-09 05:51:08 +00:00
/**
* @ } End of " defgroup format " .
*/
2001-12-01 15:20:48 +00:00
2009-11-03 06:47:23 +00:00
/**
2011-12-05 12:52:27 +00:00
* Formats an attribute string for an HTTP header .
2009-11-03 06:47:23 +00:00
*
2018-10-08 11:28:07 +00:00
* @ param array $attributes
2009-11-03 06:47:23 +00:00
* An associative array of attributes such as 'rel' .
*
2018-10-08 11:28:07 +00:00
* @ return string
2009-11-03 06:47:23 +00:00
* A ; separated string ready for insertion in a HTTP header . No escaping is
* performed for HTML entities , so this string is not safe to be printed .
2018-10-08 11:28:07 +00:00
*
* @ deprecated in Drupal 8.7 . 0 and will be removed before Drupal 9.0 . 0. Use
* \Drupal\Core\Render\HtmlResponseAttachmentsProcessor :: formatHttpHeaderAttributes ()
* instead .
*
* @ see https :// www . drupal . org / node / 3000051
2009-11-03 06:47:23 +00:00
*/
2017-03-04 01:20:24 +00:00
function drupal_http_header_attributes ( array $attributes = []) {
2018-10-08 14:54:51 +00:00
@ trigger_error ( " drupal_http_header_attributes() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \ Drupal \ Core \R ender \ HtmlResponseAttachmentsProcessor::formatHttpHeaderAttributes() instead. See https://www.drupal.org/node/3000051 " , E_USER_DEPRECATED );
2018-10-08 11:28:07 +00:00
return HtmlResponseAttachmentsProcessor :: formatHttpHeaderAttributes ( $attributes );
2009-11-03 06:47:23 +00:00
}
2009-08-05 15:58:35 +00:00
/**
* Attempts to set the PHP maximum execution time .
*
* This function is a wrapper around the PHP function set_time_limit () .
* When called , set_time_limit () restarts the timeout counter from zero .
* In other words , if the timeout is the default 30 seconds , and 25 seconds
* into script execution a call such as set_time_limit ( 20 ) is made , the
* script will run for a total of 45 seconds before timing out .
2009-08-15 06:20:20 +00:00
*
2014-04-07 17:56:16 +00:00
* If the current time limit is not unlimited it is possible to decrease the
* total time limit if the sum of the new time limit and the current time spent
* running the script is inferior to the original time limit . It is inherent to
* the way set_time_limit () works , it should rather be called with an
* appropriate value every time you need to allocate a certain amount of time
2009-08-05 15:58:35 +00:00
* to execute a task than only once at the beginning of the script .
2009-08-15 06:20:20 +00:00
*
2009-08-05 15:58:35 +00:00
* Before calling set_time_limit (), we check if this function is available
* because it could be disabled by the server administrator . We also hide all
* the errors that could occur when calling set_time_limit (), because it is
* not possible to reliably ensure that PHP or a security extension will
* not issue a warning / error if they prevent the use of this function .
*
* @ param $time_limit
* An integer specifying the new time limit , in seconds . A value of 0
* indicates unlimited execution time .
2009-09-28 22:22:54 +00:00
*
* @ ingroup php_wrappers
2009-08-05 15:58:35 +00:00
*/
function drupal_set_time_limit ( $time_limit ) {
if ( function_exists ( 'set_time_limit' )) {
2014-04-07 17:56:16 +00:00
$current = ini_get ( 'max_execution_time' );
// Do not set time limit if it is currently unlimited.
2014-04-09 10:01:37 +00:00
if ( $current != 0 ) {
2014-04-07 17:56:16 +00:00
@ set_time_limit ( $time_limit );
}
2009-08-05 15:58:35 +00:00
}
}
2006-02-02 12:44:57 +00:00
/**
2011-12-05 12:52:27 +00:00
* Returns the base URL path ( i . e . , directory ) of the Drupal installation .
2009-04-26 07:50:51 +00:00
*
2018-05-11 09:46:46 +00:00
* Function base_path () adds a " / " to the beginning and end of the returned path
* if the path is not empty . At the very least , this will return " / " .
2009-04-26 07:50:51 +00:00
*
2009-05-01 16:45:52 +00:00
* Examples :
* - http :// example . com returns " / " because the path is empty .
* - http :// example . com / drupal / folder returns " /drupal/folder/ " .
2006-02-02 12:44:57 +00:00
*/
function base_path () {
2012-04-01 01:17:44 +00:00
return $GLOBALS [ 'base_path' ];
2006-02-02 12:44:57 +00:00
}
2006-12-10 09:54:35 +00:00
/**
2010-05-09 19:44:25 +00:00
* Deletes old cached CSS files .
2011-12-05 12:52:27 +00:00
*
2014-08-08 16:52:12 +00:00
* @ deprecated in Drupal 8. x , will be removed before Drupal 9.0 .
* Use \Drupal\Core\Asset\AssetCollectionOptimizerInterface :: deleteAll () .
2017-11-13 15:35:45 +00:00
*
* @ see https :// www . drupal . org / node / 2317841
2010-05-09 19:44:25 +00:00
*/
2014-08-08 16:52:12 +00:00
function drupal_clear_css_cache () {
\Drupal :: service ( 'asset.css.collection_optimizer' ) -> deleteAll ();
2006-08-03 07:06:36 +00:00
}
2005-05-24 06:00:22 +00:00
/**
2015-01-21 15:21:06 +00:00
* Constructs an array of the defaults that are used for JavaScript assets .
2008-11-23 16:00:08 +00:00
*
* @ param $data
2015-01-21 15:21:06 +00:00
* ( optional ) The default data parameter for the JavaScript asset array .
2011-12-05 12:52:27 +00:00
*
2015-01-21 15:21:06 +00:00
* @ see hook_js_alter ()
2008-11-23 16:00:08 +00:00
*/
function drupal_js_defaults ( $data = NULL ) {
2017-03-04 01:20:24 +00:00
return [
2008-11-23 16:00:08 +00:00
'type' => 'file' ,
2010-10-05 19:59:10 +00:00
'group' => JS_DEFAULT ,
'weight' => 0 ,
2008-11-23 16:00:08 +00:00
'scope' => 'header' ,
'cache' => TRUE ,
2010-10-05 19:59:10 +00:00
'preprocess' => TRUE ,
2017-03-04 01:20:24 +00:00
'attributes' => [],
2010-03-09 03:39:44 +00:00
'version' => NULL ,
2008-11-23 16:00:08 +00:00
'data' => $data ,
2017-03-04 01:20:24 +00:00
'browsers' => [],
];
2008-11-23 16:00:08 +00:00
}
2009-10-16 19:20:34 +00:00
/**
2010-05-01 00:05:04 +00:00
* Adds JavaScript to change the state of an element based on another element .
2009-10-16 19:20:34 +00:00
*
2010-05-01 00:05:04 +00:00
* A " state " means a certain property on a DOM element , such as " visible " or
* " checked " . A state can be applied to an element , depending on the state of
* another element on the page . In general , states depend on HTML attributes and
* DOM element properties , which change due to user interaction .
*
* Since states are driven by JavaScript only , it is important to understand
* that all states are applied on presentation only , none of the states force
* any server - side logic , and that they will not be applied for site visitors
* without JavaScript support . All modules implementing states have to make
* sure that the intended logic also works without JavaScript being enabled .
*
* #states is an associative array in the form of:
* @ code
* array (
* STATE1 => CONDITIONS_ARRAY1 ,
* STATE2 => CONDITIONS_ARRAY2 ,
* ...
* )
* @ endcode
* Each key is the name of a state to apply to the element , such as 'visible' .
* Each value is a list of conditions that denote when the state should be
* applied .
*
* Multiple different states may be specified to act on complex conditions :
* @ code
* array (
* 'visible' => CONDITIONS ,
* 'checked' => OTHER_CONDITIONS ,
* )
* @ endcode
*
* Every condition is a key / value pair , whose key is a jQuery selector that
* denotes another element on the page , and whose value is an array of
* conditions , which must bet met on that element :
* @ code
* array (
* 'visible' => array (
* JQUERY_SELECTOR => REMOTE_CONDITIONS ,
* JQUERY_SELECTOR => REMOTE_CONDITIONS ,
* ...
* ),
* )
* @ endcode
* All conditions must be met for the state to be applied .
*
* Each remote condition is a key / value pair specifying conditions on the other
* element that need to be met to apply the state to the element :
* @ code
* array (
* 'visible' => array (
* ':input[name="remote_checkbox"]' => array ( 'checked' => TRUE ),
* ),
* )
* @ endcode
*
* For example , to show a textfield only when a checkbox is checked :
* @ code
* $form [ 'toggle_me' ] = array (
* '#type' => 'checkbox' ,
* '#title' => t ( 'Tick this box to type' ),
* );
* $form [ 'settings' ] = array (
* '#type' => 'textfield' ,
* '#states' => array (
* // Only show this field when the 'toggle_me' checkbox is enabled.
* 'visible' => array (
* ':input[name="toggle_me"]' => array ( 'checked' => TRUE ),
2009-10-16 19:20:34 +00:00
* ),
2010-05-01 00:05:04 +00:00
* ),
* );
* @ endcode
*
* The following states may be applied to an element :
* - enabled
* - disabled
2011-08-10 19:47:50 +00:00
* - required
* - optional
2010-05-01 00:05:04 +00:00
* - visible
* - invisible
* - checked
* - unchecked
* - expanded
* - collapsed
*
* The following states may be used in remote conditions :
2011-08-10 19:47:50 +00:00
* - empty
* - filled
2010-05-01 00:05:04 +00:00
* - checked
* - unchecked
2011-08-10 19:47:50 +00:00
* - expanded
* - collapsed
2010-05-01 00:05:04 +00:00
* - value
*
2011-08-10 19:47:50 +00:00
* The following states exist for both elements and remote conditions , but are
* not fully implemented and may not change anything on the element :
2010-05-01 00:05:04 +00:00
* - relevant
* - irrelevant
* - valid
* - invalid
* - touched
* - untouched
* - readwrite
* - readonly
*
* When referencing select lists and radio buttons in remote conditions , a
* 'value' condition must be used :
* @ code
* '#states' => array (
* // Show the settings if 'bar' has been selected for 'foo'.
* 'visible' => array (
* ':input[name="foo"]' => array ( 'value' => 'bar' ),
* ),
* ),
* @ endcode
*
* @ param $elements
* A renderable array element having a #states property as described above.
*
* @ see form_example_states_form ()
2009-10-16 19:20:34 +00:00
*/
function drupal_process_states ( & $elements ) {
2014-03-09 19:59:45 +00:00
$elements [ '#attached' ][ 'library' ][] = 'core/drupal.states' ;
2013-11-05 16:46:25 +00:00
// Elements of '#type' => 'item' are not actual form input elements, but we
// still want to be able to show/hide them. Since there's no actual HTML input
// element available, setting #attributes does not make sense, but a wrapper
// is available, so setting #wrapper_attributes makes it work.
$key = ( $elements [ '#type' ] == 'item' ) ? '#wrapper_attributes' : '#attributes' ;
2016-03-14 00:22:44 +00:00
$elements [ $key ][ 'data-drupal-states' ] = Json :: encode ( $elements [ '#states' ]);
2009-10-16 19:20:34 +00:00
}
2007-11-14 09:50:00 +00:00
/**
2013-12-20 12:05:47 +00:00
* Assists in attaching the tableDrag JavaScript behavior to a themed table .
2007-11-14 09:50:00 +00:00
*
* Draggable tables should be used wherever an outline or list of sortable items
* needs to be arranged by an end - user . Draggable tables are very flexible and
* can manipulate the value of form elements placed within individual columns .
*
2011-12-05 12:52:27 +00:00
* To set up a table to use drag and drop in place of weight select - lists or in
* place of a form that contains parent relationships , the form must be themed
2014-12-11 10:35:52 +00:00
* into a table . The table must have an ID attribute set and it
* may be set as follows :
2007-11-14 09:50:00 +00:00
* @ code
2014-02-18 10:54:10 +00:00
* $table = array (
* '#type' => 'table' ,
* '#header' => $header ,
* '#rows' => $rows ,
* '#attributes' => array (
* 'id' => 'my-module-table' ,
* ),
* );
2018-04-30 16:36:16 +00:00
* return \Drupal :: service ( 'renderer' ) -> render ( $table );
2007-11-14 09:50:00 +00:00
* @ endcode
*
* In the theme function for the form , a special class must be added to each
* form element within the same column , " grouping " them together .
*
* In a situation where a single weight column is being sorted in the table , the
* classes could be added like this ( in the theme function ) :
* @ code
2009-08-22 14:34:23 +00:00
* $form [ 'my_elements' ][ $delta ][ 'weight' ][ '#attributes' ][ 'class' ] = array ( 'my-elements-weight' );
2007-11-14 09:50:00 +00:00
* @ endcode
*
2011-12-05 12:52:27 +00:00
* Each row of the table must also have a class of " draggable " in order to
* enable the drag handles :
2007-11-20 20:13:04 +00:00
* @ code
* $row = array ( ... );
* $rows [] = array (
* 'data' => $row ,
2009-08-22 14:34:23 +00:00
* 'class' => array ( 'draggable' ),
2007-11-20 20:13:04 +00:00
* );
* @ endcode
2007-11-23 13:34:55 +00:00
*
2007-12-19 10:58:35 +00:00
* When tree relationships are present , the two additional classes
* 'tabledrag-leaf' and 'tabledrag-root' can be used to refine the behavior :
* - Rows with the 'tabledrag-leaf' class cannot have child rows .
* - Rows with the 'tabledrag-root' class cannot be nested under a parent row .
*
2013-12-20 12:05:47 +00:00
* Calling drupal_attach_tabledrag () would then be written as such :
2007-11-14 09:50:00 +00:00
* @ code
2013-12-20 12:05:47 +00:00
* drupal_attach_tabledrag ( 'my-module-table' , array (
* 'action' => 'order' ,
* 'relationship' => 'sibling' ,
* 'group' => 'my-elements-weight' ,
* );
2007-11-14 09:50:00 +00:00
* @ endcode
*
* In a more complex case where there are several groups in one column ( such as
2011-12-05 12:52:27 +00:00
* the block regions on the admin / structure / block page ), a separate subgroup
* class must also be added to differentiate the groups .
2007-11-14 09:50:00 +00:00
* @ code
2009-08-22 14:34:23 +00:00
* $form [ 'my_elements' ][ $region ][ $delta ][ 'weight' ][ '#attributes' ][ 'class' ] = array ( 'my-elements-weight' , 'my-elements-weight-' . $region );
2007-11-14 09:50:00 +00:00
* @ endcode
*
2013-12-20 12:05:47 +00:00
* The 'group' option is still 'my-element-weight' , and the additional
* 'subgroup' option will be passed in as 'my-elements-weight-' . $region . This
* also means that you ' ll need to call drupal_attach_tabledrag () once for every
* region added .
2007-11-14 09:50:00 +00:00
*
* @ code
* foreach ( $regions as $region ) {
2013-12-20 12:05:47 +00:00
* drupal_attach_tabledrag ( 'my-module-table' , array (
* 'action' => 'order' ,
2015-07-04 14:19:14 +00:00
* 'relationship' => 'sibling' ,
2013-12-20 12:05:47 +00:00
* 'group' => 'my-elements-weight' ,
2015-07-04 14:19:14 +00:00
* 'subgroup' => 'my-elements-weight-' . $region ,
2013-12-20 12:05:47 +00:00
* ));
2007-11-14 09:50:00 +00:00
* }
* @ endcode
*
* In a situation where tree relationships are present , adding multiple
* subgroups is not necessary , because the table will contain indentations that
2011-12-05 12:52:27 +00:00
* provide enough information about the sibling and parent relationships . See
2014-11-04 15:19:27 +00:00
* MenuForm :: BuildOverviewForm for an example creating a table
* containing parent relationships .
2011-12-05 12:52:27 +00:00
*
2013-12-20 12:05:47 +00:00
* @ param $element
* A form element to attach the tableDrag behavior to .
* @ param array $options
* These options are used to generate JavaScript settings necessary to
* configure the tableDrag behavior appropriately for this particular table .
* An associative array containing the following keys :
* - 'table_id' : String containing the target table ' s id attribute .
* If the table does not have an id , one will need to be set ,
* such as < table id = " my-module-table " >.
* - 'action' : String describing the action to be done on the form item .
* Either 'match' 'depth' , or 'order' :
* - 'match' is typically used for parent relationships .
* - 'order' is typically used to set weights on other form elements with
* the same group .
* - 'depth' updates the target element with the current indentation .
* - 'relationship' : String describing where the " action " option
* should be performed . Either 'parent' , 'sibling' , 'group' , or 'self' :
* - 'parent' will only look for fields up the tree .
* - 'sibling' will look for fields in the same group in rows above and
* below it .
* - 'self' affects the dragged row itself .
* - 'group' affects the dragged row , plus any children below it ( the entire
* dragged group ) .
* - 'group' : A class name applied on all related form elements for this action .
* - 'subgroup' : ( optional ) If the group has several subgroups within it , this
* string should contain the class name identifying fields in the same
* subgroup .
* - 'source' : ( optional ) If the $action is 'match' , this string should contain
* the classname identifying what field will be used as the source value
* when matching the value in $subgroup .
* - 'hidden' : ( optional ) The column containing the field elements may be
* entirely hidden from view dynamically when the JavaScript is loaded . Set
* to FALSE if the column should not be hidden .
* - 'limit' : ( optional ) Limit the maximum amount of parenting in this table .
*
2014-11-04 15:19:27 +00:00
* @ see MenuForm :: BuildOverviewForm ()
2007-11-14 09:50:00 +00:00
*/
2013-12-20 12:05:47 +00:00
function drupal_attach_tabledrag ( & $element , array $options ) {
// Add default values to elements.
2017-03-04 01:20:24 +00:00
$options = $options + [
2013-12-20 12:05:47 +00:00
'subgroup' => NULL ,
'source' => NULL ,
'hidden' => TRUE ,
2018-05-11 09:40:33 +00:00
'limit' => 0 ,
2017-03-04 01:20:24 +00:00
];
2013-01-18 18:00:29 +00:00
2013-12-20 12:05:47 +00:00
$group = $options [ 'group' ];
$tabledrag_id = & drupal_static ( __FUNCTION__ );
$tabledrag_id = ( ! isset ( $tabledrag_id )) ? 0 : $tabledrag_id + 1 ;
2007-11-14 09:50:00 +00:00
// If a subgroup or source isn't set, assume it is the same as the group.
2013-12-20 12:05:47 +00:00
$target = isset ( $options [ 'subgroup' ]) ? $options [ 'subgroup' ] : $group ;
$source = isset ( $options [ 'source' ]) ? $options [ 'source' ] : $target ;
2017-03-04 01:20:24 +00:00
$element [ '#attached' ][ 'drupalSettings' ][ 'tableDrag' ][ $options [ 'table_id' ]][ $group ][ $tabledrag_id ] = [
2007-11-14 09:50:00 +00:00
'target' => $target ,
'source' => $source ,
2013-12-20 12:05:47 +00:00
'relationship' => $options [ 'relationship' ],
'action' => $options [ 'action' ],
'hidden' => $options [ 'hidden' ],
'limit' => $options [ 'limit' ],
2017-03-04 01:20:24 +00:00
];
2013-12-20 12:05:47 +00:00
2014-03-09 19:59:45 +00:00
$element [ '#attached' ][ 'library' ][] = 'core/drupal.tabledrag' ;
2007-11-14 09:50:00 +00:00
}
2007-06-01 09:05:45 +00:00
/**
2010-05-09 19:44:25 +00:00
* Deletes old cached JavaScript files and variables .
2014-08-08 16:52:12 +00:00
*
* @ deprecated in Drupal 8. x , will be removed before Drupal 9.0 .
* Use \Drupal\Core\Asset\AssetCollectionOptimizerInterface :: deleteAll () .
2017-11-13 15:35:45 +00:00
*
* @ see https :// www . drupal . org / node / 2317841
2007-06-01 09:05:45 +00:00
*/
function drupal_clear_js_cache () {
2014-08-08 16:52:12 +00:00
\Drupal :: service ( 'asset.js.collection_optimizer' ) -> deleteAll ();
2007-06-01 09:05:45 +00:00
}
2009-11-03 05:27:18 +00:00
/**
2011-12-05 12:52:27 +00:00
* Pre - render callback : Renders a link into #markup.
2009-11-03 05:27:18 +00:00
*
2015-05-04 21:01:22 +00:00
* @ deprecated in Drupal 8. x , will be removed before Drupal 9.0 .
* Use \Drupal\Core\Render\Element\Link :: preRenderLink () .
2009-11-03 05:27:18 +00:00
*/
2010-10-21 19:31:39 +00:00
function drupal_pre_render_link ( $element ) {
2016-04-30 14:11:15 +00:00
return Link :: preRenderLink ( $element );
2009-11-03 05:27:18 +00:00
}
2010-11-14 21:04:45 +00:00
/**
2011-12-05 12:52:27 +00:00
* Pre - render callback : Collects child links into a single array .
2010-11-14 21:04:45 +00:00
*
* This function can be added as a pre_render callback for a renderable array ,
2014-02-07 04:28:14 +00:00
* usually one which will be themed by links . html . twig . It iterates through all
2010-11-14 21:04:45 +00:00
* unrendered children of the element , collects any #links properties it finds,
* merges them into the parent element ' s #links array, and prevents those
* children from being rendered separately .
*
* The purpose of this is to allow links to be logically grouped into related
* categories , so that each child group can be rendered as its own list of
* links if drupal_render () is called on it , but calling drupal_render () on the
* parent element will still produce a single list containing all the remaining
* links , regardless of what group they were in .
*
* A typical example comes from node links , which are stored in a renderable
* array similar to this :
* @ code
2014-05-02 21:43:59 +00:00
* $build [ 'links' ] = array (
2010-11-14 21:04:45 +00:00
* '#theme' => 'links__node' ,
2013-01-22 00:20:08 +00:00
* '#pre_render' => array ( 'drupal_pre_render_links' ),
2010-11-14 21:04:45 +00:00
* 'comment' => array (
* '#theme' => 'links__node__comment' ,
* '#links' => array (
* // An array of links associated with node comments, suitable for
2014-02-07 04:28:14 +00:00
* // passing in to links.html.twig.
2010-11-14 21:04:45 +00:00
* ),
* ),
* 'statistics' => array (
* '#theme' => 'links__node__statistics' ,
* '#links' => array (
* // An array of links associated with node statistics, suitable for
2014-02-07 04:28:14 +00:00
* // passing in to links.html.twig.
2010-11-14 21:04:45 +00:00
* ),
* ),
* 'translation' => array (
* '#theme' => 'links__node__translation' ,
* '#links' => array (
* // An array of links associated with node translation, suitable for
2014-02-07 04:28:14 +00:00
* // passing in to links.html.twig.
2010-11-14 21:04:45 +00:00
* ),
* ),
* );
* @ endcode
*
* In this example , the links are grouped by functionality , which can be
* helpful to themers who want to display certain kinds of links independently .
Issue #1898432 by WebDevDude, steveoliver, vlad.dancer, jenlampton, pixelmord, Fabianx, iztok, EVIIILJ, jwilson3, c4rl, Cottser: Convert node module to Twig.
2013-05-24 17:13:55 +00:00
* For example , adding this code to node . html . twig will result in the comment
2010-11-14 21:04:45 +00:00
* links being rendered as a single list :
* @ code
2013-07-15 22:28:09 +00:00
* {{ content . links . comment }}
2010-11-14 21:04:45 +00:00
* @ endcode
*
2014-05-02 21:43:59 +00:00
* ( where a node ' s content has been transformed into $content before handing
Issue #1898432 by WebDevDude, steveoliver, vlad.dancer, jenlampton, pixelmord, Fabianx, iztok, EVIIILJ, jwilson3, c4rl, Cottser: Convert node module to Twig.
2013-05-24 17:13:55 +00:00
* control to the node . html . twig template ) .
2010-11-14 21:04:45 +00:00
*
* The pre_render function defined here allows the above flexibility , but also
* allows the following code to be used to render all remaining links into a
* single list , regardless of their group :
* @ code
2013-07-15 22:28:09 +00:00
* {{ content . links }}
2010-11-14 21:04:45 +00:00
* @ endcode
*
* In the above example , this will result in the statistics and translation
* links being rendered together in a single list ( but not the comment links ,
* which were rendered previously on their own ) .
*
* Because of the way this function works , the individual properties of each
* group ( for example , a group - specific #theme property such as
* 'links__node__comment' in the example above , or any other property such as
* #attributes or #pre_render that is attached to it) are only used when that
* group is rendered on its own . When the group is rendered together with other
* children , these child - specific properties are ignored , and only the overall
* properties of the parent are used .
*/
function drupal_pre_render_links ( $element ) {
2017-03-04 01:20:24 +00:00
$element += [ '#links' => [], '#attached' => []];
2014-03-31 17:37:55 +00:00
foreach ( Element :: children ( $element ) as $key ) {
2010-11-14 21:04:45 +00:00
$child = & $element [ $key ];
// If the child has links which have not been printed yet and the user has
// access to it, merge its links in to the parent.
2015-06-30 15:05:14 +00:00
if ( isset ( $child [ '#links' ]) && empty ( $child [ '#printed' ]) && Element :: isVisibleElement ( $child )) {
2010-11-14 21:04:45 +00:00
$element [ '#links' ] += $child [ '#links' ];
// Mark the child as having been printed already (so that its links
// cannot be mistakenly rendered twice).
$child [ '#printed' ] = TRUE ;
}
2013-10-24 15:43:00 +00:00
// Merge attachments.
if ( isset ( $child [ '#attached' ])) {
2015-09-09 13:28:29 +00:00
$element [ '#attached' ] = BubbleableMetadata :: mergeAttachments ( $element [ '#attached' ], $child [ '#attached' ]);
2013-10-24 15:43:00 +00:00
}
2010-11-14 21:04:45 +00:00
}
return $element ;
}
2014-10-24 14:51:28 +00:00
/**
* Renders final HTML given a structured array tree .
*
2014-11-21 09:48:25 +00:00
* @ deprecated as of Drupal 8.0 . x , will be removed before Drupal 9.0 . 0. Use the
* 'renderer' service instead .
2014-10-24 14:51:28 +00:00
*
2014-11-21 09:48:25 +00:00
* @ see \Drupal\Core\Render\RendererInterface :: renderRoot ()
2017-11-13 15:56:42 +00:00
* @ see https :// www . drupal . org / node / 2912696
2014-10-24 14:51:28 +00:00
*/
function drupal_render_root ( & $elements ) {
2014-11-21 09:48:25 +00:00
return \Drupal :: service ( 'renderer' ) -> renderRoot ( $elements );
2014-10-24 14:51:28 +00:00
}
2006-08-10 15:42:33 +00:00
/**
2007-10-08 14:08:19 +00:00
* Renders HTML given a structured array tree .
*
2014-11-21 09:48:25 +00:00
* @ deprecated as of Drupal 8.0 . x , will be removed before Drupal 9.0 . 0. Use the
* 'renderer' service instead .
2006-08-10 15:42:33 +00:00
*
2014-11-21 09:48:25 +00:00
* @ see \Drupal\Core\Render\RendererInterface :: render ()
2017-11-13 15:56:42 +00:00
* @ see https :// www . drupal . org / node / 2912696
2014-11-21 09:48:25 +00:00
*/
function drupal_render ( & $elements , $is_recursive_call = FALSE ) {
return \Drupal :: service ( 'renderer' ) -> render ( $elements , $is_recursive_call );
2009-02-03 18:55:32 +00:00
}
/**
2011-12-05 12:52:27 +00:00
* Renders children of an element and concatenates them .
2009-02-03 18:55:32 +00:00
*
2014-01-14 07:05:39 +00:00
* @ param array $element
2009-02-03 18:55:32 +00:00
* The structured array whose children shall be rendered .
2014-01-14 07:05:39 +00:00
* @ param array $children_keys
* ( optional ) If the keys of the element ' s children are already known , they
2014-03-31 17:37:55 +00:00
* can be passed in to save another run of
* \Drupal\Core\Render\Element :: children () .
2014-01-14 07:05:39 +00:00
*
2015-10-01 23:25:03 +00:00
* @ return string | \Drupal\Component\Render\MarkupInterface
2014-01-14 07:05:39 +00:00
* The rendered HTML of all children of the element .
2015-08-06 11:51:08 +00:00
*
2015-10-23 19:36:20 +00:00
* @ deprecated in Drupal 8.0 . x and will be removed before 9.0 . 0. Avoid early
* rendering when possible or loop through the elements and render them as
* they are available .
*
Issue #2938970 by MerryHamster, surbz, msankhala, alexpott, Jo Fitzgerald, Yasiru Nilan, Manuel Garcia, ZeiP, boaloysius, xjm, wturrell, tameeshb, darrenwh, ritzz: Replace drupal_render() in @param, @return, @see, @link, etc
2018-05-03 16:58:24 +00:00
* @ see \Drupal\Core\Render\RendererInterface :: render ()
2017-11-05 11:46:03 +00:00
* @ see https :// www . drupal . org / node / 2912757
2009-02-03 18:55:32 +00:00
*/
2009-02-05 01:21:16 +00:00
function drupal_render_children ( & $element , $children_keys = NULL ) {
2009-02-03 18:55:32 +00:00
if ( $children_keys === NULL ) {
2014-03-31 17:37:55 +00:00
$children_keys = Element :: children ( $element );
2009-02-03 18:55:32 +00:00
}
$output = '' ;
foreach ( $children_keys as $key ) {
2009-11-16 05:11:01 +00:00
if ( ! empty ( $element [ $key ])) {
Issue #2704871 by pepegarciag, Mile23, Manuel Garcia, ieguskiza, snehi, gaurav.pahuja, dimaro, rajeshwari10, gargsuchi, pashupathi nath gajawada, penyaskito, xjm, ZeiP, Wim Leers, alexpott: Replace usages of deprecated method drupal_render()
2017-07-03 15:35:13 +00:00
$output .= \Drupal :: service ( 'renderer' ) -> render ( $element [ $key ]);
2009-11-16 05:11:01 +00:00
}
2009-02-03 18:55:32 +00:00
}
2015-10-01 23:25:03 +00:00
return Markup :: create ( $output );
2006-08-10 15:42:33 +00:00
}
2009-06-18 21:19:02 +00:00
/**
2011-12-05 12:52:27 +00:00
* Renders an element .
2009-06-18 21:19:02 +00:00
*
2015-04-15 16:56:41 +00:00
* This function renders an element . The top level element is shown with show ()
* before rendering , so it will always be rendered even if hide () had been
* previously used on it .
2009-06-18 21:19:02 +00:00
*
2011-01-12 23:15:26 +00:00
* @ param $element
* The element to be rendered .
*
* @ return
* The rendered element .
2009-06-18 21:19:02 +00:00
*
2015-04-15 16:56:41 +00:00
* @ see \Drupal\Core\Render\RendererInterface
2009-06-18 21:19:02 +00:00
* @ see show ()
* @ see hide ()
*/
function render ( & $element ) {
2012-11-03 17:36:10 +00:00
if ( ! $element && $element !== 0 ) {
return NULL ;
}
2009-06-18 21:19:02 +00:00
if ( is_array ( $element )) {
2014-05-02 21:43:59 +00:00
// Early return if this element was pre-rendered (no need to re-render).
if ( isset ( $element [ '#printed' ]) && $element [ '#printed' ] == TRUE && isset ( $element [ '#markup' ]) && strlen ( $element [ '#markup' ]) > 0 ) {
return $element [ '#markup' ];
}
2009-06-18 21:19:02 +00:00
show ( $element );
2015-04-15 16:56:41 +00:00
return \Drupal :: service ( 'renderer' ) -> render ( $element );
2009-06-18 21:19:02 +00:00
}
else {
2009-07-13 21:09:54 +00:00
// Safe-guard for inappropriate use of render() on flat variables: return
// the variable as-is.
return $element ;
2009-06-18 21:19:02 +00:00
}
}
/**
2011-12-05 12:52:27 +00:00
* Hides an element from later rendering .
2009-06-18 21:19:02 +00:00
*
2011-01-12 23:15:26 +00:00
* The first time render () or drupal_render () is called on an element tree ,
* as each element in the tree is rendered , it is marked with a #printed flag
* and the rendered children of the element are cached . Subsequent calls to
* render () or drupal_render () will not traverse the child tree of this element
* again : they will just use the cached children . So if you want to hide an
* element , be sure to call hide () on the element before its parent tree is
* rendered for the first time , as it will have no effect on subsequent
* renderings of the parent tree .
*
* @ param $element
* The element to be hidden .
*
* @ return
* The element .
*
2009-06-18 21:19:02 +00:00
* @ see render ()
* @ see show ()
*/
function hide ( & $element ) {
$element [ '#printed' ] = TRUE ;
return $element ;
}
/**
2011-12-05 12:52:27 +00:00
* Shows a hidden element for later rendering .
2011-01-12 23:15:26 +00:00
*
* You can also use render ( $element ), which shows the element while rendering
* it .
*
* The first time render () or drupal_render () is called on an element tree ,
* as each element in the tree is rendered , it is marked with a #printed flag
* and the rendered children of the element are cached . Subsequent calls to
* render () or drupal_render () will not traverse the child tree of this element
* again : they will just use the cached children . So if you want to show an
* element , be sure to call show () on the element before its parent tree is
* rendered for the first time , as it will have no effect on subsequent
* renderings of the parent tree .
2009-06-18 21:19:02 +00:00
*
2011-01-12 23:15:26 +00:00
* @ param $element
* The element to be shown .
*
* @ return
* The element .
2009-06-18 21:19:02 +00:00
*
* @ see render ()
* @ see hide ()
*/
function show ( & $element ) {
$element [ '#printed' ] = FALSE ;
return $element ;
}
2009-02-03 18:55:32 +00:00
/**
2011-12-05 12:52:27 +00:00
* Retrieves the default properties for the defined element type .
2010-11-12 02:59:30 +00:00
*
* @ param $type
2015-08-28 21:29:41 +00:00
* An element type as defined by an element plugin .
2014-04-25 22:14:29 +00:00
*
2015-04-09 14:52:29 +00:00
* @ deprecated in Drupal 8.0 . 0 , will be removed before Drupal 9.0 . 0.
* Use \Drupal :: service ( 'element_info' ) -> getInfo () instead .
Issue #2920018 by sergiuteaca, billywardrop, anyaabchiche, Janec, JO0st, davemckain, dinarcon, sthomps5, mairi, jyraya, kwhite: Add Change record to @deprecated for element_info service
2017-11-03 21:29:30 +00:00
*
* @ see https :// www . drupal . org / node / 2235461
2009-02-03 18:55:32 +00:00
*/
2009-05-31 07:00:12 +00:00
function element_info ( $type ) {
2014-04-25 22:14:29 +00:00
return \Drupal :: service ( 'element_info' ) -> getInfo ( $type );
2009-02-03 18:55:32 +00:00
}
2010-11-12 02:59:30 +00:00
/**
2011-12-05 12:52:27 +00:00
* Retrieves a single property for the defined element type .
2010-11-12 02:59:30 +00:00
*
* @ param $type
2015-08-28 21:29:41 +00:00
* An element type as defined by an element plugin .
2010-11-12 02:59:30 +00:00
* @ param $property_name
* The property within the element type that should be returned .
* @ param $default
* ( Optional ) The value to return if the element type does not specify a
* value for the property . Defaults to NULL .
2015-04-09 14:52:29 +00:00
*
* @ deprecated in Drupal 8.0 . 0 , will be removed before Drupal 9.0 . 0.
* Use \Drupal :: service ( 'element_info' ) -> getInfoProperty () instead .
Issue #2920018 by sergiuteaca, billywardrop, anyaabchiche, Janec, JO0st, davemckain, dinarcon, sthomps5, mairi, jyraya, kwhite: Add Change record to @deprecated for element_info service
2017-11-03 21:29:30 +00:00
*
* @ see https :// www . drupal . org / node / 2235461
2010-11-12 02:59:30 +00:00
*/
function element_info_property ( $type , $property_name , $default = NULL ) {
2015-04-09 14:52:29 +00:00
return \Drupal :: service ( 'element_info' ) -> getInfoProperty ( $type , $property_name , $default );
2010-11-12 02:59:30 +00:00
}
2007-11-26 16:25:14 +00:00
/**
2012-05-03 15:09:39 +00:00
* Flushes all persistent caches , resets all variables , and rebuilds all data structures .
*
* At times , it is necessary to re - initialize the entire system to account for
* changed or new code . This function :
2013-03-22 09:36:55 +00:00
* - Clears all persistent caches :
2012-05-03 15:09:39 +00:00
* - The bootstrap cache bin containing base system , module system , and theme
* system information .
2014-03-31 09:49:28 +00:00
* - The common 'default' cache bin containing arbitrary caches .
2012-05-03 15:09:39 +00:00
* - The page cache .
* - The URL alias path cache .
* - Resets all static variables that have been defined via drupal_static () .
* - Clears asset ( JS / CSS ) file caches .
* - Updates the system with latest information about extensions ( modules and
* themes ) .
* - Updates the bootstrap flag for modules implementing bootstrap_hooks () .
* - Rebuilds the full database schema information ( invoking hook_schema ()) .
* - Rebuilds data structures of all modules ( invoking hook_rebuild ()) . In
* core this means
* - blocks , node types , date formats and actions are synchronized with the
* database
* - The 'active' status of fields is refreshed .
* - Rebuilds the menu router .
*
* This means the entire system is reset so all caches and static variables are
* effectively empty . After that is guaranteed , information about the currently
* active code is updated , and rebuild operations are successively called in
* order to synchronize the active system according to the current information
* defined in code .
*
* All modules need to ensure that all of their caches are flushed when
* hook_cache_flush () is invoked ; any previously known information must no
* longer exist . All following hook_rebuild () operations must be based on fresh
* and current system data . All modules must be able to rely on this contract .
*
2013-03-22 09:36:55 +00:00
* @ see \Drupal\Core\Cache\CacheHelper :: getBins ()
2012-05-03 15:09:39 +00:00
* @ see hook_cache_flush ()
* @ see hook_rebuild ()
*
* This function also resets the theme , which means it is not initialized
* anymore and all previously added JavaScript and CSS is gone . Normally , this
* function is called as an end - of - POST - request operation that is followed by a
* redirect , so this effect is not visible . Since the full reset is the whole
* point of this function , callers need to take care for backing up all needed
* variables and properly restoring or re - initializing them on their own . For
* convenience , this function automatically re - initializes the maintenance theme
* if it was initialized before .
*
* @ todo Try to clear page / JS / CSS caches last , so cached pages can still be
* served during this possibly long - running operation . ( Conflict on bootstrap
* cache though . )
* @ todo Add a global lock to ensure that caches are not primed in concurrent
* requests .
2007-11-26 16:25:14 +00:00
*/
function drupal_flush_all_caches () {
2013-09-16 03:58:06 +00:00
$module_handler = \Drupal :: moduleHandler ();
2012-05-03 15:09:39 +00:00
// Flush all persistent caches.
// This is executed based on old/previously known information, which is
// sufficient, since new extensions cannot have any primed caches yet.
2013-05-19 19:32:09 +00:00
$module_handler -> invokeAll ( 'cache_flush' );
2013-03-22 09:36:55 +00:00
foreach ( Cache :: getBins () as $service_id => $cache_backend ) {
2014-03-26 13:19:28 +00:00
$cache_backend -> deleteAll ();
2012-05-03 15:09:39 +00:00
}
2008-01-07 19:43:29 +00:00
2012-05-03 15:09:39 +00:00
// Flush asset file caches.
2014-08-08 16:52:12 +00:00
\Drupal :: service ( 'asset.css.collection_optimizer' ) -> deleteAll ();
\Drupal :: service ( 'asset.js.collection_optimizer' ) -> deleteAll ();
2012-05-03 15:09:39 +00:00
_drupal_flush_css_js ();
2010-04-29 05:33:43 +00:00
2012-05-03 15:09:39 +00:00
// Reset all static caches.
drupal_static_reset ();
2012-01-18 04:02:34 +00:00
2015-07-07 16:35:44 +00:00
// Invalidate the container.
\Drupal :: service ( 'kernel' ) -> invalidateContainer ();
// Wipe the Twig PHP Storage cache.
Issue #2752961 by dawehner, Wim Leers, Jo Fitzgerald, chr.fritsch, bradjones1, anavarre, greg.1.anderson, Berdir, moshe weitzman, alexpott, bkosborne, Crell, msonnabaum, joelpittet, catch, deviantintegral, lauriii, cilefen, effulgentsia, xjm: No reliable method exists for clearing the Twig cache
2018-05-05 00:28:31 +00:00
\Drupal :: service ( 'twig' ) -> invalidate ();
2013-05-19 19:32:09 +00:00
2012-08-31 10:03:05 +00:00
// Rebuild module and theme data.
2013-05-19 19:32:09 +00:00
$module_data = system_rebuild_module_data ();
2014-09-05 10:11:16 +00:00
/** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
$theme_handler = \Drupal :: service ( 'theme_handler' );
$theme_handler -> refreshInfo ();
// In case the active theme gets requested later in the same request we need
// to reset the theme manager.
\Drupal :: theme () -> resetActiveTheme ();
2013-05-19 19:32:09 +00:00
// Rebuild and reboot a new kernel. A simple DrupalKernel reboot is not
// sufficient, since the list of enabled modules might have been adjusted
// above due to changed code.
2017-03-04 01:20:24 +00:00
$files = [];
Issue #340723 by ParisLiakos, sun, Berdir, glennpratt, Cottser, swentel, alexpott, tstoeckler, Xano, tim.plunkett, BassistJimmyJam | beejeebus: Make modules and installation profiles only require .info.yml files.
2014-03-17 14:43:29 +00:00
foreach ( $module_data as $name => $extension ) {
if ( $extension -> status ) {
$files [ $name ] = $extension ;
2013-05-19 19:32:09 +00:00
}
}
2013-09-16 03:58:06 +00:00
\Drupal :: service ( 'kernel' ) -> updateModules ( $module_handler -> getModuleList (), $files );
2013-05-19 19:32:09 +00:00
// New container, new module handler.
2013-09-16 03:58:06 +00:00
$module_handler = \Drupal :: moduleHandler ();
2013-05-19 19:32:09 +00:00
2012-05-03 15:09:39 +00:00
// Ensure that all modules that are currently supposed to be enabled are
// actually loaded.
2013-05-19 19:32:09 +00:00
$module_handler -> loadAll ();
2010-07-29 02:00:27 +00:00
2012-05-03 15:09:39 +00:00
// Rebuild all information based on new module data.
2013-05-19 19:32:09 +00:00
$module_handler -> invokeAll ( 'rebuild' );
2012-05-03 15:09:39 +00:00
2014-10-05 09:31:26 +00:00
// Clear all plugin caches.
\Drupal :: service ( 'plugin.cache_clearer' ) -> clearCachedDefinitions ();
2012-05-03 15:09:39 +00:00
// Rebuild the menu router based on all rebuilt data.
// Important: This rebuild must happen last, so the menu router is guaranteed
// to be based on up to date information.
2013-09-16 03:58:06 +00:00
\Drupal :: service ( 'router.builder' ) -> rebuild ();
2012-05-03 15:09:39 +00:00
// Re-initialize the maintenance theme, if the current request attempted to
// use it. Unlike regular usages of this function, the installer and update
// scripts need to flush all caches during GET requests/page building.
if ( function_exists ( '_drupal_maintenance_theme' )) {
2014-08-21 16:53:03 +00:00
\Drupal :: theme () -> resetActiveTheme ();
2012-05-03 15:09:39 +00:00
drupal_maintenance_theme ();
}
2007-11-26 16:25:14 +00:00
}
2008-01-07 19:43:29 +00:00
/**
2011-12-05 12:52:27 +00:00
* Changes the dummy query string added to all CSS and JavaScript files .
2008-01-07 19:43:29 +00:00
*
2011-12-05 12:52:27 +00:00
* Changing the dummy query string appended to CSS and JavaScript files forces
* all browsers to reload fresh files .
2008-01-07 19:43:29 +00:00
*/
function _drupal_flush_css_js () {
2010-03-23 21:44:10 +00:00
// The timestamp is converted to base 36 in order to make it more compact.
2013-09-27 12:20:32 +00:00
Drupal :: state () -> set ( 'system.css_js_query_string' , base_convert ( REQUEST_TIME , 10 , 36 ));
2008-01-07 19:43:29 +00:00
}
2009-08-13 03:03:04 +00:00
2009-08-15 06:20:20 +00:00
/**
2011-12-05 12:52:27 +00:00
* Outputs debug information .
2009-08-15 06:20:20 +00:00
*
* The debug information is passed on to trigger_error () after being converted
* to a string using _drupal_debug_message () .
*
* @ param $data
* Data to be output .
* @ param $label
* Label to prefix the data .
* @ param $print_r
* Flag to switch between print_r () and var_export () for data conversion to
2015-02-18 11:45:45 +00:00
* string . Set $print_r to FALSE to use var_export () instead of print_r () .
* Passing recursive data structures to var_export () will generate an error .
2009-08-15 06:20:20 +00:00
*/
2015-02-18 11:45:45 +00:00
function debug ( $data , $label = NULL , $print_r = TRUE ) {
2009-08-15 06:20:20 +00:00
// Print $data contents to string.
2015-08-26 10:34:29 +00:00
$string = Html :: escape ( $print_r ? print_r ( $data , TRUE ) : var_export ( $data , TRUE ));
2010-10-16 00:00:17 +00:00
// Display values with pre-formatting to increase readability.
$string = '<pre>' . $string . '</pre>' ;
2009-08-15 06:20:20 +00:00
trigger_error ( trim ( $label ? " $label : $string " : $string ));
}
2009-08-13 03:03:04 +00:00
/**
2011-12-05 12:52:27 +00:00
* Checks whether a version is compatible with a given dependency .
2009-08-13 03:03:04 +00:00
*
* @ param $v
2013-01-21 19:21:34 +00:00
* A parsed dependency structure e . g . from ModuleHandler :: parseDependency () .
2009-08-13 03:03:04 +00:00
* @ param $current_version
* The version to check against ( like 4.2 ) .
2011-12-05 12:52:27 +00:00
*
2009-08-13 03:03:04 +00:00
* @ return
* NULL if compatible , otherwise the original dependency version string that
2010-01-25 10:38:35 +00:00
* caused the incompatibility .
2009-08-13 03:03:04 +00:00
*
Issue #2677532 by alexpott, Mile23, kim.pepper, dawehner, andypost, Eric_A, xjm, Mixologic, larowlan, phenaproxima, markcarver, borisson_: Move drupal_check_incompatibility() functionality to a new Dependency class and Version component
2018-10-22 05:21:49 +00:00
* @ deprecated in Drupal 8.7 . 0 and will be removed before Drupal 9.0 . 0. Use
* \Drupal\Core\Extension\Dependency :: isCompatible () instead .
*
* @ see https :// www . drupal . org / node / 2756875
2009-08-13 03:03:04 +00:00
*/
function drupal_check_incompatibility ( $v , $current_version ) {
Issue #2677532 by alexpott, Mile23, kim.pepper, dawehner, andypost, Eric_A, xjm, Mixologic, larowlan, phenaproxima, markcarver, borisson_: Move drupal_check_incompatibility() functionality to a new Dependency class and Version component
2018-10-22 05:21:49 +00:00
@ trigger_error ( __FUNCTION__ . '() is deprecated. Use \Drupal\Core\Extension\Dependency::isCompatible() instead. See https://www.drupal.org/node/2756875' , E_USER_DEPRECATED );
2009-08-13 03:03:04 +00:00
if ( ! empty ( $v [ 'versions' ])) {
foreach ( $v [ 'versions' ] as $required_version ) {
if (( isset ( $required_version [ 'op' ]) && ! version_compare ( $current_version , $required_version [ 'version' ], $required_version [ 'op' ]))) {
return $v [ 'original_version' ];
}
}
}
}
2009-08-25 21:53:48 +00:00
2010-07-29 02:27:43 +00:00
/**
* Returns a string of supported archive extensions .
*
* @ return
* A space - separated string of extensions suitable for use by the file
* validation system .
*/
function archiver_get_extensions () {
2017-03-04 01:20:24 +00:00
$valid_extensions = [];
2013-09-16 03:58:06 +00:00
foreach ( \Drupal :: service ( 'plugin.manager.archiver' ) -> getDefinitions () as $archive ) {
2010-07-29 02:27:43 +00:00
foreach ( $archive [ 'extensions' ] as $extension ) {
foreach ( explode ( '.' , $extension ) as $part ) {
if ( ! in_array ( $part , $valid_extensions )) {
$valid_extensions [] = $part ;
}
}
}
}
return implode ( ' ' , $valid_extensions );
}
2009-10-15 17:55:55 +00:00
/**
2011-12-05 12:52:27 +00:00
* Creates the appropriate archiver for the specified file .
2009-10-15 17:55:55 +00:00
*
* @ param $file
2011-12-05 12:52:27 +00:00
* The full path of the archive file . Note that stream wrapper paths are
* supported , but not remote ones .
*
2009-10-15 17:55:55 +00:00
* @ return
* A newly created instance of the archiver class appropriate
* for the specified file , already bound to that file .
2009-10-23 00:55:59 +00:00
* If no appropriate archiver class was found , will return FALSE .
2009-10-15 17:55:55 +00:00
*/
function archiver_get_archiver ( $file ) {
2009-10-23 00:55:59 +00:00
// Archivers can only work on local paths
2017-11-14 15:53:29 +00:00
$filepath = \Drupal :: service ( 'file_system' ) -> realpath ( $file );
2009-10-23 00:55:59 +00:00
if ( ! is_file ( $filepath )) {
2017-03-04 01:20:24 +00:00
throw new Exception ( t ( 'Archivers can only operate on local files: %file not supported' , [ '%file' => $file ]));
2009-10-23 00:55:59 +00:00
}
2017-03-04 01:20:24 +00:00
return \Drupal :: service ( 'plugin.manager.archiver' ) -> getInstance ([ 'filepath' => $filepath ]);
2009-10-15 17:55:55 +00:00
}
2009-10-15 21:19:31 +00:00
/**
2011-12-05 12:52:27 +00:00
* Assembles the Drupal Updater registry .
2009-10-15 21:19:31 +00:00
*
* An Updater is a class that knows how to update various parts of the Drupal
* file system , for example to update modules that have newer releases , or to
* install a new theme .
*
2012-03-11 00:23:05 +00:00
* @ return array
2011-12-05 12:52:27 +00:00
* The Drupal Updater class registry .
2009-10-15 21:19:31 +00:00
*
2013-10-03 11:26:25 +00:00
* @ see \Drupal\Core\Updater\Updater
2009-10-15 21:19:31 +00:00
* @ see hook_updater_info ()
* @ see hook_updater_info_alter ()
*/
function drupal_get_updaters () {
$updaters = & drupal_static ( __FUNCTION__ );
if ( ! isset ( $updaters )) {
2013-09-16 03:58:06 +00:00
$updaters = \Drupal :: moduleHandler () -> invokeAll ( 'updater_info' );
2014-02-24 10:10:52 +00:00
\Drupal :: moduleHandler () -> alter ( 'updater_info' , $updaters );
2017-03-04 01:20:24 +00:00
uasort ( $updaters , [ SortArray :: class , 'sortByWeightElement' ]);
2009-10-15 21:19:31 +00:00
}
return $updaters ;
}
2010-12-01 00:23:36 +00:00
/**
2011-12-05 12:52:27 +00:00
* Assembles the Drupal FileTransfer registry .
2010-12-01 00:23:36 +00:00
*
* @ return
2011-12-05 12:52:27 +00:00
* The Drupal FileTransfer class registry .
2010-12-01 00:23:36 +00:00
*
2013-10-03 11:26:25 +00:00
* @ see \Drupal\Core\FileTransfer\FileTransfer
2010-12-01 00:23:36 +00:00
* @ see hook_filetransfer_info ()
* @ see hook_filetransfer_info_alter ()
*/
function drupal_get_filetransfer_info () {
$info = & drupal_static ( __FUNCTION__ );
if ( ! isset ( $info )) {
2013-09-16 03:58:06 +00:00
$info = \Drupal :: moduleHandler () -> invokeAll ( 'filetransfer_info' );
2014-02-24 10:10:52 +00:00
\Drupal :: moduleHandler () -> alter ( 'filetransfer_info' , $info );
2017-03-04 01:20:24 +00:00
uasort ( $info , [ SortArray :: class , 'sortByWeightElement' ]);
2010-12-01 00:23:36 +00:00
}
return $info ;
}