Newer
Older

catch
committed
use Drupal\Component\Utility\Json;

catch
committed
use Drupal\Component\Utility\Number;

Dries Buytaert
committed
use Drupal\Component\Utility\Settings;
use Drupal\Component\Utility\SortArray;
use Drupal\Component\Utility\String;
use Drupal\Component\Utility\Tags;
use Drupal\Component\Utility\Url;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Language\Language;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

Angie Byron
committed
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Exception\ParseException;

catch
committed
use Drupal\Component\PhpStorage\PhpStorageFactory;
use Drupal\Component\Utility\MapArray;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Routing\GeneratorNotInitializedException;

catch
committed
use Drupal\Core\SystemListingInfo;

Dries Buytaert
committed
use Drupal\Core\Template\Attribute;
use Drupal\Core\Render\Element;

Larry Garfield
committed
/**
* @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.
*/

Dries Buytaert
committed
/**
* @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
* $my_substring = drupal_substr($original_string, 0, 5);
* @endcode
*
* @}

Dries Buytaert
committed
*/

Steven Wittens
committed
/**
* Return status for saving which involved creating a new item.
*/
const SAVED_NEW = 1;

Steven Wittens
committed
/**
* Return status for saving which involved an update to an existing item.
*/
const SAVED_UPDATED = 2;

Steven Wittens
committed
/**
* Return status for saving which deleted an existing item.
*/
const SAVED_DELETED = 3;

Steven Wittens
committed

Dries Buytaert
committed
/**

Angie Byron
committed
* The default aggregation group for CSS files added to the page.

Dries Buytaert
committed
*/

Angie Byron
committed
const CSS_AGGREGATE_DEFAULT = 0;

Dries Buytaert
committed
/**

Angie Byron
committed
* The default aggregation group for theme CSS files added to the page.

Dries Buytaert
committed
*/

Angie Byron
committed
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;
/**
* The default weight for CSS rules that style design components (and their associated states and skins.)
*/
const CSS_COMPONENT = 0;
/**
* The default weight for CSS rules that style states and are not included with components.
*/
const CSS_STATE = 100;
/**
* The default weight for CSS rules that style skins and are not included with components.
*/
const CSS_SKIN = 200;

Dries Buytaert
committed
/**
* The default group for JavaScript settings added to the page.
*/
const JS_SETTING = -200;

Angie Byron
committed
/**

catch
committed
* The default group for JavaScript and jQuery libraries added to the page.

Angie Byron
committed
*/
const JS_LIBRARY = -100;

Angie Byron
committed
/**

Dries Buytaert
committed
* The default group for module JavaScript code added to the page.

Angie Byron
committed
*/
const JS_DEFAULT = 0;

Angie Byron
committed
/**

Dries Buytaert
committed
* The default group for theme JavaScript code added to the page.

Angie Byron
committed
*/
const JS_THEME = 100;

Angie Byron
committed
/**

Jennifer Hodgdon
committed
* @defgroup block_caching Block Caching
* @{
* Constants that define each block's caching state.
*
* Modules specify how their blocks can be cached in their hook_block_info()
* implementations. Caching can be turned off (DRUPAL_NO_CACHE), managed by the
* module declaring the block (DRUPAL_CACHE_CUSTOM), or managed by the core
* Block module. If the Block module is managing the cache, you can specify that
* the block is the same for every page and user (DRUPAL_CACHE_GLOBAL), or that
* it can change depending on the page (DRUPAL_CACHE_PER_PAGE) or by user
* (DRUPAL_CACHE_PER_ROLE or DRUPAL_CACHE_PER_USER). Page and user settings can
* be combined with a bitwise-binary or operator; for example,
* DRUPAL_CACHE_PER_ROLE | DRUPAL_CACHE_PER_PAGE means that the block can change
* depending on the user role or page it is on.
*
* The block cache is cleared when the 'content' cache tag is invalidated,
* following the same pattern as the page cache (node, comment, user, taxonomy
* added or updated...).
*
* Note that user 1 is excluded from block caching.
*/
/**

catch
committed
* The block should not get cached.
*
* This setting should be used:
* - For simple blocks (notably those that do not perform any db query), where
* querying the db cache would be more expensive than directly generating the
* content.
* - For blocks that change too frequently.
*/
const DRUPAL_NO_CACHE = -1;
/**

catch
committed
* The block is handling its own caching in its hook_block_view().
*
* This setting is useful when time based expiration is needed or a site uses a
* node access which invalidates standard block cache.
*/
const DRUPAL_CACHE_CUSTOM = -2;
/**

catch
committed
* The block or element can change depending on the user's roles.
*
* This is the default setting for blocks, used when the block does not specify
* anything.
*/
const DRUPAL_CACHE_PER_ROLE = 0x0001;
/**

catch
committed
* The block or element can change depending on the user.
*
* This setting can be resource-consuming for sites with large number of users,
* and thus should only be used when DRUPAL_CACHE_PER_ROLE is not sufficient.
*/
const DRUPAL_CACHE_PER_USER = 0x0002;
/**
* The block or element can change depending on the page being viewed.
*/
const DRUPAL_CACHE_PER_PAGE = 0x0004;
/**

catch
committed
* The block or element is the same for every user and page that it is visible.
*/
const DRUPAL_CACHE_GLOBAL = 0x0008;

