Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -30,7 +30,7 @@ class MockFileFinder implements ClassFinderInterface {
/**
* Creates new mock file finder objects.
*/
static public function create($filename) {
public static function create($filename) {
$object = new static();
$object->filename = $filename;
return $object;

View file

@ -3,14 +3,14 @@
"description": "Annotation discovery and implementation of plugins.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"doctrine/common": "2.5.*",
"doctrine/common": "^2.5",
"doctrine/annotations": "1.2.*",
"drupal/core-fileCache": "~8.2",
"drupal/core-plugin": "~8.2",
"drupal/core-utility": "~8.2"
"drupal/core-file-cache": "^8.2",
"drupal/core-plugin": "^8.2",
"drupal/core-utility": "^8.2"
},
"autoload": {
"psr-4": {

View file

@ -25,7 +25,7 @@ class Handle {
require __DIR__ . '/global_namespace_php5.php';
}
// PHP 5 - create a handler to throw the exception directly.
assert_options(ASSERT_CALLBACK, function($file = '', $line = 0, $code = '', $message = '') {
assert_options(ASSERT_CALLBACK, function ($file = '', $line = 0, $code = '', $message = '') {
if (empty($message)) {
$message = $code;
}

View file

@ -13,7 +13,7 @@ use Traversable;
*
* Example call:
* @code
* assert('Drupal\\Component\\Assertion\\Inspector::assertAllStrings($array)');
* assert(Inspector::assertAllStrings($array));
* @endcode
*
* @ingroup php_assert
@ -187,8 +187,8 @@ class Inspector {
* As an example, this assertion tests for the keys of a theme registry.
*
* @code
* assert('Drupal\\Component\\Assertion\\Inspector::assertAllHaveKey(
* $arrayToTest, "type", "theme path", "function", "template", "variables", "render element", "preprocess functions")');
* assert(Inspector::assertAllHaveKey(
* $arrayToTest, "type", "theme path", "function", "template", "variables", "render element", "preprocess functions"));
* @endcode
*
* Note: If a method requires certain keys to be present it will usually be
@ -205,9 +205,9 @@ class Inspector {
* @return bool
* TRUE if $traversable can be traversed and all members have all keys.
*/
public static function assertAllHaveKey() {
public static function assertAllHaveKey($traversable) {
$args = func_get_args();
$traversable = array_shift($args);
unset($args[0]);
if (static::assertTraversable($traversable)) {
foreach ($traversable as $member) {
@ -333,7 +333,6 @@ class Inspector {
return FALSE;
}
/**
* Asserts that all members are strings matching a regular expression.
*
@ -375,16 +374,13 @@ class Inspector {
* Here are some examples:
* @code
* // Just test all are objects, like a cache.
* assert('Drupal\\Component\\Assertion\\Inspector::assertAllObjects(
* $collection');
* assert(Inspector::assertAllObjects($collection));
*
* // Test if traversable objects (arrays won't pass this)
* assert('Drupal\\Component\\Assertion\\Inspector::assertAllObjects(
* $collection', \'\\Traversable\');
* assert(Inspector::assertAllObjects($collection, '\\Traversable'));
*
* // Test for the Foo class or Bar\None interface
* assert('Drupal\\Component\\Assertion\\Inspector::assertAllObjects(
* $collection', \'\\Foo\', \'\\Bar\\None\'');
* assert(Inspector::assertAllObjects($collection, '\\Foo', '\\Bar\\None'));
* @endcode
*
* @param mixed $traversable
@ -396,9 +392,9 @@ class Inspector {
* TRUE if $traversable can be traversed and all members are objects with
* at least one of the listed classes or interfaces.
*/
public static function assertAllObjects() {
public static function assertAllObjects($traversable) {
$args = func_get_args();
$traversable = array_shift($args);
unset($args[0]);
if (static::assertTraversable($traversable)) {
foreach ($traversable as $member) {

View file

@ -3,7 +3,7 @@
"description": "Provides runtime assertions similar to those in PHP 7, under PHP 5.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
},

View file

@ -4,6 +4,7 @@ namespace Drupal\Component\Bridge;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Zend\Feed\Reader\ExtensionManagerInterface as ReaderManagerInterface;
use Zend\Feed\Writer\ExtensionManagerInterface as WriterManagerInterface;
@ -48,6 +49,11 @@ class ZfExtensionManagerSfContainer implements ReaderManagerInterface, WriterMan
*/
protected $canonicalNames;
/**
* @var \Zend\Feed\Reader\ExtensionManagerInterface|\Zend\Feed\Writer\ExtensionManagerInterface
*/
protected $standalone;
/**
* Constructs a ZfExtensionManagerSfContainer object.
*
@ -62,14 +68,25 @@ class ZfExtensionManagerSfContainer implements ReaderManagerInterface, WriterMan
* {@inheritdoc}
*/
public function get($extension) {
return $this->container->get($this->prefix . $this->canonicalizeName($extension));
try {
return $this->container->get($this->prefix . $this->canonicalizeName($extension));
}
catch (ServiceNotFoundException $e) {
if ($this->standalone && $this->standalone->has($extension)) {
return $this->standalone->get($extension);
}
throw $e;
}
}
/**
* {@inheritdoc}
*/
public function has($extension) {
return $this->container->has($this->prefix . $this->canonicalizeName($extension));
if ($this->container->has($this->prefix . $this->canonicalizeName($extension))) {
return TRUE;
}
return $this->standalone && $this->standalone->has($extension);
}
/**
@ -102,4 +119,14 @@ class ZfExtensionManagerSfContainer implements ReaderManagerInterface, WriterMan
$this->container = $container;
}
/**
* @param $class
*/
public function setStandalone($class) {
if (!is_subclass_of($class, ReaderManagerInterface::class) && !is_subclass_of($class, WriterManagerInterface::class)) {
throw new \RuntimeException("$class must implement Zend\Feed\Reader\ExtensionManagerInterface or Zend\Feed\Writer\ExtensionManagerInterface");
}
$this->standalone = new $class();
}
}

View file

@ -3,10 +3,10 @@
"description": "Bridge.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"zendframework/zend-feed": "~2.4"
"zendframework/zend-feed": "^2.4"
},
"autoload": {
"psr-4": {

View file

@ -3,10 +3,10 @@
"description": "This class provides a class finding utility.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"doctrine/common": "2.5.*"
"doctrine/common": "^2.5"
},
"autoload": {
"psr-4": {

View file

@ -1,6 +1,7 @@
<?php
namespace Drupal\Component\Datetime;
use Drupal\Component\Utility\ToStringTrait;
/**
@ -22,17 +23,30 @@ use Drupal\Component\Utility\ToStringTrait;
* errors are. This is less disruptive than allowing datetime exceptions
* to abort processing. The calling script can decide what to do about
* errors using hasErrors() and getErrors().
*
* @method $this add(\DateInterval $interval)
* @method static array getLastErrors()
* @method $this modify(string $modify)
* @method $this setDate(int $year, int $month, int $day)
* @method $this setISODate(int $year, int $week, int $day = 1)
* @method $this setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0)
* @method $this setTimestamp(int $unixtimestamp)
* @method $this setTimezone(\DateTimeZone $timezone)
* @method $this sub(\DateInterval $interval)
* @method int getOffset()
* @method int getTimestamp()
* @method \DateTimeZone getTimezone()
*/
class DateTimePlus {
use ToStringTrait;
const FORMAT = 'Y-m-d H:i:s';
const FORMAT = 'Y-m-d H:i:s';
/**
* A RFC7231 Compliant date.
*
* http://tools.ietf.org/html/rfc7231#section-7.1.1.1
* @see http://tools.ietf.org/html/rfc7231#section-7.1.1.1
*
* Example: Sun, 06 Nov 1994 08:49:37 GMT
*/
@ -52,31 +66,43 @@ class DateTimePlus {
/**
* The value of the time value passed to the constructor.
*
* @var string
*/
protected $inputTimeRaw = '';
/**
* The prepared time, without timezone, for this date.
*
* @var string
*/
protected $inputTimeAdjusted = '';
/**
* The value of the timezone passed to the constructor.
*
* @var string
*/
protected $inputTimeZoneRaw = '';
/**
* The prepared timezone object used to construct this date.
*
* @var string
*/
protected $inputTimeZoneAdjusted = '';
/**
* The value of the format passed to the constructor.
*
* @var string
*/
protected $inputFormatRaw = '';
/**
* The prepared format, if provided.
*
* @var string
*/
protected $inputFormatAdjusted = '';
@ -250,7 +276,11 @@ class DateTimePlus {
* (optional) A date/time string. Defaults to 'now'.
* @param mixed $timezone
* (optional) \DateTimeZone object, time zone string or NULL. NULL uses the
* default system time zone. Defaults to NULL.
* default system time zone. Defaults to NULL. Note that the $timezone
* parameter and the current timezone are ignored when the $time parameter
* either is a UNIX timestamp (e.g. @946684800) or specifies a timezone
* (e.g. 2010-01-28T15:00:00+02:00).
* @see http://php.net/manual/datetime.construct.php
* @param array $settings
* (optional) Keyed array of settings. Defaults to empty array.
* - langcode: (optional) String two letter language code used to control
@ -301,8 +331,25 @@ class DateTimePlus {
* Implements the magic __call method.
*
* Passes through all unknown calls onto the DateTime object.
*
* @param string $method
* The method to call on the decorated object.
* @param array $args
* Call arguments.
*
* @return mixed
* The return value from the method on the decorated object. If the proxied
* method call returns a DateTime object, then return the original
* DateTimePlus object, which allows function chaining to work properly.
* Otherwise, the value from the proxied method call is returned.
*
* @throws \Exception
* Thrown when the DateTime object is not set.
* @throws \BadMethodCallException
* Thrown when there is no corresponding method on the DateTime object to
* call.
*/
public function __call($method, $args) {
public function __call($method, array $args) {
// @todo consider using assert() as per https://www.drupal.org/node/2451793.
if (!isset($this->dateTimeObject)) {
throw new \Exception('DateTime object not set.');
@ -310,19 +357,22 @@ class DateTimePlus {
if (!method_exists($this->dateTimeObject, $method)) {
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
}
return call_user_func_array([$this->dateTimeObject, $method], $args);
$result = call_user_func_array([$this->dateTimeObject, $method], $args);
return $result === $this->dateTimeObject ? $this : $result;
}
/**
* Returns the difference between two DateTimePlus objects.
*
* @param \Drupal\Component\Datetime\DateTimePlus|\DateTime $datetime2
* The date to compare to.
* The date to compare to.
* @param bool $absolute
* Should the interval be forced to be positive?
* Should the interval be forced to be positive?
*
* @return \DateInterval
* A DateInterval object representing the difference between the two dates.
* A DateInterval object representing the difference between the two dates.
*
* @throws \BadMethodCallException
* If the input isn't a DateTime or DateTimePlus object.
@ -427,8 +477,6 @@ class DateTimePlus {
return $format;
}
/**
* Examines getLastErrors() to see what errors to report.
*
@ -622,13 +670,14 @@ class DateTimePlus {
* Formats the date for display.
*
* @param string $format
* A format string using either PHP's date().
* Format accepted by date().
* @param array $settings
* - timezone: (optional) String timezone name. Defaults to the timezone
* of the date object.
*
* @return string
* The formatted value of the date.
* @return string|null
* The formatted value of the date or NULL if there were construction
* errors.
*/
public function format($format, $settings = []) {
@ -654,4 +703,25 @@ class DateTimePlus {
return $value;
}
/**
* Sets the default time for an object built from date-only data.
*
* The default time for a date without time can be anything, so long as it is
* consistently applied. If we use noon, dates in most timezones will have the
* same value for in both the local timezone and UTC.
*/
public function setDefaultDateTime() {
$this->dateTimeObject->setTime(12, 0, 0);
}
/**
* Gets a clone of the proxied PHP \DateTime object wrapped by this class.
*
* @return \DateTime
* A clone of the wrapped PHP \DateTime object.
*/
public function getPhpDateTime() {
return clone $this->dateTimeObject;
}
}

View file

@ -3,10 +3,10 @@
"description": "This class wraps the PHP DateTime class with more flexible initialization parameters, allowing a date to be created from an existing date object, a timestamp, a string with an unknown format, a string with a known format, or an array of date parts. It also adds an errors array and a __toString() method to the date object.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"drupal/core-utility": "~8.2"
"drupal/core-utility": "^8.2"
},
"autoload": {
"psr-4": {

View file

@ -3,9 +3,7 @@
namespace Drupal\Component\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\IntrospectableContainerInterface;
use Symfony\Component\DependencyInjection\ResettableContainerInterface;
use Symfony\Component\DependencyInjection\ScopeInterface;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@ -43,14 +41,10 @@ use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceExce
* getAServiceWithAnIdByCamelCase().
* - The function getServiceIds() was added as it has a use-case in core and
* contrib.
* - Scopes are explicitly not allowed, because Symfony 2.8 has deprecated
* them and they will be removed in Symfony 3.0.
* - Synchronized services are explicitly not supported, because Symfony 2.8 has
* deprecated them and they will be removed in Symfony 3.0.
*
* @ingroup container
*/
class Container implements IntrospectableContainerInterface, ResettableContainerInterface {
class Container implements ContainerInterface, ResettableContainerInterface {
/**
* The parameters of the container.
@ -311,12 +305,8 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
}
}
// Share the service if it is public.
if (!isset($definition['public']) || $definition['public'] !== FALSE) {
// Forward compatibility fix for Symfony 2.8 update.
if (!isset($definition['shared']) || $definition['shared'] !== FALSE) {
$this->services[$id] = $service;
}
if (!isset($definition['shared']) || $definition['shared'] !== FALSE) {
$this->services[$id] = $service;
}
if (isset($definition['calls'])) {
@ -361,11 +351,7 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
/**
* {@inheritdoc}
*/
public function set($id, $service, $scope = ContainerInterface::SCOPE_CONTAINER) {
if (!in_array($scope, ['container', 'request']) || ('request' === $scope && 'request' !== $id)) {
@trigger_error('The concept of container scopes is deprecated since version 2.8 and will be removed in 3.0. Omit the third parameter.', E_USER_DEPRECATED);
}
public function set($id, $service) {
$this->services[$id] = $service;
}
@ -587,61 +573,6 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
return $this->getAlternatives($name, array_keys($this->parameters));
}
/**
* {@inheritdoc}
*/
public function enterScope($name) {
if ('request' !== $name) {
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
}
throw new \BadMethodCallException(sprintf("'%s' is not supported by Drupal 8.", __FUNCTION__));
}
/**
* {@inheritdoc}
*/
public function leaveScope($name) {
if ('request' !== $name) {
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
}
throw new \BadMethodCallException(sprintf("'%s' is not supported by Drupal 8.", __FUNCTION__));
}
/**
* {@inheritdoc}
*/
public function addScope(ScopeInterface $scope) {
$name = $scope->getName();
if ('request' !== $name) {
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
}
throw new \BadMethodCallException(sprintf("'%s' is not supported by Drupal 8.", __FUNCTION__));
}
/**
* {@inheritdoc}
*/
public function hasScope($name) {
if ('request' !== $name) {
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
}
throw new \BadMethodCallException(sprintf("'%s' is not supported by Drupal 8.", __FUNCTION__));
}
/**
* {@inheritdoc}
*/
public function isScopeActive($name) {
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
throw new \BadMethodCallException(sprintf("'%s' is not supported by Drupal 8.", __FUNCTION__));
}
/**
* Gets all defined service IDs.
*
@ -655,8 +586,7 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
/**
* Ensure that cloning doesn't work.
*/
private function __clone()
{
private function __clone() {
}
}

View file

@ -65,7 +65,7 @@ class OptimizedPhpArrayDumper extends Dumper {
$definition['aliases'] = $this->getAliases();
$definition['parameters'] = $this->getParameters();
$definition['services'] = $this->getServiceDefinitions();
$definition['frozen'] = $this->container->isFrozen();
$definition['frozen'] = $this->container->isCompiled();
$definition['machine_format'] = $this->supportsMachineFormat();
return $definition;
}
@ -103,8 +103,8 @@ class OptimizedPhpArrayDumper extends Dumper {
}
$parameters = $this->container->getParameterBag()->all();
$is_frozen = $this->container->isFrozen();
return $this->prepareParameters($parameters, $is_frozen);
$is_compiled = $this->container->isCompiled();
return $this->prepareParameters($parameters, $is_compiled);
}
/**
@ -237,18 +237,6 @@ class OptimizedPhpArrayDumper extends Dumper {
$service['calls'] = $this->dumpMethodCalls($definition->getMethodCalls());
}
if (($scope = $definition->getScope()) !== ContainerInterface::SCOPE_CONTAINER) {
if ($scope === ContainerInterface::SCOPE_PROTOTYPE) {
// Scope prototype has been replaced with 'shared' => FALSE.
// This is a Symfony 2.8 forward compatibility fix.
// Reference: https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#dependencyinjection
$service['shared'] = FALSE;
}
else {
throw new InvalidArgumentException("The 'scope' definition is deprecated in Symfony 3.0 and not supported by Drupal 8.");
}
}
// By default services are shared, so just provide the flag, when needed.
if ($definition->isShared() === FALSE) {
$service['shared'] = $definition->isShared();
@ -294,7 +282,6 @@ class OptimizedPhpArrayDumper extends Dumper {
return $code;
}
/**
* Dumps a collection to a PHP array.
*
@ -321,10 +308,10 @@ class OptimizedPhpArrayDumper extends Dumper {
}
}
else {
if (is_object($value)) {
$code[$key] = $this->dumpValue($value);
if (is_object($code[$key])) {
$resolve = TRUE;
}
$code[$key] = $this->dumpValue($value);
}
}
@ -415,6 +402,9 @@ class OptimizedPhpArrayDumper extends Dumper {
elseif ($value instanceof Parameter) {
return $this->getParameterCall((string) $value);
}
elseif (is_string($value) && preg_match('/^\%(.*)\%$/', $value, $matches)) {
return $this->getParameterCall($matches[1]);
}
elseif ($value instanceof Expression) {
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}

View file

@ -136,12 +136,8 @@ class PhpArrayContainer extends Container {
}
}
// Share the service if it is public.
if (!isset($definition['public']) || $definition['public'] !== FALSE) {
// Forward compatibility fix for Symfony 2.8 update.
if (!isset($definition['shared']) || $definition['shared'] !== FALSE) {
$this->services[$id] = $service;
}
if (!isset($definition['shared']) || $definition['shared'] !== FALSE) {
$this->services[$id] = $service;
}
if (isset($definition['calls'])) {
@ -204,7 +200,7 @@ class PhpArrayContainer extends Container {
// The PhpArrayDumper just uses the hash of the private service
// definition to generate a unique ID.
//
// @see \Drupal\Component\DependecyInjection\Dumper\OptimizedPhpArrayDumper::getPrivateServiceCall
// @see \Drupal\Component\DependencyInjection\Dumper\OptimizedPhpArrayDumper::getPrivateServiceCall
if ($type == 'private_service') {
$id = $argument->id;

View file

@ -4,7 +4,7 @@
"keywords": ["drupal", "dependency injection"],
"type": "library",
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"support": {
"issues": "https://www.drupal.org/project/issues/drupal",
"irc": "irc://irc.freenode.net/drupal-contribute",
@ -12,7 +12,7 @@
},
"require": {
"php": ">=5.5.9",
"symfony/dependency-injection": "~2.8"
"symfony/dependency-injection": ">=2.8 <4.0.0"
},
"suggest": {
"symfony/expression-language": "For using expressions in service container configuration"

View file

@ -27,9 +27,11 @@ class Diff {
* Constructor.
* Computes diff between sequences of strings.
*
* @param $from_lines array An array of strings.
* (Typically these are lines from a file.)
* @param $to_lines array An array of strings.
* @param array $from_lines
* An array of strings.
* (Typically these are lines from a file.)
* @param array $to_lines
* An array of strings.
*/
public function __construct($from_lines, $to_lines) {
$eng = new DiffEngine();
@ -44,8 +46,8 @@ class Diff {
*
* $diff = new Diff($lines1, $lines2);
* $rev = $diff->reverse();
* @return object A Diff object representing the inverse of the
* original diff.
* @return object
* A Diff object representing the inverse of the original diff.
*/
public function reverse() {
$rev = $this;
@ -146,7 +148,6 @@ class Diff {
trigger_error("Reversed closing doesn't match", E_USER_ERROR);
}
$prevtype = 'none';
foreach ($this->edits as $edit) {
if ( $prevtype == $edit->type ) {

View file

@ -2,8 +2,6 @@
namespace Drupal\Component\Diff\Engine;
use Drupal\Component\Utility\Unicode;
/**
* Class used internally by Diff to actually compute the diffs.
*
@ -134,7 +132,7 @@ class DiffEngine {
* Returns the whole line if it's small enough, or the MD5 hash otherwise.
*/
protected function _line_hash($line) {
if (Unicode::strlen($line) > $this::MAX_XREF_LENGTH) {
if (mb_strlen($line) > $this::MAX_XREF_LENGTH) {
return md5($line);
}
else {
@ -195,34 +193,36 @@ class DiffEngine {
}
$x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks);
for ( ; $x < $x1; $x++) {
for (; $x < $x1; $x++) {
$line = $flip ? $this->yv[$x] : $this->xv[$x];
if (empty($ymatches[$line])) {
continue;
}
$matches = $ymatches[$line];
reset($matches);
while (list ($junk, $y) = each($matches)) {
if (empty($this->in_seq[$y])) {
$k = $this->_lcs_pos($y);
$this::USE_ASSERTS && assert($k > 0);
$ymids[$k] = $ymids[$k - 1];
break;
$found_empty = FALSE;
foreach ($matches as $y) {
if (!$found_empty) {
if (empty($this->in_seq[$y])) {
$k = $this->_lcs_pos($y);
$this::USE_ASSERTS && assert($k > 0);
$ymids[$k] = $ymids[$k - 1];
$found_empty = TRUE;
}
}
}
while (list ($junk, $y) = each($matches)) {
if ($y > $this->seq[$k - 1]) {
$this::USE_ASSERTS && assert($y < $this->seq[$k]);
// Optimization: this is a common case:
// next match is just replacing previous match.
$this->in_seq[$this->seq[$k]] = FALSE;
$this->seq[$k] = $y;
$this->in_seq[$y] = 1;
}
elseif (empty($this->in_seq[$y])) {
$k = $this->_lcs_pos($y);
$this::USE_ASSERTS && assert($k > 0);
$ymids[$k] = $ymids[$k - 1];
else {
if ($y > $this->seq[$k - 1]) {
$this::USE_ASSERTS && assert($y < $this->seq[$k]);
// Optimization: this is a common case:
// next match is just replacing previous match.
$this->in_seq[$this->seq[$k]] = FALSE;
$this->seq[$k] = $y;
$this->in_seq[$y] = 1;
}
elseif (empty($this->in_seq[$y])) {
$k = $this->_lcs_pos($y);
$this::USE_ASSERTS && assert($k > 0);
$ymids[$k] = $ymids[$k - 1];
}
}
}
}
@ -302,8 +302,7 @@ class DiffEngine {
//$nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
//$nchunks = max(2, min(8, (int)$nchunks));
$nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
list($lcs, $seps)
= $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks);
list($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks);
}
if ($lcs == 0) {
@ -344,7 +343,7 @@ class DiffEngine {
$i = 0;
$j = 0;
$this::USE_ASSERTS && assert('sizeof($lines) == sizeof($changed)');
$this::USE_ASSERTS && assert(sizeof($lines) == sizeof($changed));
$len = sizeof($lines);
$other_len = sizeof($other_changed);
@ -364,7 +363,7 @@ class DiffEngine {
$j++;
}
while ($i < $len && !$changed[$i]) {
$this::USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
$this::USE_ASSERTS && assert($j < $other_len && ! $other_changed[$j]);
$i++;
$j++;
while ($j < $other_len && $other_changed[$j]) {
@ -400,11 +399,11 @@ class DiffEngine {
while ($start > 0 && $changed[$start - 1]) {
$start--;
}
$this::USE_ASSERTS && assert('$j > 0');
$this::USE_ASSERTS && assert($j > 0);
while ($other_changed[--$j]) {
continue;
}
$this::USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
$this::USE_ASSERTS && assert($j >= 0 && !$other_changed[$j]);
}
/*
@ -427,7 +426,7 @@ class DiffEngine {
while ($i < $len && $changed[$i]) {
$i++;
}
$this::USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
$this::USE_ASSERTS && assert($j < $other_len && ! $other_changed[$j]);
$j++;
if ($j < $other_len && $other_changed[$j]) {
$corresponding = $i;
@ -445,11 +444,11 @@ class DiffEngine {
while ($corresponding < $i) {
$changed[--$start] = 1;
$changed[--$i] = 0;
$this::USE_ASSERTS && assert('$j > 0');
$this::USE_ASSERTS && assert($j > 0);
while ($other_changed[--$j]) {
continue;
}
$this::USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
$this::USE_ASSERTS && assert($j >= 0 && !$other_changed[$j]);
}
}
}

View file

@ -2,8 +2,6 @@
namespace Drupal\Component\Diff\Engine;
use Drupal\Component\Utility\Unicode;
/**
* Additions by Axel Boldt follow, partly taken from diff.php, phpwiki-1.3.3
*/
@ -64,7 +62,7 @@ class HWLDFWordAccumulator {
}
if ($word[0] == "\n") {
$this->_flushLine($tag);
$word = Unicode::substr($word, 1);
$word = mb_substr($word, 1);
}
assert(!strstr($word, "\n"));
$this->group .= $word;

View file

@ -19,16 +19,17 @@ class MappedDiff extends Diff {
* case-insensitive diffs, or diffs which ignore
* changes in white-space.
*
* @param $from_lines array An array of strings.
* @param array $from_lines
* An array of strings.
* (Typically these are lines from a file.)
* @param $to_lines array An array of strings.
* @param $mapped_from_lines array This array should
* have the same size number of elements as $from_lines.
* The elements in $mapped_from_lines and
* $mapped_to_lines are what is actually compared
* when computing the diff.
* @param $mapped_to_lines array This array should
* have the same number of elements as $to_lines.
* @param array $to_lines
* An array of strings.
* @param array $mapped_from_lines
* This array should have the same size number of elements as $from_lines.
* The elements in $mapped_from_lines and $mapped_to_lines are what is
* actually compared when computing the diff.
* @param array $mapped_to_lines
* This array should have the same number of elements as $to_lines.
*/
public function __construct($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines) {

View file

@ -3,7 +3,6 @@
namespace Drupal\Component\Diff;
use Drupal\Component\Diff\Engine\HWLDFWordAccumulator;
use Drupal\Component\Utility\Unicode;
/**
* @todo document
@ -35,7 +34,7 @@ class WordLevelDiff extends MappedDiff {
$words[] = "\n";
$stripped[] = "\n";
}
if (Unicode::strlen($line) > $this::MAX_LINE_LENGTH) {
if (mb_strlen($line) > $this::MAX_LINE_LENGTH) {
$words[] = $line;
$stripped[] = $line;
}

View file

@ -3,10 +3,10 @@
"description": "Diff.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"drupal/utility": "~8.2"
"symfony/polyfill-mbstring": "~1.0"
},
"autoload": {
"psr-4": {

View file

@ -3,11 +3,11 @@
"description": "Discovery.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"drupal/core-filecache": "~8.2",
"drupal/core-serialization": "~8.2"
"drupal/core-file-cache": "^8.2",
"drupal/core-serialization": "^8.2"
},
"autoload": {
"psr-4": {

View file

@ -2,7 +2,7 @@
namespace Drupal\Component\EventDispatcher;
use Symfony\Component\DependencyInjection\IntrospectableContainerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@ -36,7 +36,7 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
/**
* The service container.
*
* @var \Symfony\Component\DependencyInjection\IntrospectableContainerInterface;
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
@ -66,7 +66,7 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
/**
* Constructs a container aware event dispatcher.
*
* @param \Symfony\Component\DependencyInjection\IntrospectableContainerInterface $container
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The service container.
* @param array $listeners
* A nested array of listener definitions keyed by event name and priority.
@ -77,7 +77,7 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
* A service entry will be resolved to a callable only just before its
* invocation.
*/
public function __construct(IntrospectableContainerInterface $container, array $listeners = []) {
public function __construct(ContainerInterface $container, array $listeners = []) {
$this->container = $container;
$this->listeners = $listeners;
$this->unsorted = [];
@ -91,9 +91,6 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
$event = new Event();
}
$event->setDispatcher($this);
$event->setName($event_name);
if (isset($this->listeners[$event_name])) {
// Sort listeners if necessary.
if (isset($this->unsorted[$event_name])) {
@ -107,8 +104,11 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
if (!isset($definition['callable'])) {
$definition['callable'] = [$this->container->get($definition['service'][0]), $definition['service'][1]];
}
if (is_array($definition['callable']) && isset($definition['callable'][0]) && $definition['callable'][0] instanceof \Closure) {
$definition['callable'][0] = $definition['callable'][0]();
}
$definition['callable']($event, $event_name, $this);
call_user_func($definition['callable'], $event, $event_name, $this);
if ($event->isPropagationStopped()) {
return $event;
}
@ -147,6 +147,9 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
if (!isset($definition['callable'])) {
$definition['callable'] = [$this->container->get($definition['service'][0]), $definition['service'][1]];
}
if (is_array($definition['callable']) && isset($definition['callable'][0]) && $definition['callable'][0] instanceof \Closure) {
$definition['callable'][0] = $definition['callable'][0]();
}
$result[] = $definition['callable'];
}
@ -159,27 +162,29 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
/**
* {@inheritdoc}
*/
public function getListenerPriority($eventName, $listener) {
// Parts copied from \Symfony\Component\EventDispatcher, that's why you see
// a yoda condition here.
if (!isset($this->listeners[$eventName])) {
public function getListenerPriority($event_name, $listener) {
if (!isset($this->listeners[$event_name])) {
return;
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
if (FALSE !== ($key = array_search(['callable' => $listener], $listeners, TRUE))) {
return $priority;
}
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
}
// Resolve service definitions if the listener has not been found so far.
foreach ($this->listeners[$eventName] as $priority => &$definitions) {
foreach ($this->listeners[$event_name] as $priority => &$definitions) {
foreach ($definitions as $key => &$definition) {
if (!isset($definition['callable'])) {
// Once the callable is retrieved we keep it for subsequent method
// invocations on this class.
$definition['callable'] = [$this->container->get($definition['service'][0]), $definition['service'][1]];
if ($definition['callable'] === $listener) {
return $priority;
}
$definition['callable'] = [
$this->container->get($definition['service'][0]),
$definition['service'][1],
];
}
if (is_array($definition['callable']) && isset($definition['callable'][0]) && $definition['callable'][0] instanceof \Closure) {
$definition['callable'][0] = $definition['callable'][0]();
}
if ($definition['callable'] === $listener) {
return $priority;
}
}
}
@ -189,7 +194,17 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
* {@inheritdoc}
*/
public function hasListeners($event_name = NULL) {
return (bool) count($this->getListeners($event_name));
if ($event_name !== NULL) {
return !empty($this->listeners[$event_name]);
}
foreach ($this->listeners as $event_listeners) {
if ($event_listeners) {
return TRUE;
}
}
return FALSE;
}
/**
@ -217,9 +232,22 @@ class ContainerAwareEventDispatcher implements EventDispatcherInterface {
$definition['callable'] = [$this->container->get($definition['service'][0]), $definition['service'][1]];
}
if ($definition['callable'] === $listener) {
unset($this->listeners[$event_name][$priority][$key]);
if (is_array($definition['callable']) && isset($definition['callable'][0]) && $definition['callable'][0] instanceof \Closure && !$listener instanceof \Closure) {
$definition['callable'][0] = $definition['callable'][0]();
}
if (is_array($definition['callable']) && isset($definition['callable'][0]) && !$definition['callable'][0] instanceof \Closure && is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
}
if ($definition['callable'] === $listener) {
unset($definitions[$key]);
}
}
if ($definitions) {
$this->listeners[$event_name][$priority] = $definitions;
}
else {
unset($this->listeners[$event_name][$priority]);
}
}
}

View file

@ -3,11 +3,11 @@
"description": "EventDispatcher.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"symfony/dependency-injection": "~2.8",
"symfony/event-dispatcher": "~2.7"
"symfony/dependency-injection": ">=2.8 <4.0.0",
"symfony/event-dispatcher": ">=2.7 <4.0.0"
},
"autoload": {
"psr-4": {

View file

@ -15,7 +15,7 @@ class FileCacheFactory {
/**
* The configuration used to create FileCache objects.
*
* @var array $configuration
* @var array
*/
protected static $configuration;

View file

@ -3,7 +3,7 @@
"description": "FileCache.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
},

View file

@ -3,7 +3,7 @@
"description": "FileSystem.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
},

View file

@ -27,42 +27,42 @@ class PoHeader {
*
* @var string
*/
private $_langcode;
protected $langcode;
/**
* Formula for the plural form.
*
* @var string
*/
private $_pluralForms;
protected $pluralForms;
/**
* Author(s) of the file.
*
* @var string
*/
private $_authors;
protected $authors;
/**
* Date the po file got created.
*
* @var string
*/
private $_po_date;
protected $poDate;
/**
* Human readable language name.
*
* @var string
*/
private $_languageName;
protected $languageName;
/**
* Name of the project the translation belongs to.
*
* @var string
*/
private $_projectName;
protected $projectName;
/**
* Constructor, creates a PoHeader with default values.
@ -71,11 +71,11 @@ class PoHeader {
* Language code.
*/
public function __construct($langcode = NULL) {
$this->_langcode = $langcode;
$this->langcode = $langcode;
// Ignore errors when run during site installation before
// date_default_timezone_set() is called.
$this->_po_date = @date("Y-m-d H:iO");
$this->_pluralForms = 'nplurals=2; plural=(n > 1);';
$this->poDate = @date("Y-m-d H:iO");
$this->pluralForms = 'nplurals=2; plural=(n > 1);';
}
/**
@ -86,7 +86,7 @@ class PoHeader {
* 'nplurals=2; plural=(n > 1);'.
*/
public function getPluralForms() {
return $this->_pluralForms;
return $this->pluralForms;
}
/**
@ -96,7 +96,7 @@ class PoHeader {
* Human readable language name.
*/
public function setLanguageName($languageName) {
$this->_languageName = $languageName;
$this->languageName = $languageName;
}
/**
@ -106,7 +106,7 @@ class PoHeader {
* The human readable language name.
*/
public function getLanguageName() {
return $this->_languageName;
return $this->languageName;
}
/**
@ -116,7 +116,7 @@ class PoHeader {
* Human readable project name.
*/
public function setProjectName($projectName) {
$this->_projectName = $projectName;
$this->projectName = $projectName;
}
/**
@ -126,7 +126,7 @@ class PoHeader {
* The human readable project name.
*/
public function getProjectName() {
return $this->_projectName;
return $this->projectName;
}
/**
@ -142,7 +142,7 @@ class PoHeader {
// There is only one value relevant for our header implementation when
// reading, and that is the plural formula.
if (!empty($values['Plural-Forms'])) {
$this->_pluralForms = $values['Plural-Forms'];
$this->pluralForms = $values['Plural-Forms'];
}
}
@ -152,11 +152,11 @@ class PoHeader {
public function __toString() {
$output = '';
$isTemplate = empty($this->_languageName);
$isTemplate = empty($this->languageName);
$output .= '# ' . ($isTemplate ? 'LANGUAGE' : $this->_languageName) . ' translation of ' . ($isTemplate ? 'PROJECT' : $this->_projectName) . "\n";
if (!empty($this->_authors)) {
$output .= '# Generated by ' . implode("\n# ", $this->_authors) . "\n";
$output .= '# ' . ($isTemplate ? 'LANGUAGE' : $this->languageName) . ' translation of ' . ($isTemplate ? 'PROJECT' : $this->projectName) . "\n";
if (!empty($this->authors)) {
$output .= '# Generated by ' . implode("\n# ", $this->authors) . "\n";
}
$output .= "#\n";
@ -164,14 +164,14 @@ class PoHeader {
$output .= "msgid \"\"\n";
$output .= "msgstr \"\"\n";
$output .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
$output .= "\"POT-Creation-Date: " . $this->_po_date . "\\n\"\n";
$output .= "\"PO-Revision-Date: " . $this->_po_date . "\\n\"\n";
$output .= "\"POT-Creation-Date: " . $this->poDate . "\\n\"\n";
$output .= "\"PO-Revision-Date: " . $this->poDate . "\\n\"\n";
$output .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
$output .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
$output .= "\"MIME-Version: 1.0\\n\"\n";
$output .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
$output .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
$output .= "\"Plural-Forms: " . $this->_pluralForms . "\\n\"\n";
$output .= "\"Plural-Forms: " . $this->pluralForms . "\\n\"\n";
$output .= "\n";
return $output;
@ -188,7 +188,7 @@ class PoHeader {
* - 'nplurals': The number of plural forms defined by the plural formula.
* - 'plurals': Array of plural positions keyed by plural value.
*
* @throws Exception
* @throws \Exception
*/
public function parsePluralForms($pluralforms) {
$plurals = [];
@ -473,7 +473,7 @@ class PoHeader {
* Number of the plural string to be used for the given plural value.
*
* @see parseArithmetic()
* @throws Exception
* @throws \Exception
*/
protected function evaluatePlural($element_stack, $n) {
$count = count($element_stack);

View file

@ -13,46 +13,47 @@ class PoItem {
/**
* The language code this translation is in.
*
* @car string
* @var string
*/
private $_langcode;
protected $langcode;
/**
* The context this translation belongs to.
*
* @var string
*/
private $_context = '';
protected $context = '';
/**
* The source string or array of strings if it has plurals.
*
* @var string or array
* @see $_plural
* @var string|array
*
* @see $plural
*/
private $_source;
protected $source;
/**
* Flag indicating if this translation has plurals.
*
* @var bool
*/
private $_plural;
protected $plural;
/**
* The comment of this translation.
*
* @var string
*/
private $_comment;
protected $comment;
/**
* The translation string or array of strings if it has plurals.
*
* @var string or array
* @see $_plural
* @var string|array
* @see $plural
*/
private $_translation;
protected $translation;
/**
* Gets the language code of the currently used language.
@ -60,7 +61,7 @@ class PoItem {
* @return string with langcode
*/
public function getLangcode() {
return $this->_langcode;
return $this->langcode;
}
/**
@ -69,7 +70,7 @@ class PoItem {
* @param string $langcode
*/
public function setLangcode($langcode) {
$this->_langcode = $langcode;
$this->langcode = $langcode;
}
/**
@ -78,7 +79,7 @@ class PoItem {
* @return string $context
*/
public function getContext() {
return $this->_context;
return $this->context;
}
/**
@ -87,7 +88,7 @@ class PoItem {
* @param string $context
*/
public function setContext($context) {
$this->_context = $context;
$this->context = $context;
}
/**
@ -97,17 +98,17 @@ class PoItem {
* @return string or array $translation
*/
public function getSource() {
return $this->_source;
return $this->source;
}
/**
* Set the source string or the array of strings if the translation has
* plurals.
*
* @param string or array $source
* @param string|array $source
*/
public function setSource($source) {
$this->_source = $source;
$this->source = $source;
}
/**
@ -117,17 +118,17 @@ class PoItem {
* @return string or array $translation
*/
public function getTranslation() {
return $this->_translation;
return $this->translation;
}
/**
* Set the translation string or the array of strings if the translation has
* plurals.
*
* @param string or array $translation
* @param string|array $translation
*/
public function setTranslation($translation) {
$this->_translation = $translation;
$this->translation = $translation;
}
/**
@ -136,7 +137,7 @@ class PoItem {
* @param bool $plural
*/
public function setPlural($plural) {
$this->_plural = $plural;
$this->plural = $plural;
}
/**
@ -145,7 +146,7 @@ class PoItem {
* @return bool
*/
public function isPlural() {
return $this->_plural;
return $this->plural;
}
/**
@ -154,7 +155,7 @@ class PoItem {
* @return String $comment
*/
public function getComment() {
return $this->_comment;
return $this->comment;
}
/**
@ -163,7 +164,7 @@ class PoItem {
* @param string $comment
*/
public function setComment($comment) {
$this->_comment = $comment;
$this->comment = $comment;
}
/**
@ -184,11 +185,11 @@ class PoItem {
if (isset($values['comment'])) {
$this->setComment($values['comment']);
}
if (isset($this->_source) &&
strpos($this->_source, LOCALE_PLURAL_DELIMITER) !== FALSE) {
$this->setSource(explode(LOCALE_PLURAL_DELIMITER, $this->_source));
$this->setTranslation(explode(LOCALE_PLURAL_DELIMITER, $this->_translation));
$this->setPlural(count($this->_source) > 1);
if (isset($this->source) &&
strpos($this->source, LOCALE_PLURAL_DELIMITER) !== FALSE) {
$this->setSource(explode(LOCALE_PLURAL_DELIMITER, $this->source));
$this->setTranslation(explode(LOCALE_PLURAL_DELIMITER, $this->translation));
$this->setPlural(count($this->source) > 1);
}
}
@ -206,12 +207,12 @@ class PoItem {
$output = '';
// Format string context.
if (!empty($this->_context)) {
$output .= 'msgctxt ' . $this->formatString($this->_context);
if (!empty($this->context)) {
$output .= 'msgctxt ' . $this->formatString($this->context);
}
// Format translation.
if ($this->_plural) {
if ($this->plural) {
$output .= $this->formatPlural();
}
else {
@ -231,11 +232,11 @@ class PoItem {
$output = '';
// Format source strings.
$output .= 'msgid ' . $this->formatString($this->_source[0]);
$output .= 'msgid_plural ' . $this->formatString($this->_source[1]);
$output .= 'msgid ' . $this->formatString($this->source[0]);
$output .= 'msgid_plural ' . $this->formatString($this->source[1]);
foreach ($this->_translation as $i => $trans) {
if (isset($this->_translation[$i])) {
foreach ($this->translation as $i => $trans) {
if (isset($this->translation[$i])) {
$output .= 'msgstr[' . $i . '] ' . $this->formatString($trans);
}
else {
@ -251,8 +252,8 @@ class PoItem {
*/
private function formatSingular() {
$output = '';
$output .= 'msgid ' . $this->formatString($this->_source);
$output .= 'msgstr ' . (isset($this->_translation) ? $this->formatString($this->_translation) : '""');
$output .= 'msgid ' . $this->formatString($this->source);
$output .= 'msgstr ' . (isset($this->translation) ? $this->formatString($this->translation) : '""');
return $output;
}

View file

@ -12,13 +12,13 @@ class PoMemoryWriter implements PoWriterInterface {
*
* @var array
*/
private $_items;
protected $items;
/**
* Constructor, initialize empty items.
*/
public function __construct() {
$this->_items = [];
$this->items = [];
}
/**
@ -30,7 +30,7 @@ class PoMemoryWriter implements PoWriterInterface {
$item->setTranslation(implode(LOCALE_PLURAL_DELIMITER, $item->getTranslation()));
}
$context = $item->getContext();
$this->_items[$context != NULL ? $context : ''][$item->getSource()] = $item->getTranslation();
$this->items[$context != NULL ? $context : ''][$item->getSource()] = $item->getTranslation();
}
/**
@ -49,7 +49,7 @@ class PoMemoryWriter implements PoWriterInterface {
* @return array PoItem
*/
public function getData() {
return $this->_items;
return $this->items;
}
/**

View file

@ -2,7 +2,7 @@
namespace Drupal\Component\Gettext;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
/**
* Implements Gettext PO stream reader.
@ -17,7 +17,7 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
*
* @var int
*/
private $_line_number = 0;
protected $lineNumber = 0;
/**
* Parser context for the stream reader state machine.
@ -32,90 +32,90 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
*
* @var string
*/
private $_context = 'COMMENT';
protected $context = 'COMMENT';
/**
* Current entry being read. Incomplete.
*
* @var array
*/
private $_current_item = [];
protected $currentItem = [];
/**
* Current plural index for plural translations.
*
* @var int
*/
private $_current_plural_index = 0;
protected $currentPluralIndex = 0;
/**
* URI of the PO stream that is being read.
*
* @var string
*/
private $_uri = '';
protected $uri = '';
/**
* Language code for the PO stream being read.
*
* @var string
*/
private $_langcode = NULL;
protected $langcode = NULL;
/**
* File handle of the current PO stream.
*
* @var resource
*/
private $_fd;
protected $fd;
/**
* The PO stream header.
*
* @var \Drupal\Component\Gettext\PoHeader
*/
private $_header;
protected $header;
/**
* Object wrapper for the last read source/translation pair.
*
* @var \Drupal\Component\Gettext\PoItem
*/
private $_last_item;
protected $lastItem;
/**
* Indicator of whether the stream reading is finished.
*
* @var bool
*/
private $_finished;
protected $finished;
/**
* Array of translated error strings recorded on reading this stream so far.
*
* @var array
*/
private $_errors;
protected $errors;
/**
* {@inheritdoc}
*/
public function getLangcode() {
return $this->_langcode;
return $this->langcode;
}
/**
* {@inheritdoc}
*/
public function setLangcode($langcode) {
$this->_langcode = $langcode;
$this->langcode = $langcode;
}
/**
* {@inheritdoc}
*/
public function getHeader() {
return $this->_header;
return $this->header;
}
/**
@ -130,14 +130,14 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
* {@inheritdoc}
*/
public function getURI() {
return $this->_uri;
return $this->uri;
}
/**
* {@inheritdoc}
*/
public function setURI($uri) {
$this->_uri = $uri;
$this->uri = $uri;
}
/**
@ -146,12 +146,12 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
* Opens the stream and reads the header. The stream is ready for reading
* items after.
*
* @throws Exception
* @throws \Exception
* If the URI is not yet set.
*/
public function open() {
if (!empty($this->_uri)) {
$this->_fd = fopen($this->_uri, 'rb');
if (!empty($this->uri)) {
$this->fd = fopen($this->uri, 'rb');
$this->readHeader();
}
else {
@ -162,12 +162,12 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
/**
* Implements Drupal\Component\Gettext\PoStreamInterface::close().
*
* @throws Exception
* @throws \Exception
* If the stream is not open.
*/
public function close() {
if ($this->_fd) {
fclose($this->_fd);
if ($this->fd) {
fclose($this->fd);
}
else {
throw new \Exception('Cannot close stream that is not open.');
@ -179,14 +179,14 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
*/
public function readItem() {
// Clear out the last item.
$this->_last_item = NULL;
$this->lastItem = NULL;
// Read until finished with the stream or a complete item was identified.
while (!$this->_finished && is_null($this->_last_item)) {
while (!$this->finished && is_null($this->lastItem)) {
$this->readLine();
}
return $this->_last_item;
return $this->lastItem;
}
/**
@ -196,14 +196,14 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
* The new seek position to set.
*/
public function setSeek($seek) {
fseek($this->_fd, $seek);
fseek($this->fd, $seek);
}
/**
* Gets the pointer position of the current PO stream.
*/
public function getSeek() {
return ftell($this->_fd);
return ftell($this->fd);
}
/**
@ -221,18 +221,18 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
}
$header = new PoHeader();
$header->setFromString(trim($item->getTranslation()));
$this->_header = $header;
$this->header = $header;
}
/**
* Reads a line from the PO stream and stores data internally.
*
* Expands $this->_current_item based on new data for the current item. If
* Expands $this->current_item based on new data for the current item. If
* this line ends the current item, it is saved with setItemFromArray() with
* data from $this->_current_item.
* data from $this->current_item.
*
* An internal state machine is maintained in this reader using
* $this->_context as the reading state. PO items are in between COMMENT
* $this->context as the reading state. PO items are in between COMMENT
* states (when items have at least one line or comment in between them) or
* indicated by MSGSTR or MSGSTR_ARR followed immediately by an MSGID or
* MSGCTXT (when items closely follow each other).
@ -245,25 +245,25 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
private function readLine() {
// Read a line and set the stream finished indicator if it was not
// possible anymore.
$line = fgets($this->_fd);
$this->_finished = ($line === FALSE);
$line = fgets($this->fd);
$this->finished = ($line === FALSE);
if (!$this->_finished) {
if (!$this->finished) {
if ($this->_line_number == 0) {
if ($this->lineNumber == 0) {
// The first line might come with a UTF-8 BOM, which should be removed.
$line = str_replace("\xEF\xBB\xBF", '', $line);
// Current plurality for 'msgstr[]'.
$this->_current_plural_index = 0;
$this->currentPluralIndex = 0;
}
// Track the line number for error reporting.
$this->_line_number++;
$this->lineNumber++;
// Initialize common values for error logging.
$log_vars = [
'%uri' => $this->getURI(),
'%line' => $this->_line_number,
'%line' => $this->lineNumber,
];
// Trim away the linefeed. \\n might appear at the end of the string if
@ -273,24 +273,24 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
if (!strncmp('#', $line, 1)) {
// Lines starting with '#' are comments.
if ($this->_context == 'COMMENT') {
if ($this->context == 'COMMENT') {
// Already in comment context, add to current comment.
$this->_current_item['#'][] = substr($line, 1);
$this->currentItem['#'][] = substr($line, 1);
}
elseif (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) {
elseif (($this->context == 'MSGSTR') || ($this->context == 'MSGSTR_ARR')) {
// We are currently in string context, save current item.
$this->setItemFromArray($this->_current_item);
$this->setItemFromArray($this->currentItem);
// Start a new entry for the comment.
$this->_current_item = [];
$this->_current_item['#'][] = substr($line, 1);
$this->currentItem = [];
$this->currentItem['#'][] = substr($line, 1);
$this->_context = 'COMMENT';
$this->context = 'COMMENT';
return;
}
else {
// A comment following any other context is a syntax error.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgstr" was expected but not found on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgstr" was expected but not found on line %line.', $log_vars);
return FALSE;
}
return;
@ -298,9 +298,9 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
elseif (!strncmp('msgid_plural', $line, 12)) {
// A plural form for the current source string.
if ($this->_context != 'MSGID') {
if ($this->context != 'MSGID') {
// A plural form can only be added to an msgid directly.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgid_plural" was expected but not found on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgid_plural" was expected but not found on line %line.', $log_vars);
return FALSE;
}
@ -311,34 +311,34 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
$quoted = $this->parseQuoted($line);
if ($quoted === FALSE) {
// The plural form must be wrapped in quotes.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains a syntax error on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains a syntax error on line %line.', $log_vars);
return FALSE;
}
// Append the plural source to the current entry.
if (is_string($this->_current_item['msgid'])) {
if (is_string($this->currentItem['msgid'])) {
// The first value was stored as string. Now we know the context is
// plural, it is converted to array.
$this->_current_item['msgid'] = [$this->_current_item['msgid']];
$this->currentItem['msgid'] = [$this->currentItem['msgid']];
}
$this->_current_item['msgid'][] = $quoted;
$this->currentItem['msgid'][] = $quoted;
$this->_context = 'MSGID_PLURAL';
$this->context = 'MSGID_PLURAL';
return;
}
elseif (!strncmp('msgid', $line, 5)) {
// Starting a new message.
if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) {
if (($this->context == 'MSGSTR') || ($this->context == 'MSGSTR_ARR')) {
// We are currently in string context, save current item.
$this->setItemFromArray($this->_current_item);
$this->setItemFromArray($this->currentItem);
// Start a new context for the msgid.
$this->_current_item = [];
$this->currentItem = [];
}
elseif ($this->_context == 'MSGID') {
elseif ($this->context == 'MSGID') {
// We are currently already in the context, meaning we passed an id with no data.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgid" is unexpected on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgid" is unexpected on line %line.', $log_vars);
return FALSE;
}
@ -349,25 +349,25 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
$quoted = $this->parseQuoted($line);
if ($quoted === FALSE) {
// The message id must be wrapped in quotes.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgid" on line %line.', $log_vars, $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgid" on line %line.', $log_vars, $log_vars);
return FALSE;
}
$this->_current_item['msgid'] = $quoted;
$this->_context = 'MSGID';
$this->currentItem['msgid'] = $quoted;
$this->context = 'MSGID';
return;
}
elseif (!strncmp('msgctxt', $line, 7)) {
// Starting a new context.
if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) {
if (($this->context == 'MSGSTR') || ($this->context == 'MSGSTR_ARR')) {
// We are currently in string context, save current item.
$this->setItemFromArray($this->_current_item);
$this->_current_item = [];
$this->setItemFromArray($this->currentItem);
$this->currentItem = [];
}
elseif (!empty($this->_current_item['msgctxt'])) {
elseif (!empty($this->currentItem['msgctxt'])) {
// A context cannot apply to another context.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgctxt" is unexpected on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgctxt" is unexpected on line %line.', $log_vars);
return FALSE;
}
@ -378,37 +378,37 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
$quoted = $this->parseQuoted($line);
if ($quoted === FALSE) {
// The context string must be quoted.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgctxt" on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgctxt" on line %line.', $log_vars);
return FALSE;
}
$this->_current_item['msgctxt'] = $quoted;
$this->currentItem['msgctxt'] = $quoted;
$this->_context = 'MSGCTXT';
$this->context = 'MSGCTXT';
return;
}
elseif (!strncmp('msgstr[', $line, 7)) {
// A message string for a specific plurality.
if (($this->_context != 'MSGID') &&
($this->_context != 'MSGCTXT') &&
($this->_context != 'MSGID_PLURAL') &&
($this->_context != 'MSGSTR_ARR')) {
// Plural message strings must come after msgid, msgxtxt,
if (($this->context != 'MSGID') &&
($this->context != 'MSGCTXT') &&
($this->context != 'MSGID_PLURAL') &&
($this->context != 'MSGSTR_ARR')) {
// Plural message strings must come after msgid, msgctxt,
// msgid_plural, or other msgstr[] entries.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgstr[]" is unexpected on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgstr[]" is unexpected on line %line.', $log_vars);
return FALSE;
}
// Ensure the plurality is terminated.
if (strpos($line, ']') === FALSE) {
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
return FALSE;
}
// Extract the plurality.
$frombracket = strstr($line, '[');
$this->_current_plural_index = substr($frombracket, 1, strpos($frombracket, ']') - 1);
$this->currentPluralIndex = substr($frombracket, 1, strpos($frombracket, ']') - 1);
// Skip to the next whitespace and trim away any further whitespace,
// bringing $line to the message text only.
@ -417,24 +417,24 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
$quoted = $this->parseQuoted($line);
if ($quoted === FALSE) {
// The string must be quoted.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
return FALSE;
}
if (!isset($this->_current_item['msgstr']) || !is_array($this->_current_item['msgstr'])) {
$this->_current_item['msgstr'] = [];
if (!isset($this->currentItem['msgstr']) || !is_array($this->currentItem['msgstr'])) {
$this->currentItem['msgstr'] = [];
}
$this->_current_item['msgstr'][$this->_current_plural_index] = $quoted;
$this->currentItem['msgstr'][$this->currentPluralIndex] = $quoted;
$this->_context = 'MSGSTR_ARR';
$this->context = 'MSGSTR_ARR';
return;
}
elseif (!strncmp("msgstr", $line, 6)) {
// A string pair for an msgid (with optional context).
if (($this->_context != 'MSGID') && ($this->_context != 'MSGCTXT')) {
if (($this->context != 'MSGID') && ($this->context != 'MSGCTXT')) {
// Strings are only valid within an id or context scope.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: "msgstr" is unexpected on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgstr" is unexpected on line %line.', $log_vars);
return FALSE;
}
@ -445,13 +445,13 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
$quoted = $this->parseQuoted($line);
if ($quoted === FALSE) {
// The string must be quoted.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: invalid format for "msgstr" on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: invalid format for "msgstr" on line %line.', $log_vars);
return FALSE;
}
$this->_current_item['msgstr'] = $quoted;
$this->currentItem['msgstr'] = $quoted;
$this->_context = 'MSGSTR';
$this->context = 'MSGSTR';
return;
}
elseif ($line != '') {
@ -460,37 +460,37 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
$quoted = $this->parseQuoted($line);
if ($quoted === FALSE) {
// This string must be quoted.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: string continuation expected on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: string continuation expected on line %line.', $log_vars);
return FALSE;
}
// Append the string to the current item.
if (($this->_context == 'MSGID') || ($this->_context == 'MSGID_PLURAL')) {
if (is_array($this->_current_item['msgid'])) {
if (($this->context == 'MSGID') || ($this->context == 'MSGID_PLURAL')) {
if (is_array($this->currentItem['msgid'])) {
// Add string to last array element for plural sources.
$last_index = count($this->_current_item['msgid']) - 1;
$this->_current_item['msgid'][$last_index] .= $quoted;
$last_index = count($this->currentItem['msgid']) - 1;
$this->currentItem['msgid'][$last_index] .= $quoted;
}
else {
// Singular source, just append the string.
$this->_current_item['msgid'] .= $quoted;
$this->currentItem['msgid'] .= $quoted;
}
}
elseif ($this->_context == 'MSGCTXT') {
elseif ($this->context == 'MSGCTXT') {
// Multiline context name.
$this->_current_item['msgctxt'] .= $quoted;
$this->currentItem['msgctxt'] .= $quoted;
}
elseif ($this->_context == 'MSGSTR') {
elseif ($this->context == 'MSGSTR') {
// Multiline translation string.
$this->_current_item['msgstr'] .= $quoted;
$this->currentItem['msgstr'] .= $quoted;
}
elseif ($this->_context == 'MSGSTR_ARR') {
elseif ($this->context == 'MSGSTR_ARR') {
// Multiline plural translation string.
$this->_current_item['msgstr'][$this->_current_plural_index] .= $quoted;
$this->currentItem['msgstr'][$this->currentPluralIndex] .= $quoted;
}
else {
// No valid context to append to.
$this->_errors[] = SafeMarkup::format('The translation stream %uri contains an error: unexpected string on line %line.', $log_vars);
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: unexpected string on line %line.', $log_vars);
return FALSE;
}
return;
@ -498,14 +498,16 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
}
// Empty line read or EOF of PO stream, close out the last entry.
if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) {
$this->setItemFromArray($this->_current_item);
$this->_current_item = [];
if (($this->context == 'MSGSTR') || ($this->context == 'MSGSTR_ARR')) {
$this->setItemFromArray($this->currentItem);
$this->currentItem = [];
}
elseif ($this->_context != 'COMMENT') {
$this->_errors[] = SafeMarkup::format('The translation stream %uri ended unexpectedly at line %line.', $log_vars);
elseif ($this->context != 'COMMENT') {
$this->errors[] = new FormattableMarkup('The translation stream %uri ended unexpectedly at line %line.', $log_vars);
return FALSE;
}
return;
}
/**
@ -531,11 +533,11 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
$item->setTranslation($value['msgstr']);
$item->setPlural($plural);
$item->setComment($comments);
$item->setLangcode($this->_langcode);
$item->setLangcode($this->langcode);
$this->_last_item = $item;
$this->lastItem = $item;
$this->_context = 'COMMENT';
$this->context = 'COMMENT';
}
/**

View file

@ -12,21 +12,28 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
*
* @var string
*/
private $_uri;
protected $uri;
/**
* The Gettext PO header.
*
* @var \Drupal\Component\Gettext\PoHeader
*/
private $_header;
protected $header;
/**
* File handle of the current PO stream.
*
* @var resource
*/
private $_fd;
protected $fd;
/**
* The language code of this writer.
*
* @var string
*/
protected $langcode;
/**
* Gets the PO header of the current stream.
@ -35,7 +42,7 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
* The Gettext PO header.
*/
public function getHeader() {
return $this->_header;
return $this->header;
}
/**
@ -45,7 +52,7 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
* The Gettext PO header to set.
*/
public function setHeader(PoHeader $header) {
$this->_header = $header;
$this->header = $header;
}
/**
@ -55,7 +62,7 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
* The language code.
*/
public function getLangcode() {
return $this->_langcode;
return $this->langcode;
}
/**
@ -65,7 +72,7 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
* The language code.
*/
public function setLangcode($langcode) {
$this->_langcode = $langcode;
$this->langcode = $langcode;
}
/**
@ -73,7 +80,7 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
*/
public function open() {
// Open in write mode. Will overwrite the stream if it already exists.
$this->_fd = fopen($this->getURI(), 'w');
$this->fd = fopen($this->getURI(), 'w');
// Write the header at the start.
$this->writeHeader();
}
@ -81,15 +88,15 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
/**
* Implements Drupal\Component\Gettext\PoStreamInterface::close().
*
* @throws Exception
* @throws \Exception
* If the stream is not open.
*/
public function close() {
if ($this->_fd) {
fclose($this->_fd);
if ($this->fd) {
fclose($this->fd);
}
else {
throw new Exception('Cannot close stream that is not open.');
throw new \Exception('Cannot close stream that is not open.');
}
}
@ -100,13 +107,13 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
* Piece of string to write to the stream. If the value is not directly a
* string, casting will happen in writing.
*
* @throws Exception
* @throws \Exception
* If writing the data is not possible.
*/
private function write($data) {
$result = fputs($this->_fd, $data);
if ($result === FALSE) {
throw new Exception('Unable to write data: ' . substr($data, 0, 20));
$result = fwrite($this->fd, $data);
if ($result === FALSE || $result != strlen($data)) {
throw new \Exception('Unable to write data: ' . substr($data, 0, 20));
}
}
@ -114,7 +121,7 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
* Write the PO header to the stream.
*/
private function writeHeader() {
$this->write($this->_header);
$this->write($this->header);
}
/**
@ -137,21 +144,21 @@ class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
/**
* Implements Drupal\Component\Gettext\PoStreamInterface::getURI().
*
* @throws Exception
* @throws \Exception
* If the URI is not set.
*/
public function getURI() {
if (empty($this->_uri)) {
throw new Exception('No URI set.');
if (empty($this->uri)) {
throw new \Exception('No URI set.');
}
return $this->_uri;
return $this->uri;
}
/**
* {@inheritdoc}
*/
public function setURI($uri) {
$this->_uri = $uri;
$this->uri = $uri;
}
}

View file

@ -2,7 +2,7 @@
"name": "drupal/core-gettext",
"description": "PHP library for reading PO files.",
"type": "library",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"support": {
"issues": "https://www.drupal.org/project/issues/drupal",
"irc": "irc://irc.freenode.net/drupal-contribute",
@ -10,7 +10,7 @@
},
"require": {
"php": ">=5.5.9",
"drupal/core-utility": "~8.2"
"drupal/core-utility": "^8.2"
},
"autoload": {
"psr-4": {

View file

@ -3,7 +3,7 @@
"description": "Graph.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
},

View file

@ -2,7 +2,7 @@
namespace Drupal\Component\HttpFoundation;
use \Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Provides a common base class for safe redirects.
@ -36,7 +36,7 @@ abstract class SecuredRedirectResponse extends RedirectResponse {
* Copies over the values from the given response.
*
* @param \Symfony\Component\HttpFoundation\RedirectResponse $response
* The redirect reponse object.
* The redirect response object.
*/
protected function fromResponse(RedirectResponse $response) {
$this->setProtocolVersion($response->getProtocolVersion());

View file

@ -3,10 +3,10 @@
"description": "HttpFoundation.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"symfony/http-foundation": "~2.7"
"symfony/http-foundation": ">=2.7 <4.0.0"
},
"autoload": {
"psr-4": {

View file

@ -95,6 +95,7 @@ EOF;
<IfModule !mod_authz_core.c>
Deny from all
</IfModule>
$lines
EOF;
}
@ -138,34 +139,42 @@ EOF;
* The directory path.
* @param int $mode
* The mode, permissions, the directory should have.
* @param bool $is_backwards_recursive
* Internal use only.
*
* @return bool
* TRUE if the directory exists or has been created, FALSE otherwise.
*/
protected function createDirectory($directory, $mode = 0777, $is_backwards_recursive = FALSE) {
protected function createDirectory($directory, $mode = 0777) {
// If the directory exists already, there's nothing to do.
if (is_dir($directory)) {
return TRUE;
}
// Otherwise, try to create the directory and ensure to set its permissions,
// because mkdir() obeys the umask of the current process.
if (is_dir($parent = dirname($directory))) {
// If the parent directory exists, then the backwards recursion must end,
// regardless of whether the subdirectory could be created.
if ($status = mkdir($directory)) {
// Only try to chmod() if the subdirectory could be created.
$status = chmod($directory, $mode);
}
return $is_backwards_recursive ? TRUE : $status;
// If the parent directory doesn't exist, try to create it.
$parent_exists = is_dir($parent = dirname($directory));
if (!$parent_exists) {
$parent_exists = $this->createDirectory($parent, $mode);
}
// If the parent directory and the requested directory does not exist and
// could not be created above, walk the requested directory path back up
// until an existing directory is hit, and from there, recursively create
// the sub-directories. Only if that recursion succeeds, create the final,
// originally requested subdirectory.
return $this->createDirectory($parent, $mode, TRUE) && mkdir($directory) && chmod($directory, $mode);
// If parent exists, try to create the directory and ensure to set its
// permissions, because mkdir() obeys the umask of the current process.
if ($parent_exists) {
// We hide warnings and ignore the return because there may have been a
// race getting here and the directory could already exist.
@mkdir($directory);
// Only try to chmod() if the subdirectory could be created.
if (is_dir($directory)) {
// Avoid writing permissions if possible.
if (fileperms($directory) !== $mode) {
return chmod($directory, $mode);
}
return TRUE;
}
else {
// Something failed and the directory doesn't exist.
trigger_error('mkdir(): Permission Denied', E_USER_WARNING);
}
}
return FALSE;
}
/**

View file

@ -44,7 +44,7 @@ interface PhpStorageInterface {
* @param string $name
* The virtual file name. Can be a relative path.
* @param string $code
* The PHP code to be saved.
* The PHP code to be saved.
*
* @return bool
* TRUE if the save succeeded, FALSE if it failed.

View file

@ -3,7 +3,7 @@
"description": "PhpStorage.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
},

View file

@ -2,7 +2,7 @@
namespace Drupal\Component\Plugin;
use \Drupal\Component\Plugin\Context\ContextInterface;
use Drupal\Component\Plugin\Context\ContextInterface;
/**
* Interface for defining context aware plugins.

View file

@ -0,0 +1,71 @@
<?php
namespace Drupal\Component\Plugin\Definition;
use Drupal\Component\Plugin\Context\ContextDefinitionInterface;
/**
* Provides an interface for plugin definitions which use contexts.
*
* @ingroup Plugin
*/
interface ContextAwarePluginDefinitionInterface extends PluginDefinitionInterface {
/**
* Checks if the plugin defines a particular context.
*
* @param string $name
* The context name.
*
* @return bool
* TRUE if the plugin defines the given context, otherwise FALSE.
*/
public function hasContextDefinition($name);
/**
* Returns all context definitions for this plugin.
*
* @return \Drupal\Component\Plugin\Context\ContextDefinitionInterface[]
* The context definitions.
*/
public function getContextDefinitions();
/**
* Returns a particular context definition for this plugin.
*
* @param string $name
* The context name.
*
* @return \Drupal\Component\Plugin\Context\ContextDefinitionInterface
* The context definition.
*
* @throws \Drupal\Component\Plugin\Exception\ContextException
* Thrown if the plugin does not define the given context.
*/
public function getContextDefinition($name);
/**
* Adds a context to this plugin definition.
*
* @param string $name
* The context name.
* @param \Drupal\Component\Plugin\Context\ContextDefinitionInterface $definition
* The context definition.
*
* @return $this
* The called object.
*/
public function addContextDefinition($name, ContextDefinitionInterface $definition);
/**
* Removes a context definition from this plugin.
*
* @param string $name
* The context name.
*
* @return $this
* The called object.
*/
public function removeContextDefinition($name);
}

View file

@ -0,0 +1,60 @@
<?php
namespace Drupal\Component\Plugin\Definition;
use Drupal\Component\Plugin\Context\ContextDefinitionInterface;
use Drupal\Component\Plugin\Exception\ContextException;
/**
* Provides a trait for context-aware object-based plugin definitions.
*/
trait ContextAwarePluginDefinitionTrait {
/**
* The context definitions for this plugin definition.
*
* @var \Drupal\Component\Plugin\Context\ContextDefinitionInterface[]
*/
protected $contextDefinitions = [];
/**
* Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::hasContextDefinition().
*/
public function hasContextDefinition($name) {
return array_key_exists($name, $this->contextDefinitions);
}
/**
* Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::getContextDefinitions().
*/
public function getContextDefinitions() {
return $this->contextDefinitions;
}
/**
* Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::getContextDefinition().
*/
public function getContextDefinition($name) {
if ($this->hasContextDefinition($name)) {
return $this->contextDefinitions[$name];
}
throw new ContextException($this->id() . " does not define a '$name' context");
}
/**
* Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::addContextDefinition().
*/
public function addContextDefinition($name, ContextDefinitionInterface $definition) {
$this->contextDefinitions[$name] = $definition;
return $this;
}
/**
* Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::removeContextDefinition().
*/
public function removeContextDefinition($name) {
unset($this->contextDefinitions[$name]);
return $this;
}
}

View file

@ -33,6 +33,8 @@ interface DiscoveryInterface {
* @return mixed[]
* An array of plugin definitions (empty array if no definitions were
* found). Keys are plugin IDs.
*
* @see \Drupal\Core\Plugin\FilteredPluginManagerInterface::getFilteredDefinitions()
*/
public function getDefinitions();

View file

@ -5,4 +5,4 @@ namespace Drupal\Component\Plugin\Exception;
/**
* An exception class to be thrown for context plugin exceptions.
*/
class ContextException extends \Exception implements ExceptionInterface { }
class ContextException extends \Exception implements ExceptionInterface {}

View file

@ -5,4 +5,4 @@ namespace Drupal\Component\Plugin\Exception;
/**
* Exception interface for all exceptions thrown by the Plugin component.
*/
interface ExceptionInterface { }
interface ExceptionInterface {}

View file

@ -2,10 +2,10 @@
namespace Drupal\Component\Plugin\Exception;
use \BadMethodCallException;
use BadMethodCallException;
/**
* Exception thrown when a decorator's _call() method is triggered, but the
* decorated object does not contain the requested method.
*/
class InvalidDecoratedMethod extends BadMethodCallException implements ExceptionInterface { }
class InvalidDecoratedMethod extends BadMethodCallException implements ExceptionInterface {}

View file

@ -5,4 +5,4 @@ namespace Drupal\Component\Plugin\Exception;
/**
* Exception to be thrown if a plugin tries to use an invalid deriver.
*/
class InvalidDeriverException extends PluginException { }
class InvalidDeriverException extends PluginException {}

View file

@ -8,4 +8,4 @@ namespace Drupal\Component\Plugin\Exception;
* Extended interface for exceptions thrown specifically by the Mapper subsystem
* within the Plugin component.
*/
interface MapperExceptionInterface extends ExceptionInterface { }
interface MapperExceptionInterface extends ExceptionInterface {}

View file

@ -0,0 +1,21 @@
<?php
namespace Drupal\Component\Plugin\Exception;
/**
* An exception class thrown when contexts exist but are missing a value.
*/
class MissingValueContextException extends ContextException {
/**
* MissingValueContextException constructor.
*
* @param string[] $contexts_without_value
* List of contexts with missing value.
*/
public function __construct(array $contexts_without_value = []) {
$message = 'Required contexts without a value: ' . implode(', ', $contexts_without_value);
parent::__construct($message);
}
}

View file

@ -6,4 +6,4 @@ namespace Drupal\Component\Plugin\Exception;
* Generic Plugin exception class to be thrown when no more specific class
* is applicable.
*/
class PluginException extends \Exception implements ExceptionInterface { }
class PluginException extends \Exception implements ExceptionInterface {}

View file

@ -63,7 +63,7 @@ class DefaultFactory implements FactoryInterface {
* @param \Drupal\Component\Plugin\Definition\PluginDefinitionInterface|mixed[] $plugin_definition
* The plugin definition associated with the plugin ID.
* @param string $required_interface
* (optional) THe required plugin interface.
* (optional) The required plugin interface.
*
* @return string
* The appropriate class name.

View file

@ -22,7 +22,7 @@ interface MapperInterface {
*
* @return object|false
* A fully configured plugin instance. The interface of the plugin instance
* will depends on the plugin type. If no instance can be retrieved, FALSE
* will depend on the plugin type. If no instance can be retrieved, FALSE
* will be returned.
*/
public function getInstance(array $options);

View file

@ -41,7 +41,7 @@ abstract class PluginBase implements PluginInspectionInterface, DerivativeInspec
protected $configuration;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
* Constructs a \Drupal\Component\Plugin\PluginBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.

View file

@ -29,7 +29,7 @@ abstract class PluginManagerBase implements PluginManagerInterface {
/**
* The object that returns the preconfigured plugin instance appropriate for a particular runtime condition.
*
* @var \Drupal\Component\Plugin\Mapper\MapperInterface
* @var \Drupal\Component\Plugin\Mapper\MapperInterface|null
*/
protected $mapper;
@ -76,8 +76,7 @@ abstract class PluginManagerBase implements PluginManagerInterface {
return $this->getFactory()->createInstance($plugin_id, $configuration);
}
catch (PluginNotFoundException $e) {
$fallback_id = $this->getFallbackPluginId($plugin_id, $configuration);
return $this->getFactory()->createInstance($fallback_id, $configuration);
return $this->handlePluginNotFound($plugin_id, $configuration);
}
}
else {
@ -85,10 +84,29 @@ abstract class PluginManagerBase implements PluginManagerInterface {
}
}
/**
* Allows plugin managers to specify custom behavior if a plugin is not found.
*
* @param string $plugin_id
* The ID of the missing requested plugin.
* @param array $configuration
* An array of configuration relevant to the plugin instance.
*
* @return object
* A fallback plugin instance.
*/
protected function handlePluginNotFound($plugin_id, array $configuration) {
$fallback_id = $this->getFallbackPluginId($plugin_id, $configuration);
return $this->getFactory()->createInstance($fallback_id, $configuration);
}
/**
* {@inheritdoc}
*/
public function getInstance(array $options) {
if (!$this->mapper) {
throw new \BadMethodCallException(sprintf('%s does not support this method unless %s::$mapper is set.', static::class, static::class));
}
return $this->mapper->getInstance($options);
}

View file

@ -3,10 +3,10 @@
"description": "Base building block for a scalable and extensible plug-in system for PHP components and application framework extensions.",
"keywords": ["drupal", "plugin", "plugins"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"symfony/validator": "~2.7"
"symfony/validator": ">=2.7 <4.0.0"
},
"autoload": {
"psr-4": {

View file

@ -3,7 +3,7 @@
"description": "Provides a lightweight mechanism to provide lazy loaded proxies.",
"keywords": ["drupal", "proxy"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
},

View file

@ -3,7 +3,6 @@
namespace Drupal\Component\Render;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\UrlHelper;
/**
@ -61,6 +60,13 @@ use Drupal\Component\Utility\UrlHelper;
*/
class FormattableMarkup implements MarkupInterface, \Countable {
/**
* The string containing placeholders.
*
* @var string
*/
protected $string;
/**
* The arguments to replace placeholders with.
*
@ -100,7 +106,7 @@ class FormattableMarkup implements MarkupInterface, \Countable {
* The length of the string.
*/
public function count() {
return Unicode::strlen($this->string);
return mb_strlen($this->string);
}
/**

View file

@ -3,7 +3,6 @@
namespace Drupal\Component\Render;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
/**
* Escapes HTML syntax characters to HTML entities for display in markup.
@ -43,7 +42,7 @@ class HtmlEscapedText implements MarkupInterface, \Countable {
* {@inheritdoc}
*/
public function count() {
return Unicode::strlen($this->string);
return mb_strlen($this->string);
}
/**

View file

@ -2,8 +2,6 @@
namespace Drupal\Component\Render;
use Drupal\Component\Utility\Unicode;
/**
* Implements MarkupInterface and Countable for rendered objects.
*
@ -61,7 +59,7 @@ trait MarkupTrait {
* The length of the string.
*/
public function count() {
return Unicode::strlen($this->string);
return mb_strlen($this->string);
}
/**

View file

@ -3,10 +3,10 @@
"description": "Renders placeholder variables for HTML and plain-text display.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"drupal/core-utility": "~8.2"
"drupal/core-utility": "^8.2"
},
"autoload": {
"psr-4": {

View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View file

@ -29,6 +29,9 @@ class YamlPecl implements SerializationInterface {
public static function decode($raw) {
static $init;
if (!isset($init)) {
// Decode binary, since Symfony YAML parser encodes binary from 3.1
// onwards.
ini_set('yaml.decode_binary', 1);
// We never want to unserialize !php/object.
ini_set('yaml.decode_php', 0);
$init = TRUE;
@ -44,7 +47,7 @@ class YamlPecl implements SerializationInterface {
// and then restore it after decoding has occurred. This allows us to turn
// parsing errors into a throwable exception.
// @see Drupal\Component\Serialization\Exception\InvalidDataTypeException
// @see http://php.net/manual/en/class.errorexception.php
// @see http://php.net/manual/class.errorexception.php
set_error_handler([__CLASS__, 'errorHandler']);
$ndocs = 0;
$data = yaml_parse($raw, 0, $ndocs, [

View file

@ -5,6 +5,7 @@ namespace Drupal\Component\Serialization;
use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Dumper;
use Symfony\Component\Yaml\Yaml as SymfonyYaml;
/**
* Default serialization for YAML using the Symfony component.
@ -16,9 +17,9 @@ class YamlSymfony implements SerializationInterface {
*/
public static function encode($data) {
try {
$yaml = new Dumper();
$yaml->setIndentation(2);
return $yaml->dump($data, PHP_INT_MAX, 0, TRUE, FALSE);
// Set the indentation to 2 to match Drupal's coding standards.
$yaml = new Dumper(2);
return $yaml->dump($data, PHP_INT_MAX, 0, SymfonyYaml::DUMP_EXCEPTION_ON_INVALID_TYPE);
}
catch (\Exception $e) {
throw new InvalidDataTypeException($e->getMessage(), $e->getCode(), $e);
@ -33,7 +34,7 @@ class YamlSymfony implements SerializationInterface {
$yaml = new Parser();
// Make sure we have a single trailing newline. A very simple config like
// 'foo: bar' with no newline will fail to parse otherwise.
return $yaml->parse($raw, TRUE, FALSE);
return $yaml->parse($raw, SymfonyYaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
}
catch (\Exception $e) {
throw new InvalidDataTypeException($e->getMessage(), $e->getCode(), $e);

View file

@ -3,10 +3,10 @@
"description": "Serialization.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"symfony/yaml": "~2.7"
"symfony/yaml": ">=2.7 <4.0.0"
},
"autoload": {
"psr-4": {

View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View file

@ -2,7 +2,7 @@
"name": "drupal/core-transliteration",
"description": "Transliteration.",
"type": "library",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"support": {
"issues": "https://www.drupal.org/project/issues/drupal",
"irc": "irc://irc.freenode.net/drupal-contribute",

View file

@ -14,11 +14,11 @@ $base = [
0x50 => NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0x60 => '', '', '', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0x70 => NULL, NULL, NULL, NULL, '\'', ',', NULL, NULL, NULL, NULL, 'i', NULL, NULL, NULL, '?', NULL,
0x80 => NULL, NULL, NULL, NULL, '', '', 'A', ':', 'E', 'E', 'I', NULL, 'O', NULL, 'Y', 'O',
0x90 => 'i', 'A', 'B', 'G', 'D', 'E', 'Z', 'E', 'TH', 'I', 'K', 'L', 'M', 'N', 'X', 'O',
0xA0 => 'P', 'R', NULL, 'S', 'T', 'Y', 'PH', 'CH', 'PS', 'O', 'I', 'Y', 'a', 'e', 'e', 'i',
0xB0 => 'y', 'a', 'b', 'g', 'd', 'e', 'z', 'e', 'th', 'i', 'k', 'l', 'm', 'n', 'x', 'o',
0xC0 => 'p', 'r', 's', 's', 't', 'y', 'ph', 'ch', 'ps', 'o', 'i', 'y', 'o', 'y', 'o', NULL,
0x80 => NULL, NULL, NULL, NULL, '', '', 'A', ';', 'E', 'I', 'I', NULL, 'O', NULL, 'U', 'O',
0x90 => 'I', 'A', 'B', 'G', 'D', 'E', 'Z', 'I', 'Th', 'I', 'K', 'L', 'M', 'N', 'X', 'O',
0xA0 => 'P', 'R', NULL, 'S', 'T', 'Y', 'F', 'H', 'Ps', 'O', 'I', 'Y', 'a', 'e', 'i', 'i',
0xB0 => 'y', 'a', 'b', 'g', 'd', 'e', 'z', 'i', 'th', 'i', 'k', 'l', 'm', 'n', 'x', 'o',
0xC0 => 'p', 'r', 's', 's', 't', 'y', 'f', 'h', 'ps', 'o', 'i', 'y', 'o', 'y', 'o', NULL,
0xD0 => 'b', 'th', 'Y', 'Y', 'Y', 'ph', 'p', '&', NULL, NULL, 'St', 'st', 'W', 'w', 'Q', 'q',
0xE0 => 'Sp', 'sp', 'Sh', 'sh', 'F', 'f', 'Kh', 'kh', 'H', 'h', 'G', 'g', 'CH', 'ch', 'Ti', 'ti',
0xF0 => 'k', 'r', 's', 'j', 'TH', 'e', NULL, 'S', 's', 'S', 'S', 's', NULL, NULL, NULL, NULL,

View file

@ -6,12 +6,12 @@
*/
$base = [
0x00 => 'E', 'E', 'D', 'G', 'E', 'Z', 'I', 'I', 'J', 'L', 'N', 'C', 'K', 'I', 'U', 'D',
0x10 => 'A', 'B', 'V', 'G', 'D', 'E', 'Z', 'Z', 'I', 'I', 'K', 'L', 'M', 'N', 'O', 'P',
0x20 => 'R', 'S', 'T', 'U', 'F', 'H', 'C', 'C', 'S', 'S', '', 'Y', '', 'E', 'U', 'A',
0x30 => 'a', 'b', 'v', 'g', 'd', 'e', 'z', 'z', 'i', 'i', 'k', 'l', 'm', 'n', 'o', 'p',
0x40 => 'r', 's', 't', 'u', 'f', 'h', 'c', 'c', 's', 's', '', 'y', '', 'e', 'u', 'a',
0x50 => 'e', 'e', 'd', 'g', 'e', 'z', 'i', 'i', 'j', 'l', 'n', 'c', 'k', 'i', 'u', 'd',
0x00 => 'E', 'YO', 'D', 'G', 'E', 'Z', 'I', 'I', 'J', 'L', 'N', 'C', 'K', 'I', 'U', 'D',
0x10 => 'A', 'B', 'V', 'G', 'D', 'E', 'ZH', 'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P',
0x20 => 'R', 'S', 'T', 'U', 'F', 'KH', 'C', 'CH', 'SH', 'SCH', '', 'Y', '', 'E', 'YU', 'YA',
0x30 => 'a', 'b', 'v', 'g', 'd', 'e', 'zh', 'z', 'i', 'y', 'k', 'l', 'm', 'n', 'o', 'p',
0x40 => 'r', 's', 't', 'u', 'f', 'kh', 'c', 'ch', 'sh', 'sch', '', 'y', '', 'e', 'yu', 'ya',
0x50 => 'e', 'yo', 'd', 'g', 'e', 'z', 'i', 'i', 'j', 'l', 'n', 'c', 'k', 'i', 'u', 'd',
0x60 => 'O', 'o', 'E', 'e', 'Ie', 'ie', 'E', 'e', 'Ie', 'ie', 'O', 'o', 'Io', 'io', 'Ks', 'ks',
0x70 => 'Ps', 'ps', 'F', 'f', 'Y', 'y', 'Y', 'y', 'u', 'u', 'O', 'o', 'O', 'o', 'Ot', 'ot',
0x80 => 'Q', 'q', '*1000*', '', '', '', '', NULL, '*100.000*', '*1.000.000*', NULL, NULL, '"', '"', 'R\'', 'r\'',

View file

@ -23,7 +23,7 @@ class Color {
// Hash prefix is optional.
$hex = ltrim($hex, '#');
// Must be either RGB or RRGGBB.
$length = Unicode::strlen($hex);
$length = mb_strlen($hex);
$valid = $valid && ($length === 3 || $length === 6);
// Must be a valid hex value.
$valid = $valid && ctype_xdigit($hex);
@ -94,4 +94,28 @@ class Color {
return '#' . str_pad(dechex($out), 6, 0, STR_PAD_LEFT);
}
/**
* Normalize the hex color length to 6 characters for comparison.
*
* @param string $hex
* The hex color to normalize.
*
* @return string
* The 6 character hex color.
*/
public static function normalizeHexLength($hex) {
// Ignore '#' prefixes.
$hex = ltrim($hex, '#');
if (strlen($hex) === 3) {
$hex[5] = $hex[2];
$hex[4] = $hex[2];
$hex[3] = $hex[1];
$hex[2] = $hex[1];
$hex[1] = $hex[0];
}
return '#' . $hex;
}
}

View file

@ -71,7 +71,7 @@ class Html {
public static function getClass($class) {
$class = (string) $class;
if (!isset(static::$classes[$class])) {
static::$classes[$class] = static::cleanCssIdentifier(Unicode::strtolower($class));
static::$classes[$class] = static::cleanCssIdentifier(mb_strtolower($class));
}
return static::$classes[$class];
}
@ -79,9 +79,10 @@ class Html {
/**
* Prepares a string for use as a CSS identifier (element, class, or ID name).
*
* http://www.w3.org/TR/CSS21/syndata.html#characters shows the syntax for
* valid CSS identifiers (including element names, classes, and IDs in
* selectors.)
* Link below shows the syntax for valid CSS identifiers (including element
* names, classes, and IDs in selectors).
*
* @see http://www.w3.org/TR/CSS21/syndata.html#characters
*
* @param string $identifier
* The identifier to clean.
@ -124,7 +125,7 @@ class Html {
// Identifiers cannot start with a digit, two hyphens, or a hyphen followed by a digit.
$identifier = preg_replace([
'/^[0-9]/',
'/^(-[0-9])|^(--)/'
'/^(-[0-9])|^(--)/',
], ['_', '__'], $identifier);
return $identifier;
}
@ -215,7 +216,7 @@ class Html {
* @see self::getUniqueId()
*/
public static function getId($id) {
$id = str_replace([' ', '_', '[', ']'], ['-', '-', '-', ''], Unicode::strtolower($id));
$id = str_replace([' ', '_', '[', ']'], ['-', '-', '-', ''], mb_strtolower($id));
// As defined in http://www.w3.org/TR/html4/types.html#type-name, HTML IDs can
// only contain letters, digits ([0-9]), hyphens ("-"), underscores ("_"),
@ -451,9 +452,9 @@ EOD;
* The updated (X)HTML snippet.
*/
public static function transformRootRelativeUrlsToAbsolute($html, $scheme_and_host) {
assert('empty(array_diff(array_keys(parse_url($scheme_and_host)), ["scheme", "host", "port"]))', '$scheme_and_host contains scheme, host and port at most.');
assert('isset(parse_url($scheme_and_host)["scheme"])', '$scheme_and_host is absolute and hence has a scheme.');
assert('isset(parse_url($scheme_and_host)["host"])', '$base_url is absolute and hence has a host.');
assert(empty(array_diff(array_keys(parse_url($scheme_and_host)), ["scheme", "host", "port"])), '$scheme_and_host contains scheme, host and port at most.');
assert(isset(parse_url($scheme_and_host)["scheme"]), '$scheme_and_host is absolute and hence has a scheme.');
assert(isset(parse_url($scheme_and_host)["host"]), '$base_url is absolute and hence has a host.');
$html_dom = Html::load($html);
$xpath = new \DOMXpath($html_dom);

View file

@ -69,7 +69,7 @@ class NestedArray {
public static function &getValue(array &$array, array $parents, &$key_exists = NULL) {
$ref = &$array;
foreach ($parents as $parent) {
if (is_array($ref) && array_key_exists($parent, $ref)) {
if (is_array($ref) && (isset($ref[$parent]) || array_key_exists($parent, $ref))) {
$ref = &$ref[$parent];
}
else {
@ -219,7 +219,7 @@ class NestedArray {
public static function unsetValue(array &$array, array $parents, &$key_existed = NULL) {
$unset_key = array_pop($parents);
$ref = &self::getValue($array, $parents, $key_existed);
if ($key_existed && is_array($ref) && array_key_exists($unset_key, $ref)) {
if ($key_existed && is_array($ref) && (isset($ref[$unset_key]) || array_key_exists($unset_key, $ref))) {
$key_existed = TRUE;
unset($ref[$unset_key]);
}
@ -328,7 +328,7 @@ class NestedArray {
// Renumber integer keys as array_merge_recursive() does unless
// $preserve_integer_keys is set to TRUE. Note that PHP automatically
// converts array keys that are integer strings (e.g., '1') to integers.
if (is_integer($key) && !$preserve_integer_keys) {
if (is_int($key) && !$preserve_integer_keys) {
$result[] = $value;
}
// Recurse when both values are arrays.

View file

@ -50,7 +50,7 @@ class Number {
// can't be represented with single precision floats are acceptable. The
// fractional part of a float has 24 bits. That means remainders smaller than
// $step * 2^-24 are acceptable.
$computed_acceptable_error = (double)($step / pow(2.0, 24));
$computed_acceptable_error = (double) ($step / pow(2.0, 24));
return $computed_acceptable_error >= $remainder || $remainder >= ($step - $computed_acceptable_error);
}

View file

@ -143,7 +143,9 @@ class Random {
$vowels = ["a", "e", "i", "o", "u"];
$cons = ["b", "c", "d", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "u", "v", "w", "tr",
"cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr", "sl", "cl", "sh"];
"cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr",
"sl", "cl", "sh",
];
$num_vowels = count($vowels);
$num_cons = count($cons);
@ -219,7 +221,8 @@ class Random {
"utrum", "uxor", "valde", "valetudo", "validus", "vel", "velit",
"veniam", "venio", "vereor", "vero", "verto", "vicis", "vindico",
"virtus", "voco", "volutpat", "vulpes", "vulputate", "wisi", "ymo",
"zelus"];
"zelus",
];
$dictionary_flipped = array_flip($dictionary);
$greeking = '';
@ -256,7 +259,6 @@ class Random {
return $output;
}
/**
* Create a placeholder image.
*

View file

@ -13,6 +13,8 @@ use Drupal\Component\Render\MarkupInterface;
* @link sanitization sanitization functions @endlink or the @link theme_render theme and render systems @endlink
* so that the output can can be themed, escaped, and altered properly.
*
* @see https://www.drupal.org/node/2549395
*
* @see TwigExtension::escapeFilter()
* @see twig_render_template()
* @see sanitization
@ -34,8 +36,11 @@ class SafeMarkup {
* @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
* Instead, you should just check if a variable is an instance of
* \Drupal\Component\Render\MarkupInterface.
*
* @see https://www.drupal.org/node/2549395
*/
public static function isSafe($string, $strategy = 'html') {
@trigger_error('SafeMarkup::isSafe() is scheduled for removal in Drupal 9.0.0. Instead, you should just check if a variable is an instance of \Drupal\Component\Render\MarkupInterface. See https://www.drupal.org/node/2549395.', E_USER_DEPRECATED);
return $string instanceof MarkupInterface;
}
@ -58,9 +63,11 @@ class SafeMarkup {
* possible, \Drupal\Component\Utility\Html::escape() can be used in places
* where explicit escaping is needed.
*
* @see https://www.drupal.org/node/2549395
* @see drupal_validate_utf8()
*/
public static function checkPlain($text) {
@trigger_error('SafeMarkup::checkPlain() is scheduled for removal in Drupal 9.0.0. Rely on Twig\'s auto-escaping feature, or use the @link theme_render #plain_text @endlink key when constructing a render array that contains plain text in order to use the renderer\'s auto-escaping feature. If neither of these are possible, \Drupal\Component\Utility\Html::escape() can be used in places where explicit escaping is needed. See https://www.drupal.org/node/2549395.', E_USER_DEPRECATED);
return new HtmlEscapedText($text);
}
@ -84,8 +91,11 @@ class SafeMarkup {
*
* @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
* Use \Drupal\Component\Render\FormattableMarkup.
*
* @see https://www.drupal.org/node/2549395
*/
public static function format($string, array $args) {
@trigger_error('SafeMarkup::format() is scheduled for removal in Drupal 9.0.0. Use \Drupal\Component\Render\FormattableMarkup. See https://www.drupal.org/node/2549395.', E_USER_DEPRECATED);
return new FormattableMarkup($string, $args);
}

View file

@ -20,7 +20,7 @@ class Timer {
* @param $name
* The name of the timer.
*/
static public function start($name) {
public static function start($name) {
static::$timers[$name]['start'] = microtime(TRUE);
static::$timers[$name]['count'] = isset(static::$timers[$name]['count']) ? ++static::$timers[$name]['count'] : 1;
}
@ -34,7 +34,7 @@ class Timer {
* @return int
* The current timer value in ms.
*/
static public function read($name) {
public static function read($name) {
if (isset(static::$timers[$name]['start'])) {
$stop = microtime(TRUE);
$diff = round(($stop - static::$timers[$name]['start']) * 1000, 2);
@ -57,7 +57,7 @@ class Timer {
* A timer array. The array contains the number of times the timer has been
* started and stopped (count) and the accumulated timer value in ms (time).
*/
static public function stop($name) {
public static function stop($name) {
if (isset(static::$timers[$name]['start'])) {
$stop = microtime(TRUE);
$diff = round(($stop - static::$timers[$name]['start']) * 1000, 2);

View file

@ -87,13 +87,6 @@ EOD;
*/
const STATUS_ERROR = -1;
/**
* Holds the multibyte capabilities of the current environment.
*
* @var int
*/
protected static $status = 0;
/**
* Gets the current status of unicode/multibyte support on this environment.
*
@ -107,7 +100,13 @@ EOD;
* An error occurred. No unicode support.
*/
public static function getStatus() {
return static::$status;
switch (static::check()) {
case 'mb_strlen':
return Unicode::STATUS_SINGLEBYTE;
case '':
return Unicode::STATUS_MULTIBYTE;
}
return Unicode::STATUS_ERROR;
}
/**
@ -123,12 +122,16 @@ EOD;
*
* @param int $status
* The new status of multibyte support.
*
* @deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In
* Drupal 9 there will be no way to set the status and in Drupal 8 this
* ability has been removed because mb_*() functions are supplied using
* Symfony's polyfill.
*
* @see https://www.drupal.org/node/2850048
*/
public static function setStatus($status) {
if (!in_array($status, [static::STATUS_SINGLEBYTE, static::STATUS_MULTIBYTE, static::STATUS_ERROR])) {
throw new \InvalidArgumentException('Invalid status value for unicode support.');
}
static::$status = $status;
@trigger_error('\Drupal\Component\Utility\Unicode::setStatus() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In Drupal 9 there will be no way to set the status and in Drupal 8 this ability has been removed because mb_*() functions are supplied using Symfony\'s polyfill. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED);
}
/**
@ -143,38 +146,33 @@ EOD;
* Otherwise, an empty string.
*/
public static function check() {
// Set appropriate configuration.
mb_internal_encoding('utf-8');
mb_language('uni');
// Check for mbstring extension.
if (!function_exists('mb_strlen')) {
static::$status = static::STATUS_SINGLEBYTE;
if (!extension_loaded('mbstring')) {
return 'mb_strlen';
}
// Check mbstring configuration.
if (ini_get('mbstring.func_overload') != 0) {
static::$status = static::STATUS_ERROR;
return 'mbstring.func_overload';
}
if (ini_get('mbstring.encoding_translation') != 0) {
static::$status = static::STATUS_ERROR;
return 'mbstring.encoding_translation';
}
// mbstring.http_input and mbstring.http_output are deprecated and empty by
// default in PHP 5.6.
if (version_compare(PHP_VERSION, '5.6.0') == -1) {
if (ini_get('mbstring.http_input') != 'pass') {
static::$status = static::STATUS_ERROR;
return 'mbstring.http_input';
}
if (ini_get('mbstring.http_output') != 'pass') {
static::$status = static::STATUS_ERROR;
return 'mbstring.http_output';
}
}
// Set appropriate configuration.
mb_internal_encoding('utf-8');
mb_language('uni');
static::$status = static::STATUS_MULTIBYTE;
return '';
}
@ -224,17 +222,7 @@ EOD;
* Converted data or FALSE.
*/
public static function convertToUtf8($data, $encoding) {
if (function_exists('iconv')) {
return @iconv($encoding, 'utf-8', $data);
}
elseif (function_exists('mb_convert_encoding')) {
return @mb_convert_encoding($data, 'utf-8', $encoding);
}
elseif (function_exists('recode_string')) {
return @recode_string($encoding . '..utf-8', $data);
}
// Cannot convert.
return FALSE;
return @iconv($encoding, 'utf-8', $data);
}
/**
@ -264,7 +252,9 @@ EOD;
return substr($string, 0, $len);
}
// Scan backwards to beginning of the byte sequence.
while (--$len >= 0 && ord($string[$len]) >= 0x80 && ord($string[$len]) < 0xC0);
// @todo Make the code more readable in https://www.drupal.org/node/2911497.
while (--$len >= 0 && ord($string[$len]) >= 0x80 && ord($string[$len]) < 0xC0) {
}
return substr($string, 0, $len);
}
@ -279,15 +269,15 @@ EOD;
*
* @return int
* The length of the string.
*
* @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use
* mb_strlen() instead.
*
* @see https://www.drupal.org/node/2850048
*/
public static function strlen($text) {
if (static::getStatus() == static::STATUS_MULTIBYTE) {
return mb_strlen($text);
}
else {
// Do not count UTF-8 continuation bytes.
return strlen(preg_replace("/[\x80-\xBF]/", '', $text));
}
@trigger_error('\Drupal\Component\Utility\Unicode::strlen() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strlen() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED);
return mb_strlen($text);
}
/**
@ -298,18 +288,15 @@ EOD;
*
* @return string
* The string in uppercase.
*
* @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use
* mb_strtoupper() instead.
*
* @see https://www.drupal.org/node/2850048
*/
public static function strtoupper($text) {
if (static::getStatus() == static::STATUS_MULTIBYTE) {
return mb_strtoupper($text);
}
else {
// Use C-locale for ASCII-only uppercase.
$text = strtoupper($text);
// Case flip Latin-1 accented letters.
$text = preg_replace_callback('/\xC3[\xA0-\xB6\xB8-\xBE]/', '\Drupal\Component\Utility\Unicode::caseFlip', $text);
return $text;
}
@trigger_error('\Drupal\Component\Utility\Unicode::strtoupper() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strtoupper() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED);
return mb_strtoupper($text);
}
/**
@ -320,18 +307,15 @@ EOD;
*
* @return string
* The string in lowercase.
*
* @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use
* mb_strtolower() instead.
*
* @see https://www.drupal.org/node/2850048
*/
public static function strtolower($text) {
if (static::getStatus() == static::STATUS_MULTIBYTE) {
return mb_strtolower($text);
}
else {
// Use C-locale for ASCII-only lowercase.
$text = strtolower($text);
// Case flip Latin-1 accented letters.
$text = preg_replace_callback('/\xC3[\x80-\x96\x98-\x9E]/', '\Drupal\Component\Utility\Unicode::caseFlip', $text);
return $text;
}
@trigger_error('\Drupal\Component\Utility\Unicode::strtolower() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strtolower() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED);
return mb_strtolower($text);
}
/**
@ -344,7 +328,7 @@ EOD;
* The string with the first character as uppercase.
*/
public static function ucfirst($text) {
return static::strtoupper(static::substr($text, 0, 1)) . static::substr($text, 1);
return mb_strtoupper(mb_substr($text, 0, 1)) . mb_substr($text, 1);
}
/**
@ -360,7 +344,7 @@ EOD;
*/
public static function lcfirst($text) {
// Note: no mbstring equivalent!
return static::strtolower(static::substr($text, 0, 1)) . static::substr($text, 1);
return mb_strtolower(mb_substr($text, 0, 1)) . mb_substr($text, 1);
}
/**
@ -376,8 +360,8 @@ EOD;
*/
public static function ucwords($text) {
$regex = '/(^|[' . static::PREG_CLASS_WORD_BOUNDARY . '])([^' . static::PREG_CLASS_WORD_BOUNDARY . '])/u';
return preg_replace_callback($regex, function(array $matches) {
return $matches[1] . Unicode::strtoupper($matches[2]);
return preg_replace_callback($regex, function (array $matches) {
return $matches[1] . mb_strtoupper($matches[2]);
}, $text);
}
@ -397,92 +381,15 @@ EOD;
*
* @return string
* The shortened string.
*
* @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use
* mb_substr() instead.
*
* @see https://www.drupal.org/node/2850048
*/
public static function substr($text, $start, $length = NULL) {
if (static::getStatus() == static::STATUS_MULTIBYTE) {
return $length === NULL ? mb_substr($text, $start) : mb_substr($text, $start, $length);
}
else {
$strlen = strlen($text);
// Find the starting byte offset.
$bytes = 0;
if ($start > 0) {
// Count all the characters except continuation bytes from the start
// until we have found $start characters or the end of the string.
$bytes = -1; $chars = -1;
while ($bytes < $strlen - 1 && $chars < $start) {
$bytes++;
$c = ord($text[$bytes]);
if ($c < 0x80 || $c >= 0xC0) {
$chars++;
}
}
}
elseif ($start < 0) {
// Count all the characters except continuation bytes from the end
// until we have found abs($start) characters.
$start = abs($start);
$bytes = $strlen; $chars = 0;
while ($bytes > 0 && $chars < $start) {
$bytes--;
$c = ord($text[$bytes]);
if ($c < 0x80 || $c >= 0xC0) {
$chars++;
}
}
}
$istart = $bytes;
// Find the ending byte offset.
if ($length === NULL) {
$iend = $strlen;
}
elseif ($length > 0) {
// Count all the characters except continuation bytes from the starting
// index until we have found $length characters or reached the end of
// the string, then backtrace one byte.
$iend = $istart - 1;
$chars = -1;
$last_real = FALSE;
while ($iend < $strlen - 1 && $chars < $length) {
$iend++;
$c = ord($text[$iend]);
$last_real = FALSE;
if ($c < 0x80 || $c >= 0xC0) {
$chars++;
$last_real = TRUE;
}
}
// Backtrace one byte if the last character we found was a real
// character and we don't need it.
if ($last_real && $chars >= $length) {
$iend--;
}
}
elseif ($length < 0) {
// Count all the characters except continuation bytes from the end
// until we have found abs($start) characters, then backtrace one byte.
$length = abs($length);
$iend = $strlen; $chars = 0;
while ($iend > 0 && $chars < $length) {
$iend--;
$c = ord($text[$iend]);
if ($c < 0x80 || $c >= 0xC0) {
$chars++;
}
}
// Backtrace one byte if we are not at the beginning of the string.
if ($iend > 0) {
$iend--;
}
}
else {
// $length == 0, return an empty string.
return '';
}
return substr($text, $istart, max(0, $iend - $istart + 1));
}
@trigger_error('\Drupal\Component\Utility\Unicode::substr() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_substr() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED);
return mb_substr($text, $start, $length);
}
/**
@ -524,15 +431,15 @@ EOD;
$max_length = max($max_length, 0);
$min_wordsafe_length = max($min_wordsafe_length, 0);
if (static::strlen($string) <= $max_length) {
if (mb_strlen($string) <= $max_length) {
// No truncation needed, so don't add ellipsis, just return.
return $string;
}
if ($add_ellipsis) {
// Truncate ellipsis in case $max_length is small.
$ellipsis = static::substr('…', 0, $max_length);
$max_length -= static::strlen($ellipsis);
$ellipsis = mb_substr('…', 0, $max_length);
$max_length -= mb_strlen($ellipsis);
$max_length = max($max_length, 0);
}
@ -546,16 +453,16 @@ EOD;
// Find the last word boundary, if there is one within $min_wordsafe_length
// to $max_length characters. preg_match() is always greedy, so it will
// find the longest string possible.
$found = preg_match('/^(.{' . $min_wordsafe_length . ',' . $max_length . '})[' . Unicode::PREG_CLASS_WORD_BOUNDARY . ']/u', $string, $matches);
$found = preg_match('/^(.{' . $min_wordsafe_length . ',' . $max_length . '})[' . Unicode::PREG_CLASS_WORD_BOUNDARY . ']/us', $string, $matches);
if ($found) {
$string = $matches[1];
}
else {
$string = static::substr($string, 0, $max_length);
$string = mb_substr($string, 0, $max_length);
}
}
else {
$string = static::substr($string, 0, $max_length);
$string = mb_substr($string, 0, $max_length);
}
if ($add_ellipsis) {
@ -580,8 +487,8 @@ EOD;
* Returns < 0 if $str1 is less than $str2; > 0 if $str1 is greater than
* $str2, and 0 if they are equal.
*/
public static function strcasecmp($str1 , $str2) {
return strcmp(static::strtoupper($str1), static::strtoupper($str2));
public static function strcasecmp($str1, $str2) {
return strcmp(mb_strtoupper($str1), mb_strtoupper($str2));
}
/**
@ -601,18 +508,24 @@ EOD;
*
* @param string $string
* The header to encode.
* @param bool $shorten
* If TRUE, only return the first chunk of a multi-chunk encoded string.
*
* @return string
* The mime-encoded header.
*/
public static function mimeHeaderEncode($string) {
public static function mimeHeaderEncode($string, $shorten = FALSE) {
if (preg_match('/[^\x20-\x7E]/', $string)) {
$chunk_size = 47; // floor((75 - strlen("=?UTF-8?B??=")) * 0.75);
// floor((75 - strlen("=?UTF-8?B??=")) * 0.75);
$chunk_size = 47;
$len = strlen($string);
$output = '';
while ($len > 0) {
$chunk = static::truncateBytes($string, $chunk_size);
$output .= ' =?UTF-8?B?' . base64_encode($chunk) . "?=\n";
if ($shorten) {
break;
}
$c = strlen($chunk);
$string = substr($string, $c);
$len -= $c;
@ -707,18 +620,15 @@ EOD;
* The position where $needle occurs in $haystack, always relative to the
* beginning (independent of $offset), or FALSE if not found. Note that
* a return value of 0 is not the same as FALSE.
*
* @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use
* mb_strpos() instead.
*
* @see https://www.drupal.org/node/2850048
*/
public static function strpos($haystack, $needle, $offset = 0) {
if (static::getStatus() == static::STATUS_MULTIBYTE) {
return mb_strpos($haystack, $needle, $offset);
}
else {
// Remove Unicode continuation characters, to be compatible with
// Unicode::strlen() and Unicode::substr().
$haystack = preg_replace("/[\x80-\xBF]/", '', $haystack);
$needle = preg_replace("/[\x80-\xBF]/", '', $needle);
return strpos($haystack, $needle, $offset);
}
@trigger_error('\Drupal\Component\Utility\Unicode::strpos() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strpos() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED);
return mb_strpos($haystack, $needle, $offset);
}
}

View file

@ -19,7 +19,7 @@ class UrlHelper {
/**
* Parses an array into a valid, rawurlencoded query string.
*
* rawurlencode() is RFC3986 compliant, and as a consequence RFC3987
* Function rawurlencode() is RFC3986 compliant, and as a consequence RFC3987
* compliant. The latter defines the required format of "URLs" in HTML5.
* urlencode() is almost the same as rawurlencode(), except that it encodes
* spaces as "+" instead of "%20". This makes its result non compliant to
@ -148,6 +148,11 @@ class UrlHelper {
$scheme_delimiter_position = strpos($url, '://');
$query_delimiter_position = strpos($url, '?');
if ($scheme_delimiter_position !== FALSE && ($query_delimiter_position === FALSE || $scheme_delimiter_position < $query_delimiter_position)) {
// Split off the fragment, if any.
if (strpos($url, '#') !== FALSE) {
list($url, $options['fragment']) = explode('#', $url, 2);
}
// Split off everything before the query string into 'path'.
$parts = explode('?', $url);
@ -158,12 +163,7 @@ class UrlHelper {
}
// If there is a query string, transform it into keyed query parameters.
if (isset($parts[1])) {
$query_parts = explode('#', $parts[1]);
parse_str($query_parts[0], $options['query']);
// Take over the fragment, if there is any.
if (isset($query_parts[1])) {
$options['fragment'] = $query_parts[1];
}
parse_str($parts[1], $options['query']);
}
}
// Internal URLs.
@ -248,6 +248,16 @@ class UrlHelper {
* Exception thrown when a either $url or $bath_url are not fully qualified.
*/
public static function externalIsLocal($url, $base_url) {
// Some browsers treat \ as / so normalize to forward slashes.
$url = str_replace('\\', '/', $url);
// Leading control characters may be ignored or mishandled by browsers, so
// assume such a path may lead to an non-local location. The \p{C} character
// class matches all UTF-8 control, unassigned, and private characters.
if (preg_match('/^\p{C}/u', $url) !== 0) {
return FALSE;
}
$url_parts = parse_url($url);
$base_parts = parse_url($base_url);

View file

@ -3,11 +3,13 @@
"description": "Mostly static utility classes for string, xss, array, image, and other commonly needed manipulations.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9",
"paragonie/random_compat": "^1.0|^2.0",
"drupal/core-render": "~8.2"
"drupal/core-render": "^8.2",
"symfony/polyfill-iconv": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"autoload": {
"psr-4": {

View file

@ -8,6 +8,7 @@ namespace Drupal\Component\Uuid;
* @see http://php.net/com_create_guid
*/
class Com implements UuidInterface {
/**
* {@inheritdoc}
*/

View file

@ -1,8 +1,8 @@
{
"name": "drupal/core-uuid",
"description": "PHP library for reading PO files.",
"description": "UUID generation and validation.",
"type": "library",
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"support": {
"issues": "https://www.drupal.org/project/issues/drupal",
"irc": "irc://irc.freenode.net/drupal-contribute",
@ -10,7 +10,7 @@
},
"require": {
"php": ">=5.5.9",
"drupal/core-utility": "~8.2"
"drupal/core-utility": "^8.2"
},
"autoload": {
"psr-4": {

View file

@ -38,7 +38,7 @@ interface AccessManagerInterface {
/**
* Execute access checks against the incoming request.
*
* @param Request $request
* @param \Symfony\Component\HttpFoundation\Request $request
* The incoming request.
* @param \Drupal\Core\Session\AccountInterface $account
* (optional) Run access checks for this account. Defaults to the current

View file

@ -39,7 +39,7 @@ abstract class AccessResult implements AccessResultInterface, RefinableCacheable
* isNeutral() will be TRUE.
*/
public static function neutral($reason = NULL) {
assert('is_string($reason) || is_null($reason)');
assert(is_string($reason) || is_null($reason));
return new AccessResultNeutral($reason);
}
@ -64,7 +64,7 @@ abstract class AccessResult implements AccessResultInterface, RefinableCacheable
* isForbidden() will be TRUE.
*/
public static function forbidden($reason = NULL) {
assert('is_string($reason) || is_null($reason)');
assert(is_string($reason) || is_null($reason));
return new AccessResultForbidden($reason);
}
@ -87,13 +87,16 @@ abstract class AccessResult implements AccessResultInterface, RefinableCacheable
*
* @param bool $condition
* The condition to evaluate.
* @param string|null $reason
* (optional) The reason why access is forbidden. Intended for developers,
* hence not translatable
*
* @return \Drupal\Core\Access\AccessResult
* If $condition is TRUE, isForbidden() will be TRUE, otherwise isNeutral()
* will be TRUE.
*/
public static function forbiddenIf($condition) {
return $condition ? static::forbidden() : static::neutral();
public static function forbiddenIf($condition, $reason = NULL) {
return $condition ? static::forbidden($reason) : static::neutral();
}
/**
@ -333,10 +336,10 @@ abstract class AccessResult implements AccessResultInterface, RefinableCacheable
$merge_other = TRUE;
}
if ($this->isForbidden() && $this instanceof AccessResultReasonInterface) {
if ($this->isForbidden() && $this instanceof AccessResultReasonInterface && !is_null($this->getReason())) {
$result->setReason($this->getReason());
}
elseif ($other->isForbidden() && $other instanceof AccessResultReasonInterface) {
elseif ($other->isForbidden() && $other instanceof AccessResultReasonInterface && !is_null($other->getReason())) {
$result->setReason($other->getReason());
}
}
@ -350,14 +353,13 @@ abstract class AccessResult implements AccessResultInterface, RefinableCacheable
$result = static::neutral();
if (!$this->isNeutral() || ($this->getCacheMaxAge() === 0 && $other->isNeutral()) || ($this->getCacheMaxAge() !== 0 && $other instanceof CacheableDependencyInterface && $other->getCacheMaxAge() !== 0)) {
$merge_other = TRUE;
if ($other instanceof AccessResultReasonInterface) {
$result->setReason($other->getReason());
}
}
else {
if ($this instanceof AccessResultReasonInterface) {
$result->setReason($this->getReason());
}
if ($this instanceof AccessResultReasonInterface && !is_null($this->getReason())) {
$result->setReason($this->getReason());
}
elseif ($other instanceof AccessResultReasonInterface && !is_null($other->getReason())) {
$result->setReason($other->getReason());
}
}
$result->inheritCacheability($this);
@ -424,9 +426,9 @@ abstract class AccessResult implements AccessResultInterface, RefinableCacheable
/**
* Inherits the cacheability of the other access result, if any.
*
* inheritCacheability() differs from addCacheableDependency() in how it
* handles max-age, because it is designed to inherit the cacheability of the
* second operand in the andIf() and orIf() operations. There, the situation
* This method differs from addCacheableDependency() in how it handles
* max-age, because it is designed to inherit the cacheability of the second
* operand in the andIf() and orIf() operations. There, the situation
* "allowed, max-age=0 OR allowed, max-age=1000" needs to yield max-age 1000
* as the end result.
*

View file

@ -18,13 +18,12 @@ class AccessResultForbidden extends AccessResult implements AccessResultReasonIn
* Constructs a new AccessResultForbidden instance.
*
* @param null|string $reason
* (optional) a message to provide details about this access result
* (optional) A message to provide details about this access result.
*/
public function __construct($reason = NULL) {
$this->reason = $reason;
}
/**
* {@inheritdoc}
*/

View file

@ -18,7 +18,7 @@ class AccessResultNeutral extends AccessResult implements AccessResultReasonInte
* Constructs a new AccessResultNeutral instance.
*
* @param null|string $reason
* (optional) a message to provide details about this access result
* (optional) A message to provide details about this access result
*/
public function __construct($reason = NULL) {
$this->reason = $reason;

View file

@ -142,6 +142,7 @@ class CheckProvider implements CheckProviderInterface, ContainerAwareInterface {
return $checks;
}
/**
* Compiles a mapping of requirement keys to access checker service IDs.
*/

View file

@ -15,7 +15,6 @@ use Symfony\Component\Routing\RouteCollection;
*/
interface CheckProviderInterface {
/**
* For each route, saves a list of applicable access checks to the route.
*

View file

@ -61,7 +61,14 @@ class CustomAccessCheck implements RoutingAccessInterface {
* The access result.
*/
public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) {
$callable = $this->controllerResolver->getControllerFromDefinition($route->getRequirement('_custom_access'));
try {
$callable = $this->controllerResolver->getControllerFromDefinition($route->getRequirement('_custom_access'));
}
catch (\InvalidArgumentException $e) {
// The custom access controller method was not found.
throw new \BadMethodCallException(sprintf('The "%s" method is not callable as a _custom_access callback in route "%s"', $route->getRequirement('_custom_access'), $route->getPath()));
}
$arguments_resolver = $this->argumentsResolverFactory->getArgumentsResolver($route_match, $account);
$arguments = $arguments_resolver->getArguments($callable);

View file

@ -17,7 +17,7 @@ abstract class ConfigurableActionBase extends ActionBase implements Configurable
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->configuration += $this->defaultConfiguration();
$this->setConfiguration($configuration);
}
/**
@ -38,7 +38,7 @@ abstract class ConfigurableActionBase extends ActionBase implements Configurable
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
$this->configuration = $configuration;
$this->configuration = $configuration + $this->defaultConfiguration();
}
/**

View file

@ -0,0 +1,99 @@
<?php
namespace Drupal\Core\Action\Plugin\Action;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Redirects to an entity deletion form.
*
* @Action(
* id = "entity:delete_action",
* action_label = @Translation("Delete"),
* deriver = "Drupal\Core\Action\Plugin\Action\Derivative\EntityDeleteActionDeriver",
* )
*/
class DeleteAction extends EntityActionBase {
/**
* The tempstore object.
*
* @var \Drupal\Core\TempStore\SharedTempStore
*/
protected $tempStore;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a new DeleteAction object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
* @param \Drupal\Core\Session\AccountInterface $current_user
* Current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
$this->currentUser = $current_user;
$this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
$container->get('tempstore.private'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function executeMultiple(array $entities) {
/** @var \Drupal\Core\Entity\EntityInterface[] $entities */
$selection = [];
foreach ($entities as $entity) {
$langcode = $entity->language()->getId();
$selection[$entity->id()][$langcode] = $langcode;
}
$this->tempStore->set($this->currentUser->id() . ':' . $this->getPluginDefinition()['type'], $selection);
}
/**
* {@inheritdoc}
*/
public function execute($object = NULL) {
$this->executeMultiple([$object]);
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
return $object->access('delete', $account, $return_as_object);
}
}

View file

@ -0,0 +1,99 @@
<?php
namespace Drupal\Core\Action\Plugin\Action\Derivative;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a base action for each entity type with specific interfaces.
*/
abstract class EntityActionDeriverBase extends DeriverBase implements ContainerDeriverInterface {
use StringTranslationTrait;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructs a new EntityActionDeriverBase object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) {
$this->entityTypeManager = $entity_type_manager;
$this->stringTranslation = $string_translation;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$container->get('entity_type.manager'),
$container->get('string_translation')
);
}
/**
* Indicates whether the deriver can be used for the provided entity type.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type.
*
* @return bool
* TRUE if the entity type can be used, FALSE otherwise.
*/
abstract protected function isApplicable(EntityTypeInterface $entity_type);
/**
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
if (empty($this->derivatives)) {
$definitions = [];
foreach ($this->getApplicableEntityTypes() as $entity_type_id => $entity_type) {
$definition = $base_plugin_definition;
$definition['type'] = $entity_type_id;
$definition['label'] = sprintf('%s %s', $base_plugin_definition['action_label'], $entity_type->getSingularLabel());
$definitions[$entity_type_id] = $definition;
}
$this->derivatives = $definitions;
}
return parent::getDerivativeDefinitions($base_plugin_definition);
}
/**
* Gets a list of applicable entity types.
*
* The list consists of all entity types which match the conditions for the
* given deriver.
* For example, if the action applies to entities that are publishable,
* this method will find all entity types that are publishable.
*
* @return \Drupal\Core\Entity\EntityTypeInterface[]
* The applicable entity types, keyed by entity type ID.
*/
protected function getApplicableEntityTypes() {
$entity_types = $this->entityTypeManager->getDefinitions();
$entity_types = array_filter($entity_types, function (EntityTypeInterface $entity_type) {
return $this->isApplicable($entity_type);
});
return $entity_types;
}
}

View file

@ -0,0 +1,22 @@
<?php
namespace Drupal\Core\Action\Plugin\Action\Derivative;
use Drupal\Core\Entity\EntityChangedInterface;
use Drupal\Core\Entity\EntityTypeInterface;
/**
* Provides an action deriver that finds entity types of EntityChangedInterface.
*
* @see \Drupal\Core\Action\Plugin\Action\SaveAction
*/
class EntityChangedActionDeriver extends EntityActionDeriverBase {
/**
* {@inheritdoc}
*/
protected function isApplicable(EntityTypeInterface $entity_type) {
return $entity_type->entityClassImplements(EntityChangedInterface::class);
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace Drupal\Core\Action\Plugin\Action\Derivative;
use Drupal\Core\Entity\EntityTypeInterface;
/**
* Provides an action deriver that finds entity types with delete form.
*
* @see \Drupal\Core\Action\Plugin\Action\DeleteAction
*/
class EntityDeleteActionDeriver extends EntityActionDeriverBase {
/**
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
if (empty($this->derivatives)) {
$definitions = [];
foreach ($this->getApplicableEntityTypes() as $entity_type_id => $entity_type) {
$definition = $base_plugin_definition;
$definition['type'] = $entity_type_id;
$definition['label'] = $this->t('Delete @entity_type', ['@entity_type' => $entity_type->getSingularLabel()]);
$definition['confirm_form_route_name'] = 'entity.' . $entity_type->id() . '.delete_multiple_form';
$definitions[$entity_type_id] = $definition;
}
$this->derivatives = $definitions;
}
return $this->derivatives;
}
/**
* {@inheritdoc}
*/
protected function isApplicable(EntityTypeInterface $entity_type) {
return $entity_type->hasLinkTemplate('delete-multiple-form');
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace Drupal\Core\Action\Plugin\Action\Derivative;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\EntityTypeInterface;
/**
* Provides an action deriver that finds publishable entity types.
*
* @see \Drupal\Core\Action\Plugin\Action\PublishAction
* @see \Drupal\Core\Action\Plugin\Action\UnpublishAction
*/
class EntityPublishedActionDeriver extends EntityActionDeriverBase {
/**
* {@inheritdoc}
*/
protected function isApplicable(EntityTypeInterface $entity_type) {
return $entity_type->entityClassImplements(EntityPublishedInterface::class);
}
}

View file

@ -0,0 +1,62 @@
<?php
namespace Drupal\Core\Action\Plugin\Action;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Action\ActionBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Base class for entity-based actions.
*/
abstract class EntityActionBase extends ActionBase implements DependentPluginInterface, ContainerFactoryPluginInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructs a EntityActionBase object.
*
* @param mixed[] $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$module_name = $this->entityTypeManager
->getDefinition($this->getPluginDefinition()['type'])
->getProvider();
return ['module' => [$module_name]];
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace Drupal\Core\Action\Plugin\Action;
use Drupal\Core\Session\AccountInterface;
/**
* Publishes an entity.
*
* @Action(
* id = "entity:publish_action",
* action_label = @Translation("Publish"),
* deriver = "Drupal\Core\Action\Plugin\Action\Derivative\EntityPublishedActionDeriver",
* )
*/
class PublishAction extends EntityActionBase {
/**
* {@inheritdoc}
*/
public function execute($entity = NULL) {
$entity->setPublished()->save();
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
$key = $object->getEntityType()->getKey('published');
/** @var \Drupal\Core\Entity\EntityInterface $object */
$result = $object->access('update', $account, TRUE)
->andIf($object->$key->access('edit', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace Drupal\Core\Action\Plugin\Action;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides an action that can save any entity.
*
* @Action(
* id = "entity:save_action",
* action_label = @Translation("Save"),
* deriver = "Drupal\Core\Action\Plugin\Action\Derivative\EntityChangedActionDeriver",
* )
*/
class SaveAction extends EntityActionBase {
/**
* The time service.
*
* @var \Drupal\Component\Datetime\TimeInterface
*/
protected $time;
/**
* Constructs a SaveAction object.
*
* @param mixed[] $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, TimeInterface $time) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager);
$this->time = $time;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
$container->get('datetime.time')
);
}
/**
* {@inheritdoc}
*/
public function execute($entity = NULL) {
$entity->setChangedTime($this->time->getRequestTime())->save();
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
// It's not necessary to check the changed field access here, because
// Drupal\Core\Field\ChangedFieldItemList would anyway return 'not allowed'.
// Also changing the changed field value is only a workaround to trigger an
// entity resave. Without a field change, this would not be possible.
/** @var \Drupal\Core\Entity\EntityInterface $object */
return $object->access('update', $account, $return_as_object);
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace Drupal\Core\Action\Plugin\Action;
use Drupal\Core\Session\AccountInterface;
/**
* Unpublishes an entity.
*
* @Action(
* id = "entity:unpublish_action",
* action_label = @Translation("Unpublish"),
* deriver = "Drupal\Core\Action\Plugin\Action\Derivative\EntityPublishedActionDeriver",
* )
*/
class UnpublishAction extends EntityActionBase {
/**
* {@inheritdoc}
*/
public function execute($entity = NULL) {
$entity->setUnpublished()->save();
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
$key = $object->getEntityType()->getKey('published');
/** @var \Drupal\Core\Entity\EntityInterface $object */
$result = $object->access('update', $account, TRUE)
->andIf($object->$key->access('edit', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace Drupal\Core\Ajax;
use Drupal\Core\Form\FormStateInterface;
/**
* Provides a helper to for submitting an AJAX form.
*
* @internal
*/
trait AjaxFormHelperTrait {
use AjaxHelperTrait;
/**
* Submit form dialog #ajax callback.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* An AJAX response that display validation error messages or represents a
* successful submission.
*/
public function ajaxSubmit(array &$form, FormStateInterface $form_state) {
if ($form_state->hasAnyErrors()) {
$form['status_messages'] = [
'#type' => 'status_messages',
'#weight' => -1000,
];
$response = new AjaxResponse();
$response->addCommand(new ReplaceCommand('[data-drupal-selector="' . $form['#attributes']['data-drupal-selector'] . '"]', $form));
}
else {
$response = $this->successfulAjaxSubmit($form, $form_state);
}
return $response;
}
/**
* Allows the form to respond to a successful AJAX submission.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* An AJAX response.
*/
abstract protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state);
}

View file

@ -0,0 +1,39 @@
<?php
namespace Drupal\Core\Ajax;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
/**
* Provides a helper to determine if the current request is via AJAX.
*
* @internal
*/
trait AjaxHelperTrait {
/**
* Determines if the current request is via AJAX.
*
* @return bool
* TRUE if the current request is via AJAX, FALSE otherwise.
*/
protected function isAjax() {
foreach (['drupal_ajax', 'drupal_modal', 'drupal_dialog'] as $wrapper) {
if (strpos($this->getRequestWrapperFormat(), $wrapper) !== FALSE) {
return TRUE;
}
}
return FALSE;
}
/**
* Gets the wrapper format of the current request.
*
* @string
* The wrapper format.
*/
protected function getRequestWrapperFormat() {
return \Drupal::request()->get(MainContentViewSubscriber::WRAPPER_FORMAT);
}
}

View file

@ -119,7 +119,7 @@ class OpenDialogCommand implements CommandInterface, CommandWithAttachedAssetsIn
* The new title of the dialog.
*/
public function setDialogTitle($title) {
$this->setDialogOptions('title', $title);
$this->setDialogOption('title', $title);
}
/**

View file

@ -8,6 +8,7 @@ namespace Drupal\Core\Ajax;
* @ingroup ajax
*/
class OpenModalDialogCommand extends OpenDialogCommand {
/**
* Constructs an OpenModalDialog object.
*

Some files were not shown because too many files have changed in this diff Show more