update drupal
This commit is contained in:
@@ -624,11 +624,10 @@ class DateTimePlus {
|
||||
$valid_date = FALSE;
|
||||
$valid_time = TRUE;
|
||||
// Check for a valid date using checkdate(). Only values that
|
||||
// meet that test are valid.
|
||||
if (array_key_exists('year', $array) && array_key_exists('month', $array) && array_key_exists('day', $array)) {
|
||||
if (@checkdate($array['month'], $array['day'], $array['year'])) {
|
||||
$valid_date = TRUE;
|
||||
}
|
||||
// meet that test are valid. An empty value, either a string or a 0, is not
|
||||
// a valid value.
|
||||
if (!empty($array['year']) && !empty($array['month']) && !empty($array['day'])) {
|
||||
$valid_date = checkdate($array['month'], $array['day'], $array['year']);
|
||||
}
|
||||
// Testing for valid time is reversed. Missing time is OK,
|
||||
// but incorrect values are not.
|
||||
|
||||
@@ -58,6 +58,21 @@ class PhpTransliteration implements TransliterationInterface {
|
||||
*/
|
||||
protected $genericMap = [];
|
||||
|
||||
/**
|
||||
* Special characters for ::removeDiacritics().
|
||||
*
|
||||
* Characters which have accented variants but their base character
|
||||
* transliterates to more than one ASCII character require special
|
||||
* treatment: we want to remove their accent and use the un-
|
||||
* transliterated base character.
|
||||
*/
|
||||
protected $fixTransliterateForRemoveDiacritics = [
|
||||
'AE' => 'Æ',
|
||||
'ae' => 'æ',
|
||||
'ZH' => 'Ʒ',
|
||||
'zh' => 'ʒ',
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructs a transliteration object.
|
||||
*
|
||||
@@ -93,6 +108,9 @@ class PhpTransliteration implements TransliterationInterface {
|
||||
if (strlen($to_add) === 1) {
|
||||
$replacement = $to_add;
|
||||
}
|
||||
elseif (isset($this->fixTransliterateForRemoveDiacritics[$to_add])) {
|
||||
$replacement = $this->fixTransliterateForRemoveDiacritics[$to_add];
|
||||
}
|
||||
}
|
||||
|
||||
$result .= $replacement;
|
||||
|
||||
@@ -35,7 +35,8 @@ class Bytes {
|
||||
return round($size * pow(self::KILOBYTE, stripos('bkmgtpezy', $unit[0])));
|
||||
}
|
||||
else {
|
||||
return round($size);
|
||||
// Ensure size is a proper number type.
|
||||
return round((float) $size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ class Image {
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if $dimensions was modified, FALSE otherwise.
|
||||
*
|
||||
* @see image_scale()
|
||||
*/
|
||||
public static function scaleDimensions(array &$dimensions, $width = NULL, $height = NULL, $upscale = FALSE) {
|
||||
$aspect = $dimensions['height'] / $dimensions['width'];
|
||||
|
||||
@@ -537,16 +537,16 @@ EOD;
|
||||
*/
|
||||
public static function mimeHeaderDecode($header) {
|
||||
$callback = function ($matches) {
|
||||
$data = ($matches[2] == 'B') ? base64_decode($matches[3]) : str_replace('_', ' ', quoted_printable_decode($matches[3]));
|
||||
$data = (strtolower($matches[2]) == 'b') ? base64_decode($matches[3]) : str_replace('_', ' ', quoted_printable_decode($matches[3]));
|
||||
if (strtolower($matches[1]) != 'utf-8') {
|
||||
$data = static::convertToUtf8($data, $matches[1]);
|
||||
}
|
||||
return $data;
|
||||
};
|
||||
// First step: encoded chunks followed by other encoded chunks (need to collapse whitespace)
|
||||
$header = preg_replace_callback('/=\?([^?]+)\?(Q|B)\?([^?]+|\?(?!=))\?=\s+(?==\?)/', $callback, $header);
|
||||
$header = preg_replace_callback('/=\?([^?]+)\?([Qq]|[Bb])\?([^?]+|\?(?!=))\?=\s+(?==\?)/', $callback, $header);
|
||||
// Second step: remaining chunks (do not collapse whitespace)
|
||||
return preg_replace_callback('/=\?([^?]+)\?(Q|B)\?([^?]+|\?(?!=))\?=/', $callback, $header);
|
||||
return preg_replace_callback('/=\?([^?]+)\?([Qq]|[Bb])\?([^?]+|\?(?!=))\?=/', $callback, $header);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -345,7 +345,7 @@ class LibraryDiscoveryParser {
|
||||
$library_file = $path . '/' . $extension . '.libraries.yml';
|
||||
if (file_exists($this->root . '/' . $library_file)) {
|
||||
try {
|
||||
$libraries = Yaml::decode(file_get_contents($this->root . '/' . $library_file));
|
||||
$libraries = Yaml::decode(file_get_contents($this->root . '/' . $library_file)) ?? [];
|
||||
}
|
||||
catch (InvalidDataTypeException $e) {
|
||||
// Rethrow a more helpful exception to provide context.
|
||||
|
||||
@@ -2,18 +2,10 @@
|
||||
|
||||
namespace Drupal\Core\Block;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Messenger\MessengerTrait;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginBase;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Defines a base block implementation that most blocks plugins will extend.
|
||||
@@ -26,260 +18,7 @@ use Drupal\Component\Transliteration\TransliterationInterface;
|
||||
*/
|
||||
abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface {
|
||||
|
||||
use BlockPluginTrait;
|
||||
use ContextAwarePluginAssignmentTrait;
|
||||
use MessengerTrait;
|
||||
use PluginWithFormsTrait;
|
||||
|
||||
/**
|
||||
* The transliteration service.
|
||||
*
|
||||
* @var \Drupal\Component\Transliteration\TransliterationInterface
|
||||
*/
|
||||
protected $transliteration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function label() {
|
||||
if (!empty($this->configuration['label'])) {
|
||||
return $this->configuration['label'];
|
||||
}
|
||||
|
||||
$definition = $this->getPluginDefinition();
|
||||
// Cast the admin label to a string since it is an object.
|
||||
// @see \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
return (string) $definition['admin_label'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->setConfiguration($configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfiguration() {
|
||||
return $this->configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfiguration(array $configuration) {
|
||||
$this->configuration = NestedArray::mergeDeep(
|
||||
$this->baseConfigurationDefaults(),
|
||||
$this->defaultConfiguration(),
|
||||
$configuration
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns generic default configuration for block plugins.
|
||||
*
|
||||
* @return array
|
||||
* An associative array with the default configuration.
|
||||
*/
|
||||
protected function baseConfigurationDefaults() {
|
||||
return [
|
||||
'id' => $this->getPluginId(),
|
||||
'label' => '',
|
||||
'provider' => $this->pluginDefinition['provider'],
|
||||
'label_display' => static::BLOCK_LABEL_VISIBLE,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfigurationValue($key, $value) {
|
||||
$this->configuration[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access(AccountInterface $account, $return_as_object = FALSE) {
|
||||
$access = $this->blockAccess($account);
|
||||
return $return_as_object ? $access : $access->isAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the block should be shown.
|
||||
*
|
||||
* Blocks with specific access checking should override this method rather
|
||||
* than access(), in order to avoid repeating the handling of the
|
||||
* $return_as_object argument.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user session for which to check access.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResult
|
||||
* The access result.
|
||||
*
|
||||
* @see self::access()
|
||||
*/
|
||||
protected function blockAccess(AccountInterface $account) {
|
||||
// By default, the block is visible.
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Creates a generic configuration form for all block types. Individual
|
||||
* block plugins can add elements to this form by overriding
|
||||
* BlockBase::blockForm(). Most block plugins should not override this
|
||||
* method unless they need to alter the generic form elements.
|
||||
*
|
||||
* @see \Drupal\Core\Block\BlockBase::blockForm()
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$definition = $this->getPluginDefinition();
|
||||
$form['provider'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $definition['provider'],
|
||||
];
|
||||
|
||||
$form['admin_label'] = [
|
||||
'#type' => 'item',
|
||||
'#title' => $this->t('Block description'),
|
||||
'#plain_text' => $definition['admin_label'],
|
||||
];
|
||||
$form['label'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Title'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $this->label(),
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['label_display'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Display title'),
|
||||
'#default_value' => ($this->configuration['label_display'] === static::BLOCK_LABEL_VISIBLE),
|
||||
'#return_value' => static::BLOCK_LABEL_VISIBLE,
|
||||
];
|
||||
|
||||
// Add context mapping UI form elements.
|
||||
$contexts = $form_state->getTemporaryValue('gathered_contexts') ?: [];
|
||||
$form['context_mapping'] = $this->addContextAssignmentElement($this, $contexts);
|
||||
// Add plugin-specific settings for this block type.
|
||||
$form += $this->blockForm($form, $form_state);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockForm($form, FormStateInterface $form_state) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Most block plugins should not override this method. To add validation
|
||||
* for a specific block type, override BlockBase::blockValidate().
|
||||
*
|
||||
* @see \Drupal\Core\Block\BlockBase::blockValidate()
|
||||
*/
|
||||
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
// Remove the admin_label form item element value so it will not persist.
|
||||
$form_state->unsetValue('admin_label');
|
||||
|
||||
$this->blockValidate($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockValidate($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Most block plugins should not override this method. To add submission
|
||||
* handling for a specific block type, override BlockBase::blockSubmit().
|
||||
*
|
||||
* @see \Drupal\Core\Block\BlockBase::blockSubmit()
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
// Process the block's submission handling if no errors occurred only.
|
||||
if (!$form_state->getErrors()) {
|
||||
$this->configuration['label'] = $form_state->getValue('label');
|
||||
$this->configuration['label_display'] = $form_state->getValue('label_display');
|
||||
$this->configuration['provider'] = $form_state->getValue('provider');
|
||||
$this->blockSubmit($form, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockSubmit($form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMachineNameSuggestion() {
|
||||
$definition = $this->getPluginDefinition();
|
||||
$admin_label = $definition['admin_label'];
|
||||
|
||||
// @todo This is basically the same as what is done in
|
||||
// \Drupal\system\MachineNameController::transliterate(), so it might make
|
||||
// sense to provide a common service for the two.
|
||||
$transliterated = $this->transliteration()->transliterate($admin_label, LanguageInterface::LANGCODE_DEFAULT, '_');
|
||||
$transliterated = mb_strtolower($transliterated);
|
||||
|
||||
$transliterated = preg_replace('@[^a-z0-9_.]+@', '', $transliterated);
|
||||
|
||||
return $transliterated;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPreviewFallbackString() {
|
||||
return $this->t('"@block" block', ['@block' => $this->label()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the transliteration service.
|
||||
*
|
||||
* @return \Drupal\Component\Transliteration\TransliterationInterface
|
||||
*/
|
||||
protected function transliteration() {
|
||||
if (!$this->transliteration) {
|
||||
$this->transliteration = \Drupal::transliteration();
|
||||
}
|
||||
return $this->transliteration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transliteration service.
|
||||
*
|
||||
* @param \Drupal\Component\Transliteration\TransliterationInterface $transliteration
|
||||
* The transliteration service.
|
||||
*/
|
||||
public function setTransliteration(TransliterationInterface $transliteration) {
|
||||
$this->transliteration = $transliteration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Core\Block;
|
||||
|
||||
use Drupal\Component\Transliteration\TransliterationInterface;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Messenger\MessengerTrait;
|
||||
use Drupal\Core\Plugin\PluginWithFormsTrait;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* Provides the base implementation of a block plugin.
|
||||
*
|
||||
* @internal
|
||||
* This trait is used internally by the block system. Block plugins should
|
||||
* extend \Drupal\Core\Block\BlockBase.
|
||||
*
|
||||
* @see \Drupal\Core\Block\BlockBase
|
||||
* @see \Drupal\Core\Block\BlockPluginInterface
|
||||
*
|
||||
* @ingroup block_api
|
||||
*/
|
||||
trait BlockPluginTrait {
|
||||
|
||||
use StringTranslationTrait;
|
||||
use MessengerTrait;
|
||||
use PluginWithFormsTrait;
|
||||
|
||||
/**
|
||||
* The transliteration service.
|
||||
*
|
||||
* @var \Drupal\Component\Transliteration\TransliterationInterface
|
||||
*/
|
||||
protected $transliteration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function label() {
|
||||
if (!empty($this->configuration['label'])) {
|
||||
return $this->configuration['label'];
|
||||
}
|
||||
|
||||
$definition = $this->getPluginDefinition();
|
||||
// Cast the admin label to a string since it is an object.
|
||||
// @see \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
return (string) $definition['admin_label'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->setConfiguration($configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfiguration() {
|
||||
return $this->configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfiguration(array $configuration) {
|
||||
$this->configuration = NestedArray::mergeDeep(
|
||||
$this->baseConfigurationDefaults(),
|
||||
$this->defaultConfiguration(),
|
||||
$configuration
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns generic default configuration for block plugins.
|
||||
*
|
||||
* @return array
|
||||
* An associative array with the default configuration.
|
||||
*/
|
||||
protected function baseConfigurationDefaults() {
|
||||
return [
|
||||
'id' => $this->getPluginId(),
|
||||
'label' => '',
|
||||
'provider' => $this->pluginDefinition['provider'],
|
||||
'label_display' => BlockPluginInterface::BLOCK_LABEL_VISIBLE,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfigurationValue($key, $value) {
|
||||
$this->configuration[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access(AccountInterface $account, $return_as_object = FALSE) {
|
||||
$access = $this->blockAccess($account);
|
||||
return $return_as_object ? $access : $access->isAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the block should be shown.
|
||||
*
|
||||
* Blocks with specific access checking should override this method rather
|
||||
* than access(), in order to avoid repeating the handling of the
|
||||
* $return_as_object argument.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user session for which to check access.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResult
|
||||
* The access result.
|
||||
*
|
||||
* @see self::access()
|
||||
*/
|
||||
protected function blockAccess(AccountInterface $account) {
|
||||
// By default, the block is visible.
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Creates a generic configuration form for all block types. Individual
|
||||
* block plugins can add elements to this form by overriding
|
||||
* BlockBase::blockForm(). Most block plugins should not override this
|
||||
* method unless they need to alter the generic form elements.
|
||||
*
|
||||
* @see \Drupal\Core\Block\BlockBase::blockForm()
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$definition = $this->getPluginDefinition();
|
||||
$form['provider'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $definition['provider'],
|
||||
];
|
||||
|
||||
$form['admin_label'] = [
|
||||
'#type' => 'item',
|
||||
'#title' => $this->t('Block description'),
|
||||
'#plain_text' => $definition['admin_label'],
|
||||
];
|
||||
$form['label'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Title'),
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => $this->label(),
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['label_display'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Display title'),
|
||||
'#default_value' => ($this->configuration['label_display'] === BlockPluginInterface::BLOCK_LABEL_VISIBLE),
|
||||
'#return_value' => BlockPluginInterface::BLOCK_LABEL_VISIBLE,
|
||||
];
|
||||
|
||||
// Add context mapping UI form elements.
|
||||
$contexts = $form_state->getTemporaryValue('gathered_contexts') ?: [];
|
||||
$form['context_mapping'] = $this->addContextAssignmentElement($this, $contexts);
|
||||
// Add plugin-specific settings for this block type.
|
||||
$form += $this->blockForm($form, $form_state);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockForm($form, FormStateInterface $form_state) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Most block plugins should not override this method. To add validation
|
||||
* for a specific block type, override BlockBase::blockValidate().
|
||||
*
|
||||
* @see \Drupal\Core\Block\BlockBase::blockValidate()
|
||||
*/
|
||||
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
// Remove the admin_label form item element value so it will not persist.
|
||||
$form_state->unsetValue('admin_label');
|
||||
|
||||
$this->blockValidate($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockValidate($form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Most block plugins should not override this method. To add submission
|
||||
* handling for a specific block type, override BlockBase::blockSubmit().
|
||||
*
|
||||
* @see \Drupal\Core\Block\BlockBase::blockSubmit()
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
// Process the block's submission handling if no errors occurred only.
|
||||
if (!$form_state->getErrors()) {
|
||||
$this->configuration['label'] = $form_state->getValue('label');
|
||||
$this->configuration['label_display'] = $form_state->getValue('label_display');
|
||||
$this->configuration['provider'] = $form_state->getValue('provider');
|
||||
$this->blockSubmit($form, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockSubmit($form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMachineNameSuggestion() {
|
||||
$definition = $this->getPluginDefinition();
|
||||
$admin_label = $definition['admin_label'];
|
||||
|
||||
// @todo This is basically the same as what is done in
|
||||
// \Drupal\system\MachineNameController::transliterate(), so it might make
|
||||
// sense to provide a common service for the two.
|
||||
$transliterated = $this->transliteration()->transliterate($admin_label, LanguageInterface::LANGCODE_DEFAULT, '_');
|
||||
$transliterated = mb_strtolower($transliterated);
|
||||
|
||||
$transliterated = preg_replace('@[^a-z0-9_.]+@', '', $transliterated);
|
||||
|
||||
return $transliterated;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPreviewFallbackString() {
|
||||
return $this->t('"@block" block', ['@block' => $this->label()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the transliteration service.
|
||||
*
|
||||
* @return \Drupal\Component\Transliteration\TransliterationInterface
|
||||
*/
|
||||
protected function transliteration() {
|
||||
if (!$this->transliteration) {
|
||||
$this->transliteration = \Drupal::transliteration();
|
||||
}
|
||||
return $this->transliteration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transliteration service.
|
||||
*
|
||||
* @param \Drupal\Component\Transliteration\TransliterationInterface $transliteration
|
||||
* The transliteration service.
|
||||
*/
|
||||
public function setTransliteration(TransliterationInterface $transliteration) {
|
||||
$this->transliteration = $transliteration;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
namespace Drupal\Core\Block\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\Core\Block\BlockPluginTrait;
|
||||
use Drupal\Core\Cache\CacheableDependencyTrait;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\PluginBase;
|
||||
|
||||
/**
|
||||
* Defines a fallback plugin for missing block plugins.
|
||||
@@ -14,7 +17,10 @@ use Drupal\Core\Form\FormStateInterface;
|
||||
* category = @Translation("Block"),
|
||||
* )
|
||||
*/
|
||||
class Broken extends BlockBase {
|
||||
class Broken extends PluginBase implements BlockPluginInterface {
|
||||
|
||||
use BlockPluginTrait;
|
||||
use CacheableDependencyTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
||||
@@ -121,7 +121,7 @@ final class ConfigEvents {
|
||||
* fire the event again to continue processing missing content dependencies.
|
||||
*
|
||||
* @see \Drupal\Core\Config\ConfigImporter::processMissingContent()
|
||||
* @see \Drupal\Core\Config\MissingContentEvent
|
||||
* @see \Drupal\Core\Config\Importer\MissingContentEvent
|
||||
*/
|
||||
const IMPORT_MISSING_CONTENT = 'config.importer.missing_content';
|
||||
|
||||
|
||||
@@ -130,6 +130,11 @@ class Condition extends ConditionBase {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
// If the parent does not exist, it's safe to say the actual property
|
||||
// we're checking for is also NULL.
|
||||
elseif ($condition['operator'] === 'IS NULL') {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
// Only try to match a scalar if there are no remaining keys in
|
||||
// $needs_matching as this indicates that we are looking for a specific
|
||||
|
||||
@@ -89,7 +89,14 @@ class Query extends QueryBase implements QueryInterface {
|
||||
$direction = $sort['direction'] == 'ASC' ? -1 : 1;
|
||||
$field = $sort['field'];
|
||||
uasort($result, function ($a, $b) use ($field, $direction) {
|
||||
return ($a[$field] <= $b[$field]) ? $direction : -$direction;
|
||||
$properties = explode('.', $field);
|
||||
foreach ($properties as $property) {
|
||||
if (isset($a[$property]) || isset($b[$property])) {
|
||||
$a = isset($a[$property]) ? $a[$property] : NULL;
|
||||
$b = isset($b[$property]) ? $b[$property] : NULL;
|
||||
}
|
||||
}
|
||||
return ($a <= $b) ? $direction : -$direction;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use Symfony\Component\EventDispatcher\Event;
|
||||
/**
|
||||
* Wraps a configuration event for event listeners.
|
||||
*
|
||||
* @see \Drupal\Core\Config\Config\ConfigEvents::IMPORT_MISSING_CONTENT
|
||||
* @see \Drupal\Core\Config\ConfigEvents::IMPORT_MISSING_CONTENT
|
||||
*/
|
||||
class MissingContentEvent extends Event {
|
||||
|
||||
|
||||
@@ -1501,8 +1501,8 @@ abstract class Connection {
|
||||
/**
|
||||
* Prepares a statement for execution and returns a statement object
|
||||
*
|
||||
* Emulated prepared statements does not communicate with the database server
|
||||
* so this method does not check the statement.
|
||||
* Emulated prepared statements do not communicate with the database server so
|
||||
* this method does not check the statement.
|
||||
*
|
||||
* @param string $statement
|
||||
* This must be a valid SQL statement for the target database server.
|
||||
|
||||
@@ -686,11 +686,11 @@ class Schema extends DatabaseSchema {
|
||||
$condition->condition('column_name', $column);
|
||||
$condition->compile($this->connection, $this);
|
||||
// Don't use {} around information_schema.columns table.
|
||||
return $this->connection->query("SELECT column_comment as column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
|
||||
return $this->connection->query("SELECT column_comment AS column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
|
||||
}
|
||||
$condition->compile($this->connection, $this);
|
||||
// Don't use {} around information_schema.tables table.
|
||||
$comment = $this->connection->query("SELECT table_comment as table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
|
||||
$comment = $this->connection->query("SELECT table_comment AS table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
|
||||
// Work-around for MySQL 5.0 bug http://bugs.mysql.com/bug.php?id=11379
|
||||
return preg_replace('/; InnoDB free:.*$/', '', $comment);
|
||||
}
|
||||
|
||||
@@ -814,13 +814,16 @@ class Select extends Query implements SelectInterface {
|
||||
$fields = [];
|
||||
foreach ($this->tables as $alias => $table) {
|
||||
if (!empty($table['all_fields'])) {
|
||||
$fields[] = $this->connection->escapeTable($alias) . '.*';
|
||||
$fields[] = $this->connection->escapeAlias($alias) . '.*';
|
||||
}
|
||||
}
|
||||
foreach ($this->fields as $field) {
|
||||
// Note that $field['table'] holds the table alias.
|
||||
// @see \Drupal\Core\Database\Query\Select::addField
|
||||
$table = isset($field['table']) ? $this->connection->escapeAlias($field['table']) . '.' : '';
|
||||
// Always use the AS keyword for field aliases, as some
|
||||
// databases require it (e.g., PostgreSQL).
|
||||
$fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']);
|
||||
$fields[] = $table . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']);
|
||||
}
|
||||
foreach ($this->expressions as $expression) {
|
||||
$fields[] = $expression['expression'] . ' AS ' . $this->connection->escapeAlias($expression['alias']);
|
||||
@@ -852,7 +855,7 @@ class Select extends Query implements SelectInterface {
|
||||
|
||||
// Don't use the AS keyword for table aliases, as some
|
||||
// databases don't support it (e.g., Oracle).
|
||||
$query .= $table_string . ' ' . $this->connection->escapeTable($table['alias']);
|
||||
$query .= $table_string . ' ' . $this->connection->escapeAlias($table['alias']);
|
||||
|
||||
if (!empty($table['condition'])) {
|
||||
$query .= ' ON ' . (string) $table['condition'];
|
||||
|
||||
@@ -200,7 +200,7 @@ abstract class Schema implements PlaceholderInterface {
|
||||
// couldn't use \Drupal::database()->select() here because it would prefix
|
||||
// information_schema.tables and the query would fail.
|
||||
// Don't use {} around information_schema.tables table.
|
||||
$results = $this->connection->query("SELECT table_name as table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments());
|
||||
$results = $this->connection->query("SELECT table_name AS table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments());
|
||||
foreach ($results as $table) {
|
||||
// Take into account tables that have an individual prefix.
|
||||
if (isset($individually_prefixed_tables[$table->table_name])) {
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Drupal\Core\DependencyInjection;
|
||||
trait DeprecatedServicePropertyTrait {
|
||||
|
||||
/**
|
||||
* Alows to access deprecated/removed properties.
|
||||
* Allows to access deprecated/removed properties.
|
||||
*
|
||||
* This method must be public.
|
||||
*/
|
||||
|
||||
@@ -70,7 +70,7 @@ interface ContentEntityFormInterface extends EntityFormInterface {
|
||||
* For more information about entity validation, see
|
||||
* https://www.drupal.org/node/2015613.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\ContentEntityTypeInterface
|
||||
* @return \Drupal\Core\Entity\ContentEntityInterface
|
||||
* The built entity.
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state);
|
||||
|
||||
@@ -14,8 +14,54 @@ use Drupal\Core\Site\Settings;
|
||||
/**
|
||||
* Provides an entity autocomplete form element.
|
||||
*
|
||||
* The #default_value accepted by this element is either an entity object or an
|
||||
* array of entity objects.
|
||||
* The autocomplete form element allows users to select one or multiple
|
||||
* entities, which can come from all or specific bundles of an entity type.
|
||||
*
|
||||
* Properties:
|
||||
* - #target_type: (required) The ID of the target entity type.
|
||||
* - #tags: (optional) TRUE if the element allows multiple selection. Defaults
|
||||
* to FALSE.
|
||||
* - #default_value: (optional) The default entity or an array of default
|
||||
* entities, depending on the value of #tags.
|
||||
* - #selection_handler: (optional) The plugin ID of the entity reference
|
||||
* selection handler (a plugin of type EntityReferenceSelection). The default
|
||||
* value is the lowest-weighted plugin that is compatible with #target_type.
|
||||
* - #selection_settings: (optional) An array of settings for the selection
|
||||
* handler. Settings for the default selection handler
|
||||
* \Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection are:
|
||||
* - target_bundles: Array of bundles to allow (omit to allow all bundles).
|
||||
* - sort: Array with 'field' and 'direction' keys, determining how results
|
||||
* will be sorted. Defaults to unsorted.
|
||||
* - #autocreate: (optional) Array of settings used to auto-create entities
|
||||
* that do not exist (omit to not auto-create entities). Elements:
|
||||
* - bundle: (required) Bundle to use for auto-created entities.
|
||||
* - uid: User ID to use as the author of auto-created entities. Defaults to
|
||||
* the current user.
|
||||
* - #process_default_value: (optional) Set to FALSE if the #default_value
|
||||
* property is processed and access checked elsewhere (such as by a Field API
|
||||
* widget). Defaults to TRUE.
|
||||
* - #validate_reference: (optional) Set to FALSE if validation of the selected
|
||||
* entities is performed elsewhere. Defaults to TRUE.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* $form['my_element'] = [
|
||||
* '#type' => 'entity_autocomplete',
|
||||
* '#target_type' => 'node',
|
||||
* '#tags' => TRUE,
|
||||
* '#default_value' => $node,
|
||||
* '#selection_handler' => 'default',
|
||||
* '#selection_settings' => [
|
||||
* 'target_bundles' => ['article', 'page'],
|
||||
* ],
|
||||
* '#autocreate' => [
|
||||
* 'bundle' => 'article',
|
||||
* 'uid' => <a valid user ID>,
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
*
|
||||
* @see \Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection
|
||||
*
|
||||
* @FormElement("entity_autocomplete")
|
||||
*/
|
||||
|
||||
+9
-6
@@ -395,13 +395,16 @@ class DefaultSelection extends SelectionPluginBase implements ContainerFactoryPl
|
||||
*/
|
||||
public function createNewEntity($entity_type_id, $bundle, $label, $uid) {
|
||||
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
|
||||
$bundle_key = $entity_type->getKey('bundle');
|
||||
$label_key = $entity_type->getKey('label');
|
||||
|
||||
$entity = $this->entityTypeManager->getStorage($entity_type_id)->create([
|
||||
$bundle_key => $bundle,
|
||||
$label_key => $label,
|
||||
]);
|
||||
$values = [
|
||||
$entity_type->getKey('label') => $label,
|
||||
];
|
||||
|
||||
if ($bundle_key = $entity_type->getKey('bundle')) {
|
||||
$values[$bundle_key] = $bundle;
|
||||
}
|
||||
|
||||
$entity = $this->entityTypeManager->getStorage($entity_type_id)->create($values);
|
||||
|
||||
if ($entity instanceof EntityOwnerInterface) {
|
||||
$entity->setOwnerId($uid);
|
||||
|
||||
@@ -846,8 +846,19 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
||||
|
||||
// Add the bundle column.
|
||||
if ($bundle = $this->entityType->getKey('bundle')) {
|
||||
if ($base_table) {
|
||||
$select->join($base_table, 'base_table', "entity_table.{$this->entityType->getKey('id')} = %alias.{$this->entityType->getKey('id')}");
|
||||
// The bundle field is not stored in the revision table, so we need to
|
||||
// join the data (or base) table and retrieve it from there.
|
||||
if ($base_table && $base_table !== $table_name) {
|
||||
$join_condition = "entity_table.{$this->entityType->getKey('id')} = %alias.{$this->entityType->getKey('id')}";
|
||||
|
||||
// If the entity type is translatable, we also need to add the langcode
|
||||
// to the join, otherwise we'll get duplicate rows for each language.
|
||||
if ($this->entityType->isTranslatable()) {
|
||||
$langcode = $this->entityType->getKey('langcode');
|
||||
$join_condition .= " AND entity_table.{$langcode} = %alias.{$langcode}";
|
||||
}
|
||||
|
||||
$select->join($base_table, 'base_table', $join_condition);
|
||||
$select->addField('base_table', $bundle, 'bundle');
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -616,6 +616,18 @@ use Drupal\node\Entity\NodeType;
|
||||
* are invoked are hook_entity_create_access() and
|
||||
* hook_ENTITY_TYPE_create_access() instead.
|
||||
*
|
||||
* The access to an entity can be influenced in several ways:
|
||||
* - To explicitly allow access, return an AccessResultInterface object with
|
||||
* isAllowed() returning TRUE. Other modules can override this access by
|
||||
* returning TRUE for isForbidden().
|
||||
* - To explicitly forbid access, return an AccessResultInterface object with
|
||||
* isForbidden() returning TRUE. Access will be forbidden even if your module
|
||||
* (or another module) also returns TRUE for isNeutral() or isAllowed().
|
||||
* - To neither allow nor explicitly forbid access, return an
|
||||
* AccessResultInterface object with isNeutral() returning TRUE.
|
||||
* - If your module does not return an AccessResultInterface object, neutral
|
||||
* access will be assumed.
|
||||
*
|
||||
* The Node entity type has a complex system for determining access, which
|
||||
* developers can interact with. This is described in the
|
||||
* @link node_access Node access topic. @endlink
|
||||
@@ -643,7 +655,10 @@ use Drupal\node\Entity\NodeType;
|
||||
* @param string $operation
|
||||
* The operation that is to be performed on $entity.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account trying to access the entity.
|
||||
* The account trying to access the entity. Usually one of:
|
||||
* - "view"
|
||||
* - "update"
|
||||
* - "delete"
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result. The final result is calculated by using
|
||||
@@ -677,7 +692,10 @@ function hook_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operat
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity to check access to.
|
||||
* @param string $operation
|
||||
* The operation that is to be performed on $entity.
|
||||
* The operation that is to be performed on $entity. Usually one of:
|
||||
* - "view"
|
||||
* - "update"
|
||||
* - "delete"
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account trying to access the entity.
|
||||
*
|
||||
|
||||
@@ -42,6 +42,7 @@ class ExceptionLoggingSubscriber implements EventSubscriberInterface {
|
||||
// why access was denied.
|
||||
$exception = $event->getException();
|
||||
$error = Error::decodeException($exception);
|
||||
unset($error['@backtrace_string']);
|
||||
$error['@uri'] = $event->getRequest()->getRequestUri();
|
||||
$this->logger->get('access denied')->warning('Path: @uri. %type: @message in %function (line %line of %file).', $error);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class BooleanCheckboxWidget extends WidgetBase {
|
||||
$summary = [];
|
||||
|
||||
$display_label = $this->getSetting('display_label');
|
||||
$summary[] = t('Use field label: @display_label', ['@display_label' => ($display_label ? t('Yes') : 'No')]);
|
||||
$summary[] = t('Use field label: @display_label', ['@display_label' => ($display_label ? t('Yes') : t('No'))]);
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
+12
-5
@@ -117,7 +117,7 @@ class EntityReferenceAutocompleteWidget extends WidgetBase {
|
||||
'#placeholder' => $this->getSetting('placeholder'),
|
||||
];
|
||||
|
||||
if ($this->getSelectionHandlerSetting('auto_create') && ($bundle = $this->getAutocreateBundle())) {
|
||||
if ($bundle = $this->getAutocreateBundle()) {
|
||||
$element['#autocreate'] = [
|
||||
'bundle' => $bundle,
|
||||
'uid' => ($entity instanceof EntityOwnerInterface) ? $entity->getOwnerId() : \Drupal::currentUser()->id(),
|
||||
@@ -154,16 +154,23 @@ class EntityReferenceAutocompleteWidget extends WidgetBase {
|
||||
* Returns the name of the bundle which will be used for autocreated entities.
|
||||
*
|
||||
* @return string
|
||||
* The bundle name.
|
||||
* The bundle name. If autocreate is not active, NULL will be returned.
|
||||
*/
|
||||
protected function getAutocreateBundle() {
|
||||
$bundle = NULL;
|
||||
if ($this->getSelectionHandlerSetting('auto_create') && $target_bundles = $this->getSelectionHandlerSetting('target_bundles')) {
|
||||
if ($this->getSelectionHandlerSetting('auto_create')) {
|
||||
$target_bundles = $this->getSelectionHandlerSetting('target_bundles');
|
||||
// If there's no target bundle at all, use the target_type. It's the
|
||||
// default for bundleless entity types.
|
||||
if (empty($target_bundles)) {
|
||||
$bundle = $this->getFieldSetting('target_type');
|
||||
}
|
||||
// If there's only one target bundle, use it.
|
||||
if (count($target_bundles) == 1) {
|
||||
elseif (count($target_bundles) == 1) {
|
||||
$bundle = reset($target_bundles);
|
||||
}
|
||||
// Otherwise use the target bundle stored in selection handler settings.
|
||||
// If there's more than one target bundle, use the autocreate bundle
|
||||
// stored in selection handler settings.
|
||||
elseif (!$bundle = $this->getSelectionHandlerSetting('auto_create_bundle')) {
|
||||
// If no bundle has been set as auto create target means that there is
|
||||
// an inconsistency in entity reference field settings.
|
||||
|
||||
@@ -861,7 +861,8 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
|
||||
// https://www.drupal.org/node/2504709.
|
||||
$parsed = UrlHelper::parse($request_uri);
|
||||
unset($parsed['query'][static::AJAX_FORM_REQUEST], $parsed['query'][MainContentViewSubscriber::WRAPPER_FORMAT]);
|
||||
return $parsed['path'] . ($parsed['query'] ? ('?' . UrlHelper::buildQuery($parsed['query'])) : '');
|
||||
$action = $parsed['path'] . ($parsed['query'] ? ('?' . UrlHelper::buildQuery($parsed['query'])) : '');
|
||||
return UrlHelper::filterBadProtocol($action);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -66,8 +66,8 @@ class Link implements RenderableInterface {
|
||||
/**
|
||||
* Creates a Link object from a given Url object.
|
||||
*
|
||||
* @param string $text
|
||||
* The text of the link.
|
||||
* @param string|array|\Drupal\Component\Render\MarkupInterface $text
|
||||
* The link text for the anchor tag as a translated string or render array.
|
||||
* @param \Drupal\Core\Url $url
|
||||
* The Url to create the link for.
|
||||
*
|
||||
|
||||
@@ -10,13 +10,13 @@ use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
* Logging severity levels as defined in RFC 5424.
|
||||
*
|
||||
* The constant definitions of this class correspond to the logging severity
|
||||
* levels defined in RFC 5424, section 4.1.1. PHP supplies predefined LOG_*
|
||||
* levels defined in RFC 5424, section 6.2.1. PHP supplies predefined LOG_*
|
||||
* constants for use in the syslog() function, but their values on Windows
|
||||
* builds do not correspond to RFC 5424. The associated PHP bug report was
|
||||
* closed with the comment, "And it's also not a bug, as Windows just have less
|
||||
* log levels," and "So the behavior you're seeing is perfectly normal."
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc5424
|
||||
* @see https://tools.ietf.org/html/rfc5424#section-6.2.1
|
||||
* @see http://bugs.php.net/bug.php?id=18090
|
||||
* @see http://php.net/manual/function.syslog.php
|
||||
* @see http://php.net/manual/network.constants.php
|
||||
|
||||
@@ -15,14 +15,14 @@ use Drupal\Core\Render\Element;
|
||||
*
|
||||
* Example usage:
|
||||
* @code
|
||||
* $form['email'] = array(
|
||||
* $form['email'] = [
|
||||
* '#type' => 'email',
|
||||
* '#title' => $this->t('Email'),
|
||||
* '#pattern' => '*@example.com',
|
||||
* );
|
||||
* @end
|
||||
* ];
|
||||
* @endcode
|
||||
*
|
||||
* @see \Drupal\Core\Render\Element\Render\Textfield
|
||||
* @see \Drupal\Core\Render\Element\Textfield
|
||||
*
|
||||
* @FormElement("email")
|
||||
*/
|
||||
|
||||
@@ -52,7 +52,7 @@ class StatusReport extends RenderElement {
|
||||
// Order the grouped requirements by a set order.
|
||||
$order = array_flip($element['#priorities']);
|
||||
uksort($grouped_requirements, function ($a, $b) use ($order) {
|
||||
return $order[$a] > $order[$b];
|
||||
return $order[$a] <=> $order[$b];
|
||||
});
|
||||
|
||||
$element['#grouped_requirements'] = $grouped_requirements;
|
||||
|
||||
@@ -414,13 +414,16 @@
|
||||
* render array contained:
|
||||
* @code
|
||||
* $build['my_element'] = [
|
||||
* '#attached' => ['placeholders' => ['@foo' => 'replacement']],
|
||||
* '#markup' => ['Something about @foo'],
|
||||
* '#markup' => 'Something about @foo',
|
||||
* '#attached' => [
|
||||
* 'placeholders' => [
|
||||
* '@foo' => ['#markup' => 'replacement'],
|
||||
* ],
|
||||
* ];
|
||||
* @endcode
|
||||
* then #markup would end up containing 'Something about replacement'.
|
||||
*
|
||||
* Note that each placeholder value can itself be a render array, which will be
|
||||
* Note that each placeholder value *must* itself be a render array. It will be
|
||||
* rendered, and any cache tags generated during rendering will be added to the
|
||||
* cache tags for the markup.
|
||||
*
|
||||
|
||||
@@ -60,8 +60,8 @@ class PharExtensionInterceptor implements Assertable {
|
||||
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.
|
||||
// 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
|
||||
|
||||
@@ -26,7 +26,7 @@ class AttributeHelper {
|
||||
* An Attribute object or an array of attributes.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the attibute exists, FALSE otherwise.
|
||||
* TRUE if the attribute exists, FALSE otherwise.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* When the input $collection is neither an Attribute object nor an array.
|
||||
|
||||
@@ -205,7 +205,7 @@ class PhpUnitTestRunner implements ContainerInjectionInterface {
|
||||
*/
|
||||
public function runTests($test_id, array $unescaped_test_classnames, &$status = NULL) {
|
||||
$phpunit_file = $this->xmlLogFilePath($test_id);
|
||||
// Store ouptut from our test run.
|
||||
// Store output from our test run.
|
||||
$output = [];
|
||||
$this->runCommand($unescaped_test_classnames, $phpunit_file, $status, $output);
|
||||
|
||||
@@ -217,7 +217,7 @@ class PhpUnitTestRunner implements ContainerInjectionInterface {
|
||||
'test_id' => $test_id,
|
||||
'test_class' => implode(",", $unescaped_test_classnames),
|
||||
'status' => TestStatus::label($status),
|
||||
'message' => 'PHPunit Test failed to complete; Error: ' . implode("\n", $output),
|
||||
'message' => 'PHPUnit Test failed to complete; Error: ' . implode("\n", $output),
|
||||
'message_group' => 'Other',
|
||||
'function' => implode(",", $unescaped_test_classnames),
|
||||
'line' => '0',
|
||||
|
||||
@@ -169,7 +169,15 @@ class TypedDataManager extends DefaultPluginManager implements TypedDataManagerI
|
||||
$parts[] = json_encode($settings);
|
||||
}
|
||||
// Property path for the requested data object.
|
||||
$parts[] = $object->getPropertyPath() . '.' . $property_name;
|
||||
$parts[] = $object->getPropertyPath();
|
||||
// Only property instances of complex data types should be cached by the
|
||||
// property name, as they represent different properties. Properties of list
|
||||
// data types are the items of the list and the property name represents
|
||||
// only the delta in that list and not an unique property, which is why all
|
||||
// items should use the same prototype.
|
||||
if ($object instanceof ComplexDataInterface) {
|
||||
$parts[] = $property_name;
|
||||
}
|
||||
$key = implode(':', $parts);
|
||||
|
||||
// Create the prototype if needed.
|
||||
|
||||
@@ -27,16 +27,28 @@ class UpdateCompilerPass implements CompilerPassInterface {
|
||||
do {
|
||||
$has_changed = FALSE;
|
||||
foreach ($container->getDefinitions() as $key => $definition) {
|
||||
// Ensure all the definition's arguments are valid.
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
if ($argument instanceof Reference) {
|
||||
$argument_id = (string) $argument;
|
||||
if (!$container->has($argument_id) && $argument->getInvalidBehavior() === ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
|
||||
// If the container does not have the argument and would throw an
|
||||
// exception, remove the service.
|
||||
if ($this->isArgumentMissingService($argument, $container)) {
|
||||
$container->removeDefinition($key);
|
||||
$container->log($this, sprintf('Removed service "%s"; reason: depends on non-existent service "%s".', $key, (string) $argument));
|
||||
$has_changed = TRUE;
|
||||
$process_aliases = TRUE;
|
||||
// Process the next definition.
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure all the method call arguments are valid.
|
||||
foreach ($definition->getMethodCalls() as $call) {
|
||||
foreach ($call[1] as $argument) {
|
||||
if ($this->isArgumentMissingService($argument, $container)) {
|
||||
$container->removeDefinition($key);
|
||||
$container->log($this, sprintf('Removed service "%s"; reason: depends on non-existent service "%s".', $key, $argument_id));
|
||||
$container->log($this, sprintf('Removed service "%s"; reason: method call "%s" depends on non-existent service "%s".', $key, $call[0], (string) $argument));
|
||||
$has_changed = TRUE;
|
||||
$process_aliases = TRUE;
|
||||
// Process the next definition.
|
||||
continue 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,4 +70,26 @@ class UpdateCompilerPass implements CompilerPassInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a reference argument is to a missing service.
|
||||
*
|
||||
* @param mixed $argument
|
||||
* The argument to check.
|
||||
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
|
||||
* The container.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the argument is a reference to a service that is missing from the
|
||||
* container and the reference is required, FALSE if not.
|
||||
*/
|
||||
private function isArgumentMissingService($argument, ContainerBuilder $container) {
|
||||
if ($argument instanceof Reference) {
|
||||
$argument_id = (string) $argument;
|
||||
if (!$container->has($argument_id) && $argument->getInvalidBehavior() === ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ class Url implements TrustedCallbackInterface {
|
||||
// Extract query parameters and fragment and merge them into $uri_options,
|
||||
// but preserve the original $options for the fallback case.
|
||||
$uri_options = $options;
|
||||
if (isset($uri_parts['fragment'])) {
|
||||
if (isset($uri_parts['fragment']) && $uri_parts['fragment'] !== '') {
|
||||
$uri_options += ['fragment' => $uri_parts['fragment']];
|
||||
unset($uri_parts['fragment']);
|
||||
}
|
||||
|
||||
@@ -35,11 +35,11 @@ class ProjectInfo {
|
||||
* @param bool $status
|
||||
* Boolean that controls what status (enabled or uninstalled) to process out
|
||||
* of the $list and add to the $projects array.
|
||||
* @param array $additional_whitelist
|
||||
* @param array $additional_elements
|
||||
* (optional) Array of additional elements to be collected from the .info.yml
|
||||
* file. Defaults to array().
|
||||
*/
|
||||
public function processInfoList(array &$projects, array $list, $project_type, $status, array $additional_whitelist = []) {
|
||||
public function processInfoList(array &$projects, array $list, $project_type, $status, array $additional_elements = []) {
|
||||
foreach ($list as $file) {
|
||||
// Just projects with a matching status should be listed.
|
||||
if ($file->status != $status) {
|
||||
@@ -111,7 +111,7 @@ class ProjectInfo {
|
||||
'name' => $project_name,
|
||||
// Only save attributes from the .info.yml file we care about so we do
|
||||
// not bloat our RAM usage needlessly.
|
||||
'info' => $this->filterProjectInfo($file->info, $additional_whitelist),
|
||||
'info' => $this->filterProjectInfo($file->info, $additional_elements),
|
||||
'datestamp' => $file->info['datestamp'],
|
||||
'includes' => [$file->getName() => $file->info['name']],
|
||||
'project_type' => $project_display_type,
|
||||
@@ -165,7 +165,7 @@ class ProjectInfo {
|
||||
* @param array $info
|
||||
* Array of .info.yml file data as returned by
|
||||
* \Drupal\Core\Extension\InfoParser.
|
||||
* @param $additional_whitelist
|
||||
* @param $additional_elements
|
||||
* (optional) Array of additional elements to be collected from the .info.yml
|
||||
* file. Defaults to array().
|
||||
*
|
||||
@@ -174,8 +174,8 @@ class ProjectInfo {
|
||||
*
|
||||
* @see \Drupal\Core\Utility\ProjectInfo::processInfoList()
|
||||
*/
|
||||
public function filterProjectInfo($info, $additional_whitelist = []) {
|
||||
$whitelist = [
|
||||
public function filterProjectInfo($info, $additional_elements = []) {
|
||||
$elements = [
|
||||
'_info_file_ctime',
|
||||
'datestamp',
|
||||
'major',
|
||||
@@ -185,8 +185,8 @@ class ProjectInfo {
|
||||
'project status url',
|
||||
'version',
|
||||
];
|
||||
$whitelist = array_merge($whitelist, $additional_whitelist);
|
||||
return array_intersect_key($info, array_combine($whitelist, $whitelist));
|
||||
$elements = array_merge($elements, $additional_elements);
|
||||
return array_intersect_key($info, array_combine($elements, $elements));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user