Jennifer Hodgdon
committed
/**
* @} End of "defgroup block_caching".
*/

Dries Buytaert
committed
/**
* The delimiter used to split plural strings.
*
* This is the ETX (End of text) character and is used as a minimal means to
* separate singular and plural variants in source and translation text. It
* was found to be the most compatible delimiter for the supported databases.
*/
const LOCALE_PLURAL_DELIMITER = "\03";

catch
committed
* Adds content to a specified region.
*
* @param $region

Dries Buytaert
committed
* Page region the content is added to.

Dries Buytaert
committed
* Content to be added.

Dries Buytaert
committed
function drupal_add_region_content($region = NULL, $data = NULL) {
static $content = array();

Dries Buytaert
committed
if (isset($region) && isset($data)) {
$content[$region][] = $data;
}
return $content;
}
/**

catch
committed
* Gets assigned content for a given region.
*
* @param $region
* A specified region to fetch content for. If NULL, all regions will be
* returned.

Dries Buytaert
committed
* Content to be inserted between imploded array elements.

Dries Buytaert
committed
function drupal_get_region_content($region = NULL, $delimiter = ' ') {
$content = drupal_add_region_content();
if (isset($region)) {
if (isset($content[$region]) && is_array($content[$region])) {
}
else {
foreach (array_keys($content) as $region) {
if (is_array($content[$region])) {
$content[$region] = implode($delimiter, $content[$region]);
}
}
return $content;
}
}

Angie Byron
committed
/**

Jennifer Hodgdon
committed
* Gets the name of the currently active installation profile.

Angie Byron
committed
*
* When this function is called during Drupal's initial installation process,
* the name of the profile that's about to be installed is stored in the global

Jennifer Hodgdon
committed
* installation state. At all other times, the "install_profile" setting will be
* available in settings.php.

Angie Byron
committed
*
* @return $profile

Jennifer Hodgdon
committed
* The name of the installation profile.

Angie Byron
committed
*/
function drupal_get_profile() {
global $install_state;

Dries Buytaert
committed
if (drupal_installation_attempted()) {
// If the profile has been selected return it.
if (isset($install_state['parameters']['profile'])) {
$profile = $install_state['parameters']['profile'];
}
else {
$profile = '';
}

Angie Byron
committed
}
else {

Dries Buytaert
committed
$profile = settings()->get('install_profile') ?: 'standard';

Angie Byron
committed
}
return $profile;
}

catch
committed
* Adds output to the HEAD tag of the HTML page.
* This function can be called as long as the headers aren't sent. Pass no
* arguments (or NULL for both) to retrieve the currently stored elements.
*
* @param $data
* A renderable array. If the '#type' key is not set then 'html_tag' will be
* added as the default '#type'.
* @param $key
* A unique string key to allow implementations of hook_html_head_alter() to
* identify the element in $data. Required if $data is not NULL.
*
* @return
* An array of all stored HEAD elements.
*

