composer update
This commit is contained in:
parent
f6abc3dce2
commit
71dfaca858
1753 changed files with 45274 additions and 14619 deletions
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Component\Plugin;
|
||||
|
||||
use Drupal\Component\Plugin\Context\ContextInterface;
|
||||
use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface;
|
||||
use Drupal\Component\Plugin\Exception\ContextException;
|
||||
use Drupal\Component\Plugin\Context\Context;
|
||||
use Symfony\Component\Validator\ConstraintViolationList;
|
||||
|
@ -67,7 +68,12 @@ abstract class ContextAwarePluginBase extends PluginBase implements ContextAware
|
|||
*/
|
||||
public function getContextDefinitions() {
|
||||
$definition = $this->getPluginDefinition();
|
||||
return !empty($definition['context']) ? $definition['context'] : [];
|
||||
if ($definition instanceof ContextAwarePluginDefinitionInterface) {
|
||||
return $definition->getContextDefinitions();
|
||||
}
|
||||
else {
|
||||
return !empty($definition['context']) ? $definition['context'] : [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,10 +81,15 @@ abstract class ContextAwarePluginBase extends PluginBase implements ContextAware
|
|||
*/
|
||||
public function getContextDefinition($name) {
|
||||
$definition = $this->getPluginDefinition();
|
||||
if (empty($definition['context'][$name])) {
|
||||
throw new ContextException(sprintf("The %s context is not a valid context.", $name));
|
||||
if ($definition instanceof ContextAwarePluginDefinitionInterface) {
|
||||
if ($definition->hasContextDefinition($name)) {
|
||||
return $definition->getContextDefinition($name);
|
||||
}
|
||||
}
|
||||
return $definition['context'][$name];
|
||||
elseif (!empty($definition['context'][$name])) {
|
||||
return $definition['context'][$name];
|
||||
}
|
||||
throw new ContextException(sprintf("The %s context is not a valid context.", $name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -107,6 +107,29 @@ class PhpTransliteration implements TransliterationInterface {
|
|||
public function transliterate($string, $langcode = 'en', $unknown_character = '?', $max_length = NULL) {
|
||||
$result = '';
|
||||
$length = 0;
|
||||
$hash = FALSE;
|
||||
|
||||
// Replace question marks with a unique hash if necessary. This because
|
||||
// mb_convert_encoding() replaces all invalid characters with a question
|
||||
// mark.
|
||||
if ($unknown_character != '?' && strpos($string, '?') !== FALSE) {
|
||||
$hash = hash('sha256', $string);
|
||||
$string = str_replace('?', $hash, $string);
|
||||
}
|
||||
|
||||
// Ensure the string is valid UTF8 for preg_split(). Unknown characters will
|
||||
// be replaced by a question mark.
|
||||
$string = mb_convert_encoding($string, 'UTF-8', 'UTF-8');
|
||||
|
||||
// Use the provided unknown character instead of a question mark.
|
||||
if ($unknown_character != '?') {
|
||||
$string = str_replace('?', $unknown_character, $string);
|
||||
// Restore original question marks if necessary.
|
||||
if ($hash !== FALSE) {
|
||||
$string = str_replace($hash, '?', $string);
|
||||
}
|
||||
}
|
||||
|
||||
// Split into Unicode characters and transliterate each one.
|
||||
foreach (preg_split('//u', $string, 0, PREG_SPLIT_NO_EMPTY) as $character) {
|
||||
$code = self::ordUTF8($character);
|
||||
|
|
67
web/core/lib/Drupal/Component/Utility/Mail.php
Normal file
67
web/core/lib/Drupal/Component/Utility/Mail.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Component\Utility;
|
||||
|
||||
/**
|
||||
* Provides helpers to ensure emails are compliant with RFCs.
|
||||
*
|
||||
* @ingroup utility
|
||||
*/
|
||||
class Mail {
|
||||
|
||||
/**
|
||||
* RFC-2822 "specials" characters.
|
||||
*/
|
||||
const RFC_2822_SPECIALS = '()<>[]:;@\,."';
|
||||
|
||||
/**
|
||||
* Return a RFC-2822 compliant "display-name" component.
|
||||
*
|
||||
* The "display-name" component is used in mail header "Originator" fields
|
||||
* (From, Sender, Reply-to) to give a human-friendly description of the
|
||||
* address, i.e. From: My Display Name <xyz@example.org>. RFC-822 and
|
||||
* RFC-2822 define its syntax and rules. This method gets as input a string
|
||||
* to be used as "display-name" and formats it to be RFC compliant.
|
||||
*
|
||||
* @param string $string
|
||||
* A string to be used as "display-name".
|
||||
*
|
||||
* @return string
|
||||
* A RFC compliant version of the string, ready to be used as
|
||||
* "display-name" in mail originator header fields.
|
||||
*/
|
||||
public static function formatDisplayName($string) {
|
||||
// Make sure we don't process html-encoded characters. They may create
|
||||
// unneeded trouble if left encoded, besides they will be correctly
|
||||
// processed if decoded.
|
||||
$string = Html::decodeEntities($string);
|
||||
|
||||
// If string contains non-ASCII characters it must be (short) encoded
|
||||
// according to RFC-2047. The output of a "B" (Base64) encoded-word is
|
||||
// always safe to be used as display-name.
|
||||
$safe_display_name = Unicode::mimeHeaderEncode($string, TRUE);
|
||||
|
||||
// Encoded-words are always safe to be used as display-name because don't
|
||||
// contain any RFC 2822 "specials" characters. However
|
||||
// Unicode::mimeHeaderEncode() encodes a string only if it contains any
|
||||
// non-ASCII characters, and leaves its value untouched (un-encoded) if
|
||||
// ASCII only. For this reason in order to produce a valid display-name we
|
||||
// still need to make sure there are no "specials" characters left.
|
||||
if (preg_match('/[' . preg_quote(Mail::RFC_2822_SPECIALS) . ']/', $safe_display_name)) {
|
||||
|
||||
// If string is already quoted, it may or may not be escaped properly, so
|
||||
// don't trust it and reset.
|
||||
if (preg_match('/^"(.+)"$/', $safe_display_name, $matches)) {
|
||||
$safe_display_name = str_replace(['\\\\', '\\"'], ['\\', '"'], $matches[1]);
|
||||
}
|
||||
|
||||
// Transform the string in a RFC-2822 "quoted-string" by wrapping it in
|
||||
// double-quotes. Also make sure '"' and '\' occurrences are escaped.
|
||||
$safe_display_name = '"' . str_replace(['\\', '"'], ['\\\\', '\\"'], $safe_display_name) . '"';
|
||||
|
||||
}
|
||||
|
||||
return $safe_display_name;
|
||||
}
|
||||
|
||||
}
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
/**
|
||||
* Note on Drupal 8 porting.
|
||||
* This file origin is Tar.php, release 1.4.0 (stable) with some code
|
||||
* This file origin is Tar.php, release 1.4.5 (stable) with some code
|
||||
* from PEAR.php, release 1.9.5 (stable) both at http://pear.php.net.
|
||||
* To simplify future porting from pear of this file, you should not
|
||||
* do cosmetic or other non significant changes to this file.
|
||||
|
@ -151,6 +151,13 @@ class ArchiveTar
|
|||
*/
|
||||
public $error_object = null;
|
||||
|
||||
/**
|
||||
* Format for data extraction
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $_fmt ='';
|
||||
|
||||
/**
|
||||
* Archive_Tar Class constructor. This flavour of the constructor only
|
||||
* declare a new Archive_Tar object, identifying it by the name of the
|
||||
|
@ -257,6 +264,18 @@ class ArchiveTar
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
|
||||
$this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
|
||||
"a8checksum/a1typeflag/a100link/a6magic/a2version/" .
|
||||
"a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
|
||||
} else {
|
||||
$this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
|
||||
"Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
|
||||
"Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
|
@ -712,7 +731,7 @@ class ArchiveTar
|
|||
}
|
||||
|
||||
// ----- Get the arguments
|
||||
$v_att_list = & func_get_args();
|
||||
$v_att_list = func_get_args();
|
||||
|
||||
// ----- Read the attributes
|
||||
$i = 0;
|
||||
|
@ -1392,10 +1411,20 @@ class ArchiveTar
|
|||
if ($p_stored_filename == '') {
|
||||
$p_stored_filename = $p_filename;
|
||||
}
|
||||
$v_reduce_filename = $this->_pathReduction($p_stored_filename);
|
||||
$v_reduced_filename = $this->_pathReduction($p_stored_filename);
|
||||
|
||||
if (strlen($v_reduce_filename) > 99) {
|
||||
if (!$this->_writeLongHeader($v_reduce_filename)) {
|
||||
if (strlen($v_reduced_filename) > 99) {
|
||||
if (!$this->_writeLongHeader($v_reduced_filename, false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$v_linkname = '';
|
||||
if (@is_link($p_filename)) {
|
||||
$v_linkname = readlink($p_filename);
|
||||
}
|
||||
if (strlen($v_linkname) > 99) {
|
||||
if (!$this->_writeLongHeader($v_linkname, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1404,14 +1433,10 @@ class ArchiveTar
|
|||
$v_uid = sprintf("%07s", DecOct($v_info[4]));
|
||||
$v_gid = sprintf("%07s", DecOct($v_info[5]));
|
||||
$v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
|
||||
|
||||
$v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
|
||||
|
||||
$v_linkname = '';
|
||||
|
||||
if (@is_link($p_filename)) {
|
||||
$v_typeflag = '2';
|
||||
$v_linkname = readlink($p_filename);
|
||||
$v_size = sprintf("%011s", DecOct(0));
|
||||
} elseif (@is_dir($p_filename)) {
|
||||
$v_typeflag = "5";
|
||||
|
@ -1423,7 +1448,6 @@ class ArchiveTar
|
|||
}
|
||||
|
||||
$v_magic = 'ustar ';
|
||||
|
||||
$v_version = ' ';
|
||||
|
||||
if (function_exists('posix_getpwuid')) {
|
||||
|
@ -1438,14 +1462,12 @@ class ArchiveTar
|
|||
}
|
||||
|
||||
$v_devmajor = '';
|
||||
|
||||
$v_devminor = '';
|
||||
|
||||
$v_prefix = '';
|
||||
|
||||
$v_binary_data_first = pack(
|
||||
"a100a8a8a8a12a12",
|
||||
$v_reduce_filename,
|
||||
$v_perms,
|
||||
$v_uid,
|
||||
$v_gid,
|
||||
|
@ -1485,7 +1507,7 @@ class ArchiveTar
|
|||
$this->_writeBlock($v_binary_data_first, 148);
|
||||
|
||||
// ----- Write the calculated checksum
|
||||
$v_checksum = sprintf("%06s ", DecOct($v_checksum));
|
||||
$v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
|
||||
$v_binary_data = pack("a8", $v_checksum);
|
||||
$this->_writeBlock($v_binary_data, 8);
|
||||
|
||||
|
@ -1517,7 +1539,7 @@ class ArchiveTar
|
|||
$p_filename = $this->_pathReduction($p_filename);
|
||||
|
||||
if (strlen($p_filename) > 99) {
|
||||
if (!$this->_writeLongHeader($p_filename)) {
|
||||
if (!$this->_writeLongHeader($p_filename, false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1613,36 +1635,31 @@ class ArchiveTar
|
|||
* @param string $p_filename
|
||||
* @return bool
|
||||
*/
|
||||
public function _writeLongHeader($p_filename)
|
||||
public function _writeLongHeader($p_filename, $is_link = false)
|
||||
{
|
||||
$v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
|
||||
|
||||
$v_typeflag = 'L';
|
||||
|
||||
$v_uid = sprintf("%07s", 0);
|
||||
$v_gid = sprintf("%07s", 0);
|
||||
$v_perms = sprintf("%07s", 0);
|
||||
$v_size = sprintf("%'011s", DecOct(strlen($p_filename)));
|
||||
$v_mtime = sprintf("%011s", 0);
|
||||
$v_typeflag = ($is_link ? 'K' : 'L');
|
||||
$v_linkname = '';
|
||||
|
||||
$v_magic = '';
|
||||
|
||||
$v_version = '';
|
||||
|
||||
$v_magic = 'ustar ';
|
||||
$v_version = ' ';
|
||||
$v_uname = '';
|
||||
|
||||
$v_gname = '';
|
||||
|
||||
$v_devmajor = '';
|
||||
|
||||
$v_devminor = '';
|
||||
|
||||
$v_prefix = '';
|
||||
|
||||
$v_binary_data_first = pack(
|
||||
"a100a8a8a8a12a12",
|
||||
'././@LongLink',
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$v_perms,
|
||||
$v_uid,
|
||||
$v_gid,
|
||||
$v_size,
|
||||
0
|
||||
$v_mtime
|
||||
);
|
||||
$v_binary_data_last = pack(
|
||||
"a1a100a6a2a32a32a8a8a155a12",
|
||||
|
@ -1677,7 +1694,7 @@ class ArchiveTar
|
|||
$this->_writeBlock($v_binary_data_first, 148);
|
||||
|
||||
// ----- Write the calculated checksum
|
||||
$v_checksum = sprintf("%06s ", DecOct($v_checksum));
|
||||
$v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
|
||||
$v_binary_data = pack("a8", $v_checksum);
|
||||
$this->_writeBlock($v_binary_data, 8);
|
||||
|
||||
|
@ -1718,28 +1735,12 @@ class ArchiveTar
|
|||
// ----- Calculate the checksum
|
||||
$v_checksum = 0;
|
||||
// ..... First part of the header
|
||||
for ($i = 0; $i < 148; $i++) {
|
||||
$v_checksum += ord(substr($v_binary_data, $i, 1));
|
||||
}
|
||||
// ..... Ignore the checksum value and replace it by ' ' (space)
|
||||
for ($i = 148; $i < 156; $i++) {
|
||||
$v_checksum += ord(' ');
|
||||
}
|
||||
// ..... Last part of the header
|
||||
for ($i = 156; $i < 512; $i++) {
|
||||
$v_checksum += ord(substr($v_binary_data, $i, 1));
|
||||
}
|
||||
$v_binary_split = str_split($v_binary_data);
|
||||
$v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 0, 148)));
|
||||
$v_checksum += array_sum(array_map('ord', array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',)));
|
||||
$v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 156, 512)));
|
||||
|
||||
if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
|
||||
$fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
|
||||
"a8checksum/a1typeflag/a100link/a6magic/a2version/" .
|
||||
"a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
|
||||
} else {
|
||||
$fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
|
||||
"Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
|
||||
"Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
|
||||
}
|
||||
$v_data = unpack($fmt, $v_binary_data);
|
||||
$v_data = unpack($this->_fmt, $v_binary_data);
|
||||
|
||||
if (strlen($v_data["prefix"]) > 0) {
|
||||
$v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
|
||||
|
@ -1775,7 +1776,7 @@ class ArchiveTar
|
|||
$v_header['mode'] = OctDec(trim($v_data['mode']));
|
||||
$v_header['uid'] = OctDec(trim($v_data['uid']));
|
||||
$v_header['gid'] = OctDec(trim($v_data['gid']));
|
||||
$v_header['size'] = OctDec(trim($v_data['size']));
|
||||
$v_header['size'] = $this->_tarRecToSize($v_data['size']);
|
||||
$v_header['mtime'] = OctDec(trim($v_data['mtime']));
|
||||
if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
|
||||
$v_header['size'] = 0;
|
||||
|
@ -1794,6 +1795,41 @@ class ArchiveTar
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Tar record size to actual size
|
||||
*
|
||||
* @param string $tar_size
|
||||
* @return size of tar record in bytes
|
||||
*/
|
||||
private function _tarRecToSize($tar_size)
|
||||
{
|
||||
/*
|
||||
* First byte of size has a special meaning if bit 7 is set.
|
||||
*
|
||||
* Bit 7 indicates base-256 encoding if set.
|
||||
* Bit 6 is the sign bit.
|
||||
* Bits 5:0 are most significant value bits.
|
||||
*/
|
||||
$ch = ord($tar_size[0]);
|
||||
if ($ch & 0x80) {
|
||||
// Full 12-bytes record is required.
|
||||
$rec_str = $tar_size . "\x00";
|
||||
|
||||
$size = ($ch & 0x40) ? -1 : 0;
|
||||
$size = ($size << 6) | ($ch & 0x3f);
|
||||
|
||||
for ($num_ch = 1; $num_ch < 12; ++$num_ch) {
|
||||
$size = ($size * 256) + ord($rec_str[$num_ch]);
|
||||
}
|
||||
|
||||
return $size;
|
||||
|
||||
} else {
|
||||
return OctDec(trim($tar_size));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detect and report a malicious file name
|
||||
*
|
||||
|
@ -1803,10 +1839,13 @@ class ArchiveTar
|
|||
*/
|
||||
private function _maliciousFilename($file)
|
||||
{
|
||||
if (strpos($file, '/../') !== false) {
|
||||
if (strpos($file, 'phar://') === 0) {
|
||||
return true;
|
||||
}
|
||||
if (strpos($file, '../') === 0) {
|
||||
if (strpos($file, DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) !== false) {
|
||||
return true;
|
||||
}
|
||||
if (strpos($file, '..' . DIRECTORY_SEPARATOR) === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1871,11 +1910,20 @@ class ArchiveTar
|
|||
continue;
|
||||
}
|
||||
|
||||
// ----- Look for long filename
|
||||
if ($v_header['typeflag'] == 'L') {
|
||||
if (!$this->_readLongHeader($v_header)) {
|
||||
return null;
|
||||
}
|
||||
switch ($v_header['typeflag']) {
|
||||
case 'L': {
|
||||
if (!$this->_readLongHeader($v_header)) {
|
||||
return null;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 'K': {
|
||||
$v_link_header = $v_header;
|
||||
if (!$this->_readLongHeader($v_link_header)) {
|
||||
return null;
|
||||
}
|
||||
$v_header['link'] = $v_link_header['filename'];
|
||||
} break;
|
||||
}
|
||||
|
||||
if ($v_header['filename'] == $p_filename) {
|
||||
|
@ -1976,11 +2024,20 @@ class ArchiveTar
|
|||
continue;
|
||||
}
|
||||
|
||||
// ----- Look for long filename
|
||||
if ($v_header['typeflag'] == 'L') {
|
||||
if (!$this->_readLongHeader($v_header)) {
|
||||
return false;
|
||||
}
|
||||
switch ($v_header['typeflag']) {
|
||||
case 'L': {
|
||||
if (!$this->_readLongHeader($v_header)) {
|
||||
return null;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 'K': {
|
||||
$v_link_header = $v_header;
|
||||
if (!$this->_readLongHeader($v_link_header)) {
|
||||
return null;
|
||||
}
|
||||
$v_header['link'] = $v_link_header['filename'];
|
||||
} break;
|
||||
}
|
||||
|
||||
// ignore extended / pax headers
|
||||
|
|
|
@ -11,6 +11,7 @@ use Drupal\Component\Utility\NestedArray;
|
|||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Plugin\PluginWithFormsInterface;
|
||||
use Drupal\Core\Plugin\PluginWithFormsTrait;
|
||||
use Drupal\Core\Render\PreviewFallbackInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Component\Transliteration\TransliterationInterface;
|
||||
|
||||
|
@ -23,7 +24,7 @@ use Drupal\Component\Transliteration\TransliterationInterface;
|
|||
*
|
||||
* @ingroup block_api
|
||||
*/
|
||||
abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface, PluginWithFormsInterface {
|
||||
abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface {
|
||||
|
||||
use ContextAwarePluginAssignmentTrait;
|
||||
use MessengerTrait;
|
||||
|
@ -252,6 +253,13 @@ abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginIn
|
|||
return $transliterated;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPreviewFallbackString() {
|
||||
return $this->t('Placeholder for the "@block" block', ['@block' => $this->label()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the transliteration service.
|
||||
*
|
||||
|
|
|
@ -156,7 +156,8 @@ class MemoryBackend implements CacheBackendInterface, CacheTagsInvalidatorInterf
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function invalidateMultiple(array $cids) {
|
||||
foreach ($cids as $cid) {
|
||||
$items = array_intersect_key($this->cache, array_flip($cids));
|
||||
foreach ($items as $cid => $item) {
|
||||
$this->cache[$cid]->expire = $this->getRequestTime() - 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,12 +162,19 @@ class DbDumpCommand extends DbCommandBase {
|
|||
$definition['fields'][$name]['precision'] = $matches[2];
|
||||
$definition['fields'][$name]['scale'] = $matches[3];
|
||||
}
|
||||
elseif ($type === 'time' || $type === 'datetime') {
|
||||
elseif ($type === 'time') {
|
||||
// @todo Core doesn't support these, but copied from `migrate-db.sh` for now.
|
||||
// Convert to varchar.
|
||||
$definition['fields'][$name]['type'] = 'varchar';
|
||||
$definition['fields'][$name]['length'] = '100';
|
||||
}
|
||||
elseif ($type === 'datetime') {
|
||||
// Adjust for other database types.
|
||||
$definition['fields'][$name]['mysql_type'] = 'datetime';
|
||||
$definition['fields'][$name]['pgsql_type'] = 'timestamp without time zone';
|
||||
$definition['fields'][$name]['sqlite_type'] = 'varchar';
|
||||
$definition['fields'][$name]['sqlsrv_type'] = 'smalldatetime';
|
||||
}
|
||||
elseif (!isset($definition['fields'][$name]['size'])) {
|
||||
// Try use the provided length, if it doesn't exist default to 100. It's
|
||||
// not great but good enough for our dumps at this point.
|
||||
|
|
|
@ -33,7 +33,7 @@ abstract class Tasks {
|
|||
],
|
||||
[
|
||||
'arguments' => [
|
||||
'CREATE TABLE {drupal_install_test} (id int NULL)',
|
||||
'CREATE TABLE {drupal_install_test} (id int NOT NULL PRIMARY KEY)',
|
||||
'Drupal can use CREATE TABLE database commands.',
|
||||
'Failed to <strong>CREATE</strong> a test table on your database server with the command %query. The server reports the following message: %error.<p>Are you sure the configured username has the necessary permissions to create tables in the database?</p>',
|
||||
TRUE,
|
||||
|
|
|
@ -248,18 +248,15 @@ use Drupal\Core\Database\Query\Condition;
|
|||
*
|
||||
* The following keys are defined:
|
||||
* - 'description': A string in non-markup plain text describing this table
|
||||
* and its purpose. References to other tables should be enclosed in
|
||||
* curly-brackets. For example, the node_field_revision table
|
||||
* description field might contain "Stores per-revision title and
|
||||
* body data for each {node}."
|
||||
* and its purpose. References to other tables should be enclosed in curly
|
||||
* brackets.
|
||||
* - 'fields': An associative array ('fieldname' => specification)
|
||||
* that describes the table's database columns. The specification
|
||||
* is also an array. The following specification parameters are defined:
|
||||
* - 'description': A string in non-markup plain text describing this field
|
||||
* and its purpose. References to other tables should be enclosed in
|
||||
* curly-brackets. For example, the node table vid field
|
||||
* description might contain "Always holds the largest (most
|
||||
* recent) {node_field_revision}.vid value for this nid."
|
||||
* and its purpose. References to other tables should be enclosed in curly
|
||||
* brackets. For example, the users_data table 'uid' field description
|
||||
* might contain "The {users}.uid this record affects."
|
||||
* - 'type': The generic datatype: 'char', 'varchar', 'text', 'blob', 'int',
|
||||
* 'float', 'numeric', or 'serial'. Most types just map to the according
|
||||
* database engine specific data types. Use 'serial' for auto incrementing
|
||||
|
@ -322,64 +319,70 @@ use Drupal\Core\Database\Query\Condition;
|
|||
* key column specifiers (see below) that form an index on the
|
||||
* table.
|
||||
*
|
||||
* A key column specifier is either a string naming a column or an
|
||||
* array of two elements, column name and length, specifying a prefix
|
||||
* of the named column.
|
||||
* A key column specifier is either a string naming a column or an array of two
|
||||
* elements, column name and length, specifying a prefix of the named column.
|
||||
*
|
||||
* As an example, here is a SUBSET of the schema definition for
|
||||
* Drupal's 'node' table. It show four fields (nid, vid, type, and
|
||||
* title), the primary key on field 'nid', a unique key named 'vid' on
|
||||
* field 'vid', and two indexes, one named 'nid' on field 'nid' and
|
||||
* one named 'node_title_type' on the field 'title' and the first four
|
||||
* bytes of the field 'type':
|
||||
* As an example, this is the schema definition for the 'users_data' table. It
|
||||
* shows five fields ('uid', 'module', 'name', 'value', and 'serialized'), the
|
||||
* primary key (on the 'uid', 'module', and 'name' fields), and two indexes (the
|
||||
* 'module' index on the 'module' field and the 'name' index on the 'name'
|
||||
* field).
|
||||
*
|
||||
* @code
|
||||
* $schema['node'] = array(
|
||||
* 'description' => 'The base table for nodes.',
|
||||
* 'fields' => array(
|
||||
* 'nid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
|
||||
* 'vid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE,'default' => 0),
|
||||
* 'type' => array('type' => 'varchar','length' => 32,'not null' => TRUE, 'default' => ''),
|
||||
* 'language' => array('type' => 'varchar','length' => 12,'not null' => TRUE,'default' => ''),
|
||||
* 'title' => array('type' => 'varchar','length' => 255,'not null' => TRUE, 'default' => ''),
|
||||
* 'uid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
|
||||
* 'status' => array('type' => 'int', 'not null' => TRUE, 'default' => 1),
|
||||
* 'created' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
|
||||
* 'changed' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
|
||||
* 'comment' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
|
||||
* 'promote' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
|
||||
* 'moderate' => array('type' => 'int', 'not null' => TRUE,'default' => 0),
|
||||
* 'sticky' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
|
||||
* 'translate' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
|
||||
* ),
|
||||
* 'indexes' => array(
|
||||
* 'node_changed' => array('changed'),
|
||||
* 'node_created' => array('created'),
|
||||
* 'node_moderate' => array('moderate'),
|
||||
* 'node_frontpage' => array('promote', 'status', 'sticky', 'created'),
|
||||
* 'node_status_type' => array('status', 'type', 'nid'),
|
||||
* 'node_title_type' => array('title', array('type', 4)),
|
||||
* 'node_type' => array(array('type', 4)),
|
||||
* 'uid' => array('uid'),
|
||||
* 'translate' => array('translate'),
|
||||
* ),
|
||||
* 'unique keys' => array(
|
||||
* 'vid' => array('vid'),
|
||||
* ),
|
||||
* $schema['users_data'] = [
|
||||
* 'description' => 'Stores module data as key/value pairs per user.',
|
||||
* 'fields' => [
|
||||
* 'uid' => [
|
||||
* 'description' => 'The {users}.uid this record affects.',
|
||||
* 'type' => 'int',
|
||||
* 'unsigned' => TRUE,
|
||||
* 'not null' => TRUE,
|
||||
* 'default' => 0,
|
||||
* ],
|
||||
* 'module' => [
|
||||
* 'description' => 'The name of the module declaring the variable.',
|
||||
* 'type' => 'varchar_ascii',
|
||||
* 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH,
|
||||
* 'not null' => TRUE,
|
||||
* 'default' => '',
|
||||
* ],
|
||||
* 'name' => [
|
||||
* 'description' => 'The identifier of the data.',
|
||||
* 'type' => 'varchar_ascii',
|
||||
* 'length' => 128,
|
||||
* 'not null' => TRUE,
|
||||
* 'default' => '',
|
||||
* ],
|
||||
* 'value' => [
|
||||
* 'description' => 'The value.',
|
||||
* 'type' => 'blob',
|
||||
* 'not null' => FALSE,
|
||||
* 'size' => 'big',
|
||||
* ],
|
||||
* 'serialized' => [
|
||||
* 'description' => 'Whether value is serialized.',
|
||||
* 'type' => 'int',
|
||||
* 'size' => 'tiny',
|
||||
* 'unsigned' => TRUE,
|
||||
* 'default' => 0,
|
||||
* ],
|
||||
* ],
|
||||
* 'primary key' => ['uid', 'module', 'name'],
|
||||
* 'indexes' => [
|
||||
* 'module' => ['module'],
|
||||
* 'name' => ['name'],
|
||||
* ],
|
||||
* // For documentation purposes only; foreign keys are not created in the
|
||||
* // database.
|
||||
* 'foreign keys' => array(
|
||||
* 'node_revision' => array(
|
||||
* 'table' => 'node_field_revision',
|
||||
* 'columns' => array('vid' => 'vid'),
|
||||
* ),
|
||||
* 'node_author' => array(
|
||||
* 'foreign keys' => [
|
||||
* 'data_user' => [
|
||||
* 'table' => 'users',
|
||||
* 'columns' => array('uid' => 'uid'),
|
||||
* ),
|
||||
* ),
|
||||
* 'primary key' => array('nid'),
|
||||
* );
|
||||
* 'columns' => [
|
||||
* 'uid' => 'uid',
|
||||
* ],
|
||||
* ],
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
*
|
||||
* @see drupal_install_schema()
|
||||
|
@ -490,60 +493,61 @@ function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $que
|
|||
* @ingroup schemaapi
|
||||
*/
|
||||
function hook_schema() {
|
||||
$schema['node'] = [
|
||||
// Example (partial) specification for table "node".
|
||||
'description' => 'The base table for nodes.',
|
||||
$schema['users_data'] = [
|
||||
'description' => 'Stores module data as key/value pairs per user.',
|
||||
'fields' => [
|
||||
'nid' => [
|
||||
'description' => 'The primary identifier for a node.',
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'vid' => [
|
||||
'description' => 'The current {node_field_revision}.vid version identifier.',
|
||||
'uid' => [
|
||||
'description' => 'The {users}.uid this record affects.',
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
],
|
||||
'type' => [
|
||||
'description' => 'The type of this node.',
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
'module' => [
|
||||
'description' => 'The name of the module declaring the variable.',
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
],
|
||||
'title' => [
|
||||
'description' => 'The node title.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'name' => [
|
||||
'description' => 'The identifier of the data.',
|
||||
'type' => 'varchar_ascii',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
],
|
||||
'value' => [
|
||||
'description' => 'The value.',
|
||||
'type' => 'blob',
|
||||
'not null' => FALSE,
|
||||
'size' => 'big',
|
||||
],
|
||||
'serialized' => [
|
||||
'description' => 'Whether value is serialized.',
|
||||
'type' => 'int',
|
||||
'size' => 'tiny',
|
||||
'unsigned' => TRUE,
|
||||
'default' => 0,
|
||||
],
|
||||
],
|
||||
'primary key' => ['uid', 'module', 'name'],
|
||||
'indexes' => [
|
||||
'node_changed' => ['changed'],
|
||||
'node_created' => ['created'],
|
||||
],
|
||||
'unique keys' => [
|
||||
'nid_vid' => ['nid', 'vid'],
|
||||
'vid' => ['vid'],
|
||||
'module' => ['module'],
|
||||
'name' => ['name'],
|
||||
],
|
||||
// For documentation purposes only; foreign keys are not created in the
|
||||
// database.
|
||||
'foreign keys' => [
|
||||
'node_revision' => [
|
||||
'table' => 'node_field_revision',
|
||||
'columns' => ['vid' => 'vid'],
|
||||
],
|
||||
'node_author' => [
|
||||
'data_user' => [
|
||||
'table' => 'users',
|
||||
'columns' => ['uid' => 'uid'],
|
||||
'columns' => [
|
||||
'uid' => 'uid',
|
||||
],
|
||||
],
|
||||
],
|
||||
'primary key' => ['nid'],
|
||||
];
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ use Drupal\Core\File\MimeType\MimeTypeGuesser;
|
|||
use Drupal\Core\Http\TrustedHostsRequestFactory;
|
||||
use Drupal\Core\Installer\InstallerRedirectTrait;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Security\PharExtensionInterceptor;
|
||||
use Drupal\Core\Security\RequestSanitizer;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\Test\TestDatabase;
|
||||
|
@ -35,6 +36,9 @@ use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
|||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
use Symfony\Component\HttpKernel\TerminableInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use TYPO3\PharStreamWrapper\Manager as PharStreamWrapperManager;
|
||||
use TYPO3\PharStreamWrapper\Behavior as PharStreamWrapperBehavior;
|
||||
use TYPO3\PharStreamWrapper\PharStreamWrapper;
|
||||
|
||||
/**
|
||||
* The DrupalKernel class is the core of Drupal itself.
|
||||
|
@ -471,6 +475,26 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
|||
// Initialize the container.
|
||||
$this->initializeContainer();
|
||||
|
||||
if (in_array('phar', stream_get_wrappers(), TRUE)) {
|
||||
// Set up a stream wrapper to handle insecurities due to PHP's builtin
|
||||
// phar stream wrapper. This is not registered as a regular stream wrapper
|
||||
// to prevent \Drupal\Core\File\FileSystem::validScheme() treating "phar"
|
||||
// as a valid scheme.
|
||||
try {
|
||||
$behavior = new PharStreamWrapperBehavior();
|
||||
PharStreamWrapperManager::initialize(
|
||||
$behavior->withAssertion(new PharExtensionInterceptor())
|
||||
);
|
||||
}
|
||||
catch (\LogicException $e) {
|
||||
// Continue if the PharStreamWrapperManager is already initialized. For
|
||||
// example, this occurs during a module install.
|
||||
// @see \Drupal\Core\Extension\ModuleInstaller::install()
|
||||
};
|
||||
stream_wrapper_unregister('phar');
|
||||
stream_wrapper_register('phar', PharStreamWrapper::class);
|
||||
}
|
||||
|
||||
$this->booted = TRUE;
|
||||
|
||||
return $this;
|
||||
|
|
|
@ -8,6 +8,7 @@ use Drupal\Core\Entity\EntityDisplayPluginCollection;
|
|||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Entity\EntityDisplayBase;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\TypedData\TranslatableInterface as TranslatableDataInterface;
|
||||
|
||||
/**
|
||||
|
@ -269,7 +270,7 @@ class EntityViewDisplay extends EntityDisplayBase implements EntityViewDisplayIn
|
|||
foreach ($entities as $id => $entity) {
|
||||
// Assign the configured weights.
|
||||
foreach ($this->getComponents() as $name => $options) {
|
||||
if (isset($build_list[$id][$name])) {
|
||||
if (isset($build_list[$id][$name]) && !Element::isEmpty($build_list[$id][$name])) {
|
||||
$build_list[$id][$name]['#weight'] = $options['weight'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
namespace Drupal\Core\Entity\Plugin\DataType;
|
||||
|
||||
use Drupal\Core\Config\TypedConfigManagerInterface;
|
||||
use Drupal\Core\TypedData\Exception\MissingDataException;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
|
||||
/**
|
||||
* Enhances EntityAdapter for config entities.
|
||||
|
@ -16,6 +18,13 @@ class ConfigEntityAdapter extends EntityAdapter {
|
|||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* The typed config manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\TypedConfigManagerInterface
|
||||
*/
|
||||
protected $typedConfigManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -68,10 +77,31 @@ class ConfigEntityAdapter extends EntityAdapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the typed data manager.
|
||||
* Gets the typed config manager.
|
||||
*
|
||||
* @return \Drupal\Core\Config\TypedConfigManagerInterface
|
||||
* The typed data manager.
|
||||
* The typed config manager.
|
||||
*/
|
||||
protected function getTypedConfigManager() {
|
||||
if (empty($this->typedConfigManager)) {
|
||||
// Use the typed data manager if it is also the typed config manager.
|
||||
// @todo Remove this in https://www.drupal.org/node/3011137.
|
||||
$typed_data_manager = $this->getTypedDataManager();
|
||||
if ($typed_data_manager instanceof TypedConfigManagerInterface) {
|
||||
$this->typedConfigManager = $typed_data_manager;
|
||||
}
|
||||
else {
|
||||
$this->typedConfigManager = \Drupal::service('config.typed');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->typedConfigManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo Remove this in https://www.drupal.org/node/3011137.
|
||||
*/
|
||||
public function getTypedDataManager() {
|
||||
if (empty($this->typedDataManager)) {
|
||||
|
@ -81,6 +111,19 @@ class ConfigEntityAdapter extends EntityAdapter {
|
|||
return $this->typedDataManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo Remove this in https://www.drupal.org/node/3011137.
|
||||
*/
|
||||
public function setTypedDataManager(TypedDataManagerInterface $typed_data_manager) {
|
||||
$this->typedDataManager = $typed_data_manager;
|
||||
if ($typed_data_manager instanceof TypedConfigManagerInterface) {
|
||||
$this->typedConfigManager = $typed_data_manager;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -97,7 +140,7 @@ class ConfigEntityAdapter extends EntityAdapter {
|
|||
* The typed data.
|
||||
*/
|
||||
protected function getConfigTypedData() {
|
||||
return $this->getTypedDataManager()->createFromNameAndData($this->entity->getConfigDependencyName(), $this->entity->toArray());
|
||||
return $this->getTypedConfigManager()->createFromNameAndData($this->entity->getConfigDependencyName(), $this->entity->toArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -184,6 +184,7 @@ class Tables implements TablesInterface {
|
|||
// finds the property first. The data table is preferred, which is why
|
||||
// it gets added before the base table.
|
||||
$entity_tables = [];
|
||||
$revision_table = NULL;
|
||||
if ($all_revisions && $field_storage && $field_storage->isRevisionable()) {
|
||||
$data_table = $entity_type->getRevisionDataTable();
|
||||
$entity_base_table = $entity_type->getRevisionTable();
|
||||
|
@ -191,11 +192,18 @@ class Tables implements TablesInterface {
|
|||
else {
|
||||
$data_table = $entity_type->getDataTable();
|
||||
$entity_base_table = $entity_type->getBaseTable();
|
||||
|
||||
if ($field_storage && $field_storage->isRevisionable() && in_array($field_storage->getName(), $entity_type->getRevisionMetadataKeys())) {
|
||||
$revision_table = $entity_type->getRevisionTable();
|
||||
}
|
||||
}
|
||||
if ($data_table) {
|
||||
$this->sqlQuery->addMetaData('simple_query', FALSE);
|
||||
$entity_tables[$data_table] = $this->getTableMapping($data_table, $entity_type_id);
|
||||
}
|
||||
if ($revision_table) {
|
||||
$entity_tables[$revision_table] = $this->getTableMapping($revision_table, $entity_type_id);
|
||||
}
|
||||
$entity_tables[$entity_base_table] = $this->getTableMapping($entity_base_table, $entity_type_id);
|
||||
$sql_column = $specifier;
|
||||
|
||||
|
|
|
@ -821,10 +821,13 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
if ($update) {
|
||||
$default_revision = $entity->isDefaultRevision();
|
||||
if ($default_revision) {
|
||||
// Remove the ID from the record to enable updates on SQL variants
|
||||
// that prevent updating serial columns, for example, mssql.
|
||||
unset($record->{$this->idKey});
|
||||
$this->database
|
||||
->update($this->baseTable)
|
||||
->fields((array) $record)
|
||||
->condition($this->idKey, $record->{$this->idKey})
|
||||
->condition($this->idKey, $entity->get($this->idKey)->value)
|
||||
->execute();
|
||||
}
|
||||
if ($this->revisionTable) {
|
||||
|
@ -833,11 +836,15 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
}
|
||||
else {
|
||||
$record = $this->mapToStorageRecord($entity->getUntranslated(), $this->revisionTable);
|
||||
// Remove the revision ID from the record to enable updates on SQL
|
||||
// variants that prevent updating serial columns, for example,
|
||||
// mssql.
|
||||
unset($record->{$this->revisionKey});
|
||||
$entity->preSaveRevision($this, $record);
|
||||
$this->database
|
||||
->update($this->revisionTable)
|
||||
->fields((array) $record)
|
||||
->condition($this->revisionKey, $record->{$this->revisionKey})
|
||||
->condition($this->revisionKey, $entity->getRevisionId())
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
@ -1064,19 +1071,21 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
->condition($this->idKey, $record->{$this->idKey})
|
||||
->execute();
|
||||
}
|
||||
// Make sure to update the new revision key for the entity.
|
||||
$entity->{$this->revisionKey}->value = $record->{$this->revisionKey};
|
||||
}
|
||||
else {
|
||||
// Remove the revision ID from the record to enable updates on SQL
|
||||
// variants that prevent updating serial columns, for example,
|
||||
// mssql.
|
||||
unset($record->{$this->revisionKey});
|
||||
$this->database
|
||||
->update($this->revisionTable)
|
||||
->fields((array) $record)
|
||||
->condition($this->revisionKey, $record->{$this->revisionKey})
|
||||
->condition($this->revisionKey, $entity->getRevisionId())
|
||||
->execute();
|
||||
}
|
||||
|
||||
// Make sure to update the new revision key for the entity.
|
||||
$entity->{$this->revisionKey}->value = $record->{$this->revisionKey};
|
||||
|
||||
return $record->{$this->revisionKey};
|
||||
return $entity->getRevisionId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -811,10 +811,10 @@ function hook_entity_view_mode_info_alter(&$view_modes) {
|
|||
* An associative array of all entity bundles, keyed by the entity
|
||||
* type name, and then the bundle name, with the following keys:
|
||||
* - label: The human-readable name of the bundle.
|
||||
* - uri_callback: The same as the 'uri_callback' key defined for the entity
|
||||
* type in the EntityManager, but for the bundle only. When determining
|
||||
* the URI of an entity, if a 'uri_callback' is defined for both the
|
||||
* entity type and the bundle, the one for the bundle is used.
|
||||
* - uri_callback: (optional) The same as the 'uri_callback' key defined for
|
||||
* the entity type in the EntityManager, but for the bundle only. When
|
||||
* determining the URI of an entity, if a 'uri_callback' is defined for both
|
||||
* the entity type and the bundle, the one for the bundle is used.
|
||||
* - translatable: (optional) A boolean value specifying whether this bundle
|
||||
* has translation support enabled. Defaults to FALSE.
|
||||
*
|
||||
|
|
|
@ -684,6 +684,20 @@ function hook_update_N(&$sandbox) {
|
|||
* Drupal also ensures to not execute the same hook_post_update_NAME() function
|
||||
* twice.
|
||||
*
|
||||
* @section sec_bulk Batch updates
|
||||
* If running your update all at once could possibly cause PHP to time out, use
|
||||
* the $sandbox parameter to indicate that the Batch API should be used for your
|
||||
* update. In this case, your update function acts as an implementation of
|
||||
* callback_batch_operation(), and $sandbox acts as the batch context
|
||||
* parameter. In your function, read the state information from the previous
|
||||
* run from $sandbox (or initialize), run a chunk of updates, save the state in
|
||||
* $sandbox, and set $sandbox['#finished'] to a value between 0 and 1 to
|
||||
* indicate the percent completed, or 1 if it is finished (you need to do this
|
||||
* explicitly in each pass).
|
||||
*
|
||||
* See the @link batch Batch operations topic @endlink for more information on
|
||||
* how to use the Batch API.
|
||||
*
|
||||
* @param array $sandbox
|
||||
* Stores information for batch updates. See above for more information.
|
||||
*
|
||||
|
|
|
@ -124,7 +124,6 @@ class StringFormatter extends FormatterBase implements ContainerFactoryPluginInt
|
|||
$elements = [];
|
||||
$url = NULL;
|
||||
if ($this->getSetting('link_to_entity')) {
|
||||
// For the default revision this falls back to 'canonical'.
|
||||
$url = $this->getEntityUrl($items->getEntity());
|
||||
}
|
||||
|
||||
|
@ -173,8 +172,11 @@ class StringFormatter extends FormatterBase implements ContainerFactoryPluginInt
|
|||
* The URI elements of the entity.
|
||||
*/
|
||||
protected function getEntityUrl(EntityInterface $entity) {
|
||||
// For the default revision this falls back to 'canonical'.
|
||||
return $entity->toUrl('revision');
|
||||
// For the default revision, the 'revision' link template falls back to
|
||||
// 'canonical'.
|
||||
// @see \Drupal\Core\Entity\Entity::toUrl()
|
||||
$rel = $entity->getEntityType()->hasLinkTemplate('revision') ? 'revision' : 'canonical';
|
||||
return $entity->toUrl($rel);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
|
|||
use Drupal\Core\Plugin\Discovery\YamlDiscoveryDecorator;
|
||||
use Drupal\Core\Layout\Annotation\Layout;
|
||||
use Drupal\Core\Plugin\FilteredPluginManagerTrait;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
|
||||
/**
|
||||
* Provides a plugin manager for layouts.
|
||||
|
@ -71,6 +72,10 @@ class LayoutPluginManager extends DefaultPluginManager implements LayoutPluginMa
|
|||
if (!$this->discovery) {
|
||||
$discovery = new AnnotatedClassDiscovery($this->subdir, $this->namespaces, $this->pluginDefinitionAnnotationName, $this->additionalAnnotationNamespaces);
|
||||
$discovery = new YamlDiscoveryDecorator($discovery, 'layouts', $this->moduleHandler->getModuleDirectories() + $this->themeHandler->getThemeDirectories());
|
||||
$discovery
|
||||
->addTranslatableProperty('label')
|
||||
->addTranslatableProperty('description')
|
||||
->addTranslatableProperty('category');
|
||||
$discovery = new AnnotationBridgeDecorator($discovery, $this->pluginDefinitionAnnotationName);
|
||||
$discovery = new ContainerDerivativeDiscoveryDecorator($discovery);
|
||||
$this->discovery = $discovery;
|
||||
|
@ -140,6 +145,15 @@ class LayoutPluginManager extends DefaultPluginManager implements LayoutPluginMa
|
|||
if (!$definition->getDefaultRegion()) {
|
||||
$definition->setDefaultRegion(key($definition->getRegions()));
|
||||
}
|
||||
// Makes sure region names are translatable.
|
||||
$regions = array_map(function ($region) {
|
||||
if (!$region['label'] instanceof TranslatableMarkup) {
|
||||
// Region labels from YAML discovery needs translation.
|
||||
$region['label'] = new TranslatableMarkup($region['label'], [], ['context' => 'layout_region']);
|
||||
}
|
||||
return $region;
|
||||
}, $definition->getRegions());
|
||||
$definition->setRegions($regions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Drupal\Core\Mail;
|
|||
use Drupal\Component\Render\MarkupInterface;
|
||||
use Drupal\Component\Render\PlainTextOutput;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Component\Utility\Mail as MailHelper;
|
||||
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
|
||||
use Drupal\Core\Messenger\MessengerTrait;
|
||||
use Drupal\Core\Plugin\DefaultPluginManager;
|
||||
|
@ -254,12 +254,8 @@ class MailManager extends DefaultPluginManager implements MailManagerInterface {
|
|||
// Return-Path headers should have a domain authorized to use the
|
||||
// originating SMTP server.
|
||||
$headers['Sender'] = $headers['Return-Path'] = $site_mail;
|
||||
// Headers are usually encoded in the mail plugin that implements
|
||||
// \Drupal\Core\Mail\MailInterface::mail(), for example,
|
||||
// \Drupal\Core\Mail\Plugin\Mail\PhpMail::mail(). The site name must be
|
||||
// encoded here to prevent mail plugins from encoding the email address,
|
||||
// which would break the header.
|
||||
$headers['From'] = Unicode::mimeHeaderEncode($site_config->get('name'), TRUE) . ' <' . $site_mail . '>';
|
||||
// Make sure the site-name is a RFC-2822 compliant 'display-name'.
|
||||
$headers['From'] = MailHelper::formatDisplayName($site_config->get('name')) . ' <' . $site_mail . '>';
|
||||
if ($reply) {
|
||||
$headers['Reply-to'] = $reply;
|
||||
}
|
||||
|
|
|
@ -106,11 +106,11 @@ class AliasStorage implements AliasStorageInterface {
|
|||
$this->catchException($e);
|
||||
$original = FALSE;
|
||||
}
|
||||
$fields['pid'] = $pid;
|
||||
$query = $this->connection->update(static::TABLE)
|
||||
->fields($fields)
|
||||
->condition('pid', $pid);
|
||||
$pid = $query->execute();
|
||||
$fields['pid'] = $pid;
|
||||
$fields['original'] = $original;
|
||||
$operation = 'update';
|
||||
}
|
||||
|
|
|
@ -270,7 +270,7 @@ class ContextDefinition implements ContextDefinitionInterface {
|
|||
public function setConstraints(array $constraints) {
|
||||
// If the backwards compatibility layer is present, delegate to that.
|
||||
if ($this->entityContextDefinition) {
|
||||
$this->entityContextDefinition->setConstraint();
|
||||
$this->entityContextDefinition->setConstraints($constraints);
|
||||
}
|
||||
|
||||
$this->constraints = $constraints;
|
||||
|
|
|
@ -48,7 +48,10 @@ trait ContextAwarePluginAssignmentTrait {
|
|||
];
|
||||
}
|
||||
|
||||
if (count($options) > 1 || !$definition->isRequired()) {
|
||||
// Show the context selector only if there is more than 1 option to choose
|
||||
// from. Also, show if there is a single option but the plugin does not
|
||||
// require a context.
|
||||
if (count($options) > 1 || (count($options) == 1 && !$definition->isRequired())) {
|
||||
$assignments = $plugin->getContextMapping();
|
||||
$element[$context_slot] = [
|
||||
'#title' => $definition->getLabel() ?: $this->t('Select a @context value:', ['@context' => $context_slot]),
|
||||
|
|
|
@ -70,7 +70,7 @@ abstract class ContextAwarePluginBase extends ComponentContextAwarePluginBase im
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function setContextValue($name, $value) {
|
||||
$this->context[$name] = Context::createFromContext($this->getContext($name), $value);
|
||||
$this->setContext($name, Context::createFromContext($this->getContext($name), $value));
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class File extends FormElement {
|
|||
*/
|
||||
public static function processFile(&$element, FormStateInterface $form_state, &$complete_form) {
|
||||
if ($element['#multiple']) {
|
||||
$element['#attributes'] = ['multiple' => 'multiple'];
|
||||
$element['#attributes']['multiple'] = 'multiple';
|
||||
$element['#name'] .= '[]';
|
||||
}
|
||||
return $element;
|
||||
|
|
|
@ -76,7 +76,9 @@ class StatusMessages extends RenderElement {
|
|||
public static function renderMessages($type = NULL) {
|
||||
$render = [];
|
||||
if (isset($type)) {
|
||||
$messages = \Drupal::messenger()->deleteByType($type);
|
||||
$messages = [
|
||||
$type => \Drupal::messenger()->deleteByType($type),
|
||||
];
|
||||
}
|
||||
else {
|
||||
$messages = \Drupal::messenger()->deleteAll();
|
||||
|
|
21
web/core/lib/Drupal/Core/Render/PreviewFallbackInterface.php
Normal file
21
web/core/lib/Drupal/Core/Render/PreviewFallbackInterface.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Render;
|
||||
|
||||
/**
|
||||
* Allows an element to provide a fallback representation of itself for preview.
|
||||
*/
|
||||
interface PreviewFallbackInterface {
|
||||
|
||||
/**
|
||||
* Returns a string to be used as a fallback during preview.
|
||||
*
|
||||
* This is typically used when an element has no output and must be displayed,
|
||||
* for example during configuration.
|
||||
*
|
||||
* @return string|\Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* A string representing for this.
|
||||
*/
|
||||
public function getPreviewFallbackString();
|
||||
|
||||
}
|
|
@ -125,6 +125,7 @@ class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterf
|
|||
throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $this->currentPath->getPath()));
|
||||
}
|
||||
$collection = $this->applyRouteFilters($collection, $request);
|
||||
$collection = $this->applyFitOrder($collection);
|
||||
|
||||
if ($ret = $this->matchCollection(rawurldecode($this->currentPath->getPath($request)), $collection)) {
|
||||
return $this->applyRouteEnhancers($ret, $request);
|
||||
|
@ -286,6 +287,44 @@ class Router extends UrlMatcher implements RequestMatcherInterface, RouterInterf
|
|||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reapplies the fit order to a RouteCollection object.
|
||||
*
|
||||
* Route filters can reorder route collections. For example, routes with an
|
||||
* explicit _format requirement will be preferred. This can result in a less
|
||||
* fit route being used. For example, as a result of filtering /user/% comes
|
||||
* before /user/login. In order to not break this fundamental property of
|
||||
* routes, we need to reapply the fit order. We also need to ensure that order
|
||||
* within each group of the same fit is preserved.
|
||||
*
|
||||
* @param \Symfony\Component\Routing\RouteCollection $collection
|
||||
* The route collection.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\RouteCollection
|
||||
* The reordered route collection.
|
||||
*/
|
||||
protected function applyFitOrder(RouteCollection $collection) {
|
||||
$buckets = [];
|
||||
// Sort all the routes by fit descending.
|
||||
foreach ($collection->all() as $name => $route) {
|
||||
$fit = $route->compile()->getFit();
|
||||
$buckets += [$fit => []];
|
||||
$buckets[$fit][] = [$name, $route];
|
||||
}
|
||||
krsort($buckets);
|
||||
|
||||
$flattened = array_reduce($buckets, 'array_merge', []);
|
||||
|
||||
// Add them back onto a new route collection.
|
||||
$collection = new RouteCollection();
|
||||
foreach ($flattened as $pair) {
|
||||
$name = $pair[0];
|
||||
$route = $pair[1];
|
||||
$collection->add($name, $route);
|
||||
}
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Security;
|
||||
|
||||
use TYPO3\PharStreamWrapper\Assertable;
|
||||
use TYPO3\PharStreamWrapper\Helper;
|
||||
use TYPO3\PharStreamWrapper\Exception;
|
||||
|
||||
/**
|
||||
* An alternate PharExtensionInterceptor to support phar-based CLI tools.
|
||||
*
|
||||
* @see \TYPO3\PharStreamWrapper\Interceptor\PharExtensionInterceptor
|
||||
*/
|
||||
class PharExtensionInterceptor implements Assertable {
|
||||
|
||||
/**
|
||||
* Determines whether phar file is allowed to execute.
|
||||
*
|
||||
* The phar file is allowed to execute if:
|
||||
* - the base file name has a ".phar" suffix.
|
||||
* - it is the CLI tool that has invoked the interceptor.
|
||||
*
|
||||
* @param string $path
|
||||
* The path of the phar file to check.
|
||||
* @param string $command
|
||||
* The command being carried out.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the phar file is allowed to execute.
|
||||
*
|
||||
* @throws Exception
|
||||
* Thrown when the file is not allowed to execute.
|
||||
*/
|
||||
public function assert($path, $command) {
|
||||
if ($this->baseFileContainsPharExtension($path)) {
|
||||
return TRUE;
|
||||
}
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Unexpected file extension in "%s"',
|
||||
$path
|
||||
),
|
||||
1535198703
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a path has a .phar extension or invoked execution.
|
||||
*
|
||||
* @param string $path
|
||||
* The path of the phar file to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the file has a .phar extension or if the execution has been
|
||||
* invoked by the phar file.
|
||||
*/
|
||||
private function baseFileContainsPharExtension($path) {
|
||||
$baseFile = Helper::determineBaseFile($path);
|
||||
if ($baseFile === NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
// If the stream wrapper is registered by invoking a phar file that does
|
||||
// not not have .phar extension then this should be allowed. For
|
||||
// example, some CLI tools recommend removing the extension.
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
// Find the last entry in the backtrace containing a 'file' key as
|
||||
// sometimes the last caller is executed outside the scope of a file. For
|
||||
// example, this occurs with shutdown functions.
|
||||
do {
|
||||
$caller = array_pop($backtrace);
|
||||
} while (empty($caller['file']) && !empty($backtrace));
|
||||
if (isset($caller['file']) && $baseFile === Helper::determineBaseFile($caller['file'])) {
|
||||
return TRUE;
|
||||
}
|
||||
$fileExtension = pathinfo($baseFile, PATHINFO_EXTENSION);
|
||||
return strtolower($fileExtension) === 'phar';
|
||||
}
|
||||
|
||||
}
|
|
@ -218,6 +218,11 @@ class SessionManager extends NativeSessionStorage implements SessionManagerInter
|
|||
|
||||
if ($this->isStarted()) {
|
||||
$old_session_id = $this->getId();
|
||||
// Save and close the old session. Call the parent method to avoid issue
|
||||
// with session destruction due to the session being considered obsolete.
|
||||
parent::save();
|
||||
// Ensure the session is reloaded correctly.
|
||||
$this->startedLazy = TRUE;
|
||||
}
|
||||
session_id(Crypt::randomBytesBase64());
|
||||
|
||||
|
@ -230,10 +235,7 @@ class SessionManager extends NativeSessionStorage implements SessionManagerInter
|
|||
$this->migrateStoredSession($old_session_id);
|
||||
}
|
||||
|
||||
if (!$this->isStarted()) {
|
||||
// Start the session when it doesn't exist yet.
|
||||
$this->startNow();
|
||||
}
|
||||
$this->startNow();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\Core\TempStore;
|
||||
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Drupal\Core\Session\AccountProxyInterface;
|
||||
|
@ -27,6 +28,7 @@ use Symfony\Component\HttpFoundation\RequestStack;
|
|||
* \Drupal\Core\TempStore\SharedTempStore.
|
||||
*/
|
||||
class PrivateTempStore {
|
||||
use DependencySerializationTrait;
|
||||
|
||||
/**
|
||||
* The key/value storage object used for this data.
|
||||
|
|
|
@ -126,10 +126,16 @@ class RecursiveContextualValidator implements ContextualValidatorInterface {
|
|||
$metadata = $this->metadataFactory->getMetadataFor($data);
|
||||
$cache_key = spl_object_hash($data);
|
||||
$property_path = $is_root_call ? '' : PropertyPath::append($previous_path, $data->getName());
|
||||
|
||||
// Prefer a specific instance of the typed data manager stored by the data
|
||||
// if it is available. This is necessary for specialized typed data objects,
|
||||
// for example those using the typed config subclass of the manager.
|
||||
$typed_data_manager = method_exists($data, 'getTypedDataManager') ? $data->getTypedDataManager() : $this->typedDataManager;
|
||||
|
||||
// Pass the canonical representation of the data as validated value to
|
||||
// constraint validators, such that they do not have to care about Typed
|
||||
// Data.
|
||||
$value = $this->typedDataManager->getCanonicalRepresentation($data);
|
||||
$value = $typed_data_manager->getCanonicalRepresentation($data);
|
||||
$this->context->setNode($value, $data, $metadata, $property_path);
|
||||
|
||||
if (isset($constraints) || !$this->context->isGroupValidated($cache_key, Constraint::DEFAULT_GROUP)) {
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Drupal\Core\Update;
|
|||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Core\Session\AnonymousUserSession;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\StackMiddleware\ReverseProxyMiddleware;
|
||||
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -59,6 +60,7 @@ class UpdateKernel extends DrupalKernel {
|
|||
|
||||
// First boot up basic things, like loading the include files.
|
||||
$this->initializeSettings($request);
|
||||
ReverseProxyMiddleware::setSettingsOnRequest($request, Settings::getInstance());
|
||||
$this->boot();
|
||||
$container = $this->getContainer();
|
||||
/** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */
|
||||
|
|
Reference in a new issue