catch
committed
* @see drupal_pre_render_html_tag()
function drupal_add_html_head($data = NULL, $key = NULL) {
$stored_head = &drupal_static(__FUNCTION__);
if (!isset($stored_head)) {
// Make sure the defaults, including Content-Type, come first.
$stored_head = _drupal_default_html_head();
}
if (isset($data) && isset($key)) {
if (!isset($data['#type'])) {
$data['#type'] = 'html_tag';
}
$stored_head[$key] = $data;
* Returns elements that are always displayed in the HEAD tag of the HTML page.
*/
function _drupal_default_html_head() {
// Add default elements. Make sure the Content-Type comes first because the
// IE browser may be vulnerable to XSS via encoding attacks from any content
// that comes before this META tag, such as a TITLE tag.
$elements['system_meta_content_type'] = array(
'#type' => 'html_tag',
'#tag' => 'meta',
'#attributes' => array(

catch
committed
'charset' => 'utf-8',
),
// Security: This always has to be output first.
'#weight' => -1000,
);
// Show Drupal and the major version number in the META GENERATOR tag.
// Get the major version.
list($version, ) = explode('.', \Drupal::VERSION);
$elements['system_meta_generator'] = array(
'#type' => 'html_tag',
'#tag' => 'meta',
'#attributes' => array(
'name' => 'Generator',
'content' => 'Drupal ' . $version . ' (http://drupal.org)',
),
);
// Also send the generator in the HTTP header.
$elements['system_meta_generator']['#attached']['drupal_add_http_header'][] = array('X-Generator', $elements['system_meta_generator']['#attributes']['content']);
return $elements;
}
/**

catch
committed
* Retrieves output to be displayed in the HEAD tag of the HTML page.
$elements = drupal_add_html_head();
\Drupal::moduleHandler()->alter('html_head', $elements);
return drupal_render($elements);

catch
committed
* Adds a feed URL for the current page.
* This function can be called as long the HTML header hasn't been sent.
*
* An internal system path or a fully qualified external URL of the feed.
* @param $title
* The title of the feed.
function drupal_add_feed($url = NULL, $title = '') {

Dries Buytaert
committed
$stored_feed_links = &drupal_static(__FUNCTION__, array());
if (isset($url)) {

catch
committed
$feed_icon = array(
'#theme' => 'feed_icon',
'#url' => $url,
'#title' => $title,
);

catch
committed
$feed_icon['#attached']['drupal_add_html_head_link'][][] = array(
'rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => $title,
// Force the URL to be absolute, for consistency with other <link> tags
// output by Drupal.
'href' => url($url, array('absolute' => TRUE)),

catch
committed
);

catch
committed
$stored_feed_links[$url] = drupal_render($feed_icon);
}
return $stored_feed_links;
}
/**

catch
committed
* Gets the feed URLs for the current page.
*
* @param $delimiter
* A delimiter to split feeds by.
*/
function drupal_get_feeds($delimiter = "\n") {
$feeds = drupal_add_feed();
return implode($feeds, $delimiter);
}
* @defgroup http_handling HTTP handling

Gerhard Killesreiter
committed
/**

catch
committed
* Processes a URL query parameter array to remove unwanted elements.

Gerhard Killesreiter
committed
*
* @param $query

Angie Byron
committed
* (optional) An array to be processed. Defaults to \Drupal::request()->query
* parameters.

Gerhard Killesreiter
committed
* @param $exclude

Dries Buytaert
committed
* (optional) A list of $query array keys to remove. Use "parent[child]" to

Dries Buytaert
committed
* exclude nested items.

Gerhard Killesreiter
committed
* @param $parent

Dries Buytaert
committed
* Internal use only. Used to build the $query array key for nested items.
*

Gerhard Killesreiter
committed
* @return

Dries Buytaert
committed
* An array containing query parameters, which can be used for url().
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal\Component\Utility\Url::filterQueryParameters().

Gerhard Killesreiter
committed
*/

Dries Buytaert
committed
function drupal_get_query_parameters(array $query = NULL, array $exclude = array(), $parent = '') {

Dries Buytaert
committed
if (!isset($query)) {
$query = \Drupal::request()->query->all();

Angie Byron
committed
}
return Url::filterQueryParameters($query, $exclude, $parent);

Angie Byron
committed
}

Dries Buytaert
committed
/**

catch
committed
* Parses an array into a valid, rawurlencoded query string.

Dries Buytaert
committed
*
* @see drupal_get_query_parameters()
* @ingroup php_wrappers
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal\Component\Utility\Url::buildQuery().

Dries Buytaert
committed
*/
function drupal_http_build_query(array $query, $parent = '') {
return Url::buildQuery($query, $parent);

Gerhard Killesreiter
committed
}
/**
* Prepares a 'destination' URL query parameter for use with url().
* 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.
*

Jennifer Hodgdon
committed
* @return
* An associative array containing the key:
* - destination: The path provided via the destination query string or, if
* not available, the current path.
*
* @see current_path()
*/
function drupal_get_destination() {

Dries Buytaert
committed
$destination = &drupal_static(__FUNCTION__);
if (isset($destination)) {
return $destination;
}
$query = \Drupal::request()->query;
if ($query->has('destination')) {
$destination = array('destination' => $query->get('destination'));

Dries Buytaert
committed
}
else {

Dries Buytaert
committed
$path = current_path();
$query = Url::buildQuery(Url::filterQueryParameters($query->all()));

Gerhard Killesreiter
committed
if ($query != '') {
$path .= '?' . $query;

Gerhard Killesreiter
committed
}

Dries Buytaert
committed
$destination = array('destination' => $path);
}
return $destination;
}
/**

catch
committed
* Parses a system URL string into an associative array suitable for url().

Angie Byron
committed
*
* This function should only be used for URLs that have been generated by the
* system, such as via url(). It should not be used for URLs that come from
* external sources, or URLs that link to external resources.

Dries Buytaert
committed
*
* The returned array contains a 'path' that may be passed separately to url().
* For example:
* @code

Angie Byron
committed
* $options = drupal_parse_url(\Drupal::request()->query->get('destination'));

Dries Buytaert
committed
* $my_url = url($options['path'], $options);
* $my_link = l('Example link', $options['path'], $options);
* @endcode
*
* This is required, because url() does not support relative URLs containing a
* query string or fragment in its $path argument. Instead, any query string
* needs to be parsed into an associative query parameter array in
* $options['query'] and the fragment into $options['fragment'].
*
* @param $url

Angie Byron
committed
* The URL string to parse.

Dries Buytaert
committed
*
* @return
* An associative array containing the keys:
* - 'path': The path of the URL. If the given $url is external, this includes
* the scheme and host.
* - 'query': An array of query parameters of $url, if existent.
* - 'fragment': The fragment of $url, if existent.
*
* @see url()
* @ingroup php_wrappers
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal\Component\Utility\Url::parse().

Dries Buytaert
committed
*/
function drupal_parse_url($url) {
return Url::parse($url);

Dries Buytaert
committed
}
/**

Dries Buytaert
committed
* Encodes a Drupal path for use in a URL.

Dries Buytaert
committed
*

Dries Buytaert
committed
* For aesthetic reasons slashes are not escaped.

Dries Buytaert
committed
*

Dries Buytaert
committed
* Note that url() takes care of calling this function, so a path passed to that
* function should not be encoded in advance.

Dries Buytaert
committed
*
* @param $path

Dries Buytaert
committed
* The Drupal path to encode.
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal\Component\Utility\Url::encodePath().

Dries Buytaert
committed
*/
function drupal_encode_path($path) {
return Url::encodePath($path);
}
/**
* Determines if an external URL points to this Drupal installation.
*
* @param $url
* A string containing an external URL, such as "http://example.com/foo".
*
* @return
* TRUE if the URL has the same domain and base path.
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal\Component\Utility\Url::externalIsLocal().
*/
function _external_url_is_local($url) {
return Url::externalIsLocal($url, base_path());
}

Dries Buytaert
committed
/**
* Helper function for determining hosts excluded from needing a proxy.
*
* @return
* TRUE if a proxy should be used for this host.
*/
function _drupal_http_use_proxy($host) {
$proxy_exceptions = settings()->get('proxy_exceptions', array('localhost', '127.0.0.1'));

Dries Buytaert
committed
return !in_array(strtolower($host), $proxy_exceptions, TRUE);
}
* @} End of "defgroup http_handling".

Dries Buytaert
committed
/**

catch
committed
* Verifies the syntax of the given e-mail address.

Dries Buytaert
committed
* This uses the
* @link http://php.net/manual/filter.filters.validate.php PHP e-mail validation filter. @endlink

Dries Buytaert
committed
*
* A string containing an e-mail address.

catch
committed
*

Dries Buytaert
committed
*/
return (bool)filter_var($mail, FILTER_VALIDATE_EMAIL);

Dries Buytaert
committed
}

catch
committed
* Verifies the syntax of the given URL.
* This function should only be used on actual URLs. It should not be used for
* Drupal menu paths, which can contain arbitrary characters.

Dries Buytaert
committed
* Valid values per RFC 3986.
* Whether the URL is absolute (beginning with a scheme such as "http:").

catch
committed
*
*
* @see \Drupal\Component\Utility\Url::isValid()
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal\Component\Utility\Url::isValid().
return Url::isValid($url, $absolute);
/**
* Verifies that a number is a multiple of a given step.
*

catch
committed
* @see \Drupal\Component\Utility\Number::validStep()

catch
committed
* @param numeric $value
* The value that needs to be checked.

catch
committed
* @param numeric $step
* The step scale factor. Must be positive.

catch
committed
* @param numeric $offset
* (optional) An offset, to which the difference must be a multiple of the
* given step.
*
* @return bool

Jennifer Hodgdon
committed
* TRUE if no step mismatch has occurred, or FALSE otherwise.
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal\Component\Utility\Number::validStep().
*/
function valid_number_step($value, $step, $offset = 0.0) {

catch
committed
return Number::validStep($value, $step, $offset);
/**
* @} End of "defgroup validation".
*/
/**
* @defgroup sanitization Sanitization functions
* @{
* Functions to sanitize values.

Dries Buytaert
committed
*
* See http://drupal.org/writing-secure-code for information
* on writing secure code.
* Strips dangerous protocols (e.g. 'javascript:') from a URI.
*
* This function must be called for all URIs within user-entered input prior
* to being output to an HTML attribute value. It is often called as part of
* check_url() or filter_xss(), but those functions return an HTML-encoded
* string, so this function can be called independently when the output needs to
* be a plain-text string for passing to t(), l(),
* Drupal\Core\Template\Attribute, or another function that will call

Angie Byron
committed
* \Drupal\Component\Utility\String::checkPlain() separately.
*
* @param $uri
* A plain-text URI that might contain dangerous protocols.
*
* @return
* A plain-text URI stripped of dangerous protocols. As with all plain-text
* strings, this return value must not be output to an HTML page without

Angie Byron
committed
* \Drupal\Component\Utility\String::checkPlain() being called on it. However,
* it can be passed to functions expecting plain-text strings.
*
* @see \Drupal\Component\Utility\Url::stripDangerousProtocols()
*/
function drupal_strip_dangerous_protocols($uri) {
return Url::stripDangerousProtocols($uri);
}
/**

catch
committed
* Strips dangerous protocols from a URI and encodes it for output to HTML.
*
* @param $uri
* A plain-text URI that might contain dangerous protocols.
*
* @return
* 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
* 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

Angie Byron
committed
* Drupal\Core\Template\Attribute, call
* \Drupal\Component\Utility\Url::stripDangerousProtocols() instead.
*
* @see \Drupal\Component\Utility\Url::stripDangerousProtocols()
* @see \Drupal\Component\Utility\String::checkPlain()
return String::checkPlain(Url::stripDangerousProtocols($uri));

catch
committed
* Applies a very permissive XSS/HTML filter for admin-only use.
*
* Use only for fields where it is impractical to use the
* whole filter system, but where some (mainly inline) mark-up

Angie Byron
committed
* is desired (so \Drupal\Component\Utility\String::checkPlain() is not
* acceptable).
*
* Allows all tags that can be used inside an HTML body, save
* for scripts and styles.
*
* @param string $string
* The string to apply the filter to.
*
* @return string
* The filtered string.
*
* @see \Drupal\Component\Utility\Xss::filterAdmin()
*/
function filter_xss_admin($string) {
return Xss::filterAdmin($string);
}
/**

catch
committed
* Filters HTML to prevent cross-site-scripting (XSS) vulnerabilities.

Dries Buytaert
committed
* Based on kses by Ulf Harnhammar, see http://sourceforge.net/projects/kses.
* For examples of various XSS attacks, see: http://ha.ckers.org/xss.html.
*
* This code does four things:

Dries Buytaert
committed
* - Removes characters and constructs that can trick browsers.
* - Makes sure all HTML entities are well-formed.
* - Makes sure all HTML tags and attributes are well-formed.
* - Makes sure no HTML tags contain URLs with a disallowed protocol (e.g.
* javascript:).
*
* @param $string

Dries Buytaert
committed
* The string with raw HTML in it. It will be stripped of everything that can
* cause an XSS attack.
* @param $allowed_tags
* An array of allowed tags.

Dries Buytaert
committed
*
* @return
* An XSS safe version of $string, or an empty string if $string is not
* valid UTF-8.
*
* @see \Drupal\Component\Utility\Xss::filter()
*

Dries Buytaert
committed
* @ingroup sanitization
*/
function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd')) {
return Xss::filter($string, $allowed_tags);
}
/**

catch
committed
* Processes an HTML attribute value and strips dangerous protocols from URLs.
* @param string $string
* The string with the attribute value.

catch
committed
*
* @return string
* Cleaned up and HTML-escaped version of $string.
*
* @see \Drupal\Component\Utility\Url::filterBadProtocol()
function filter_xss_bad_protocol($string) {
return Url::filterBadProtocol($string);
}
/**
* @} End of "defgroup sanitization".
*/
/**
* Formats an RSS channel.
*
* Arbitrary elements may be added using the $args associative array.
*/

Gábor Hojtsy
committed
function format_rss_channel($title, $link, $description, $items, $langcode = NULL, $args = array()) {
$langcode = $langcode ? $langcode : language(Language::TYPE_CONTENT)->id;

Angie Byron
committed
$output .= ' <title>' . String::checkPlain($title) . "</title>\n";
$output .= ' <link>' . check_url($link) . "</link>\n";
// The RSS 2.0 "spec" doesn't indicate HTML can be used in the description.
// We strip all HTML tags, but need to prevent double encoding from properly
// escaped source data (such as & becoming &amp;).

Angie Byron
committed
$output .= ' <description>' . String::checkPlain(decode_entities(strip_tags($description))) . "</description>\n";
$output .= ' <language>' . String::checkPlain($langcode) . "</language>\n";
$output .= format_xml_elements($args);
$output .= $items;
$output .= "</channel>\n";
return $output;
}

catch
committed
* Formats a single RSS item.
*
* Arbitrary elements may be added using the $args associative array.
*/
function format_rss_item($title, $link, $description, $args = array()) {

Angie Byron
committed
$output .= ' <title>' . String::checkPlain($title) . "</title>\n";
$output .= ' <link>' . check_url($link) . "</link>\n";

Angie Byron
committed
$output .= ' <description>' . String::checkPlain($description) . "</description>\n";
$output .= format_xml_elements($args);
$output .= "</item>\n";
return $output;
}
/**

catch
committed
* Formats XML elements.
*
* @param $array
* An array where each item represents an element and is either a:
* - (key => value) pair (<key>value</key>)
* - Associative array with fields:
* - 'key': element name
* - 'value': element contents
* - 'attributes': associative array of element attributes
*
* In both cases, 'value' can be a simple string, or it can be another array
* with the same format as $array itself for nesting.
*/
function format_xml_elements($array) {

Steven Wittens
committed
$output = '';
foreach ($array as $key => $value) {
if (is_numeric($key)) {
$output .= ' <' . $value['key'];

Dries Buytaert
committed
if (isset($value['attributes']) && is_array($value['attributes'])) {
$output .= new Attribute($value['attributes']);
if (isset($value['value']) && $value['value'] != '') {

Angie Byron
committed
$output .= '>' . (is_array($value['value']) ? format_xml_elements($value['value']) : String::checkPlain($value['value'])) . '</' . $value['key'] . ">\n";

Angie Byron
committed
$output .= ' <' . $key . '>' . (is_array($value) ? format_xml_elements($value) : String::checkPlain($value)) . "</$key>\n";

catch
committed
* Formats a string containing a count of items.
* This function ensures that the string is pluralized correctly. Since t() is
* called by this function, make sure not to pass already-localized strings to
* it.
* For example:
* @code
* $output = format_plural($node->comment_count, '1 comment', '@count comments');
* @endcode
*
* Example with additional replacements:
* @code
* $output = format_plural($update_count,
* 'Changed the content type of 1 post from %old-type to %new-type.',
* 'Changed the content type of @count posts from %old-type to %new-type.',
* array('%old-type' => $info->old_type, '%new-type' => $info->new_type));
* @endcode
*
* @param $count
* The item count to display.
* @param $singular

catch
committed
* The string for the singular case. Make sure it is clear this is singular,
* to ease translation (e.g. use "1 new comment" instead of "1 new"). Do not
* use @count in the singular string.

catch
committed
* The string for the plural case. Make sure it is clear this is plural, to
* ease translation. Use @count in place of the item count, as in
* "@count new comments".
* @param $args

catch
committed
* An associative array of replacements to make after translation. Instances
* of any key in this array are replaced with the corresponding value.

catch
committed
* Based on the first character of the key, the value is escaped and/or
* themed. See format_string(). Note that you do not need to include @count
* in this array; this replacement is done automatically for the plural case.

Dries Buytaert
committed
* @param $options

catch
committed
* An associative array of additional options. See t() for allowed keys.
*

catch
committed
*
* @see t()
* @see format_string()
* @see \Drupal\Core\StringTranslation\TranslationManager->formatPlural()
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal::translation()->formatPlural().

Dries Buytaert
committed
function format_plural($count, $singular, $plural, array $args = array(), array $options = array()) {
return \Drupal::translation()->formatPlural($count, $singular, $plural, $args, $options);

Dries Buytaert
committed
/**

catch
committed
* Parses a given byte count.

Dries Buytaert
committed
*
* @param $size

Dries Buytaert
committed
* A size expressed as a number of bytes with optional SI or IEC binary unit
* prefix (e.g. 2, 3K, 5MB, 10G, 6GiB, 8 bytes, 9mbytes).

catch
committed
*

Dries Buytaert
committed
* @return

Dries Buytaert
committed
* An integer representation of the size in bytes.

Dries Buytaert
committed
*/
function parse_size($size) {

Dries Buytaert
committed
$unit = preg_replace('/[^bkmgtpezy]/i', '', $size); // Remove the non-unit characters from the size.
$size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size.
if ($unit) {
// Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
return round($size * pow(DRUPAL_KILOBYTE, stripos('bkmgtpezy', $unit[0])));
}
else {
return round($size);

Dries Buytaert
committed
}
}

catch
committed
* Generates a string representation for the given byte count.
* A size in bytes.

Gábor Hojtsy
committed
* @param $langcode
* Optional language code to translate to a language other than what is used
* to display the page.

catch
committed
*

Gábor Hojtsy
committed
function format_size($size, $langcode = NULL) {

Dries Buytaert
committed
if ($size < DRUPAL_KILOBYTE) {

Dries Buytaert
committed
return format_plural($size, '1 byte', '@count bytes', array(), array('langcode' => $langcode));

Dries Buytaert
committed
$size = $size / DRUPAL_KILOBYTE; // Convert bytes to kilobytes.

Dries Buytaert
committed
$units = array(

Dries Buytaert
committed
t('@size KB', array(), array('langcode' => $langcode)),
t('@size MB', array(), array('langcode' => $langcode)),
t('@size GB', array(), array('langcode' => $langcode)),
t('@size TB', array(), array('langcode' => $langcode)),
t('@size PB', array(), array('langcode' => $langcode)),
t('@size EB', array(), array('langcode' => $langcode)),
t('@size ZB', array(), array('langcode' => $langcode)),
t('@size YB', array(), array('langcode' => $langcode)),

Dries Buytaert
committed
);
foreach ($units as $unit) {

Dries Buytaert
committed
if (round($size, 2) >= DRUPAL_KILOBYTE) {
$size = $size / DRUPAL_KILOBYTE;

Dries Buytaert
committed
}
else {
break;
}

Dries Buytaert
committed
return str_replace('@size', round($size, 2), $unit);

catch
committed
* Formats a time interval with the requested granularity.

Dries Buytaert
committed
* @param $interval
* The length of the interval in seconds.
* @param $granularity
* How many different units to display in the string.

Gábor Hojtsy
committed
* @param $langcode
* Optional language code to translate to a language other than
* what is used to display the page.

catch
committed
*
*
* @see \Drupal\Core\Datetime\Date::formatInterval()
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal::service('date')->formatInterval().