Skip to content
Commits on Source (29)
......@@ -2047,7 +2047,7 @@ function hook_mail_alter(&$message) {
* An array of parameters supplied by the caller of
* MailManagerInterface->mail().
*
* @see \Drupal\Core\Mail\MailManagerInterface->mail()
* @see \Drupal\Core\Mail\MailManagerInterface::mail()
*/
function hook_mail($key, &$message, $params) {
$account = $params['account'];
......
......@@ -1220,7 +1220,9 @@ function file_directory_os_temp() {
foreach ($directories as $directory) {
if (is_dir($directory) && is_writable($directory)) {
return $directory;
// Both sys_get_temp_dir() and ini_get('upload_tmp_dir') can return paths
// with a trailing directory separator.
return rtrim($directory, DIRECTORY_SEPARATOR);
}
}
return FALSE;
......
......@@ -596,7 +596,7 @@ function update_already_performed($module, $number) {
* An array of return values obtained by merging the results of the
* hook_update_dependencies() implementations in all installed modules.
*
* @see \Drupal::moduleHandler()->invokeAll()
* @see \Drupal\Core\Extension\ModuleHandlerInterface::invokeAll()
* @see hook_update_dependencies()
*/
function update_retrieve_dependencies() {
......
......@@ -81,7 +81,7 @@ class Drupal {
/**
* The current system version.
*/
const VERSION = '8.1.9-dev';
const VERSION = '8.1.11-dev';
/**
* Core API compatibility.
......
......@@ -23,7 +23,7 @@ class Schema extends DatabaseSchema {
* This is collected by DatabaseConnection_pgsql->queryTableInformation(),
* by introspecting the database.
*
* @see DatabaseConnection_pgsql->queryTableInformation()
* @see \Drupal\Core\Database\Driver\pgsql\Schema::queryTableInformation()
* @var array
*/
protected $tableInformation = array();
......
......@@ -297,7 +297,7 @@ protected static function matchEntityByTitle(SelectionInterface $handler, $input
$multiples[] = $name . ' (' . $id . ')';
}
$params['@id'] = $id;
$form_state->setError($element, t('Multiple entities match this reference; "%multiple". Specify the one you want by appending the id in parentheses, like "@value (@id)".', array('%multiple' => implode('", "', $multiples))));
$form_state->setError($element, t('Multiple entities match this reference; "%multiple". Specify the one you want by appending the id in parentheses, like "@value (@id)".', array('%multiple' => implode('", "', $multiples)) + $params));
}
else {
// Take the one and only matching entity.
......
......@@ -1543,6 +1543,7 @@ protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definit
$item_query = $this->database->select($table_name, 't', array('fetch' => \PDO::FETCH_ASSOC))
->fields('t')
->condition('entity_id', $row['entity_id'])
->condition('deleted', 1)
->orderBy('delta');
foreach ($item_query->execute() as $item_row) {
......@@ -1581,10 +1582,12 @@ protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefiniti
$revision_id = $this->entityType->isRevisionable() ? $entity->getRevisionId() : $entity->id();
$this->database->delete($table_name)
->condition('revision_id', $revision_id)
->condition('deleted', 1)
->execute();
if ($this->entityType->isRevisionable()) {
$this->database->delete($revision_name)
->condition('revision_id', $revision_id)
->condition('deleted', 1)
->execute();
}
}
......@@ -1684,6 +1687,12 @@ public function countFieldData($storage_definition, $as_bool = FALSE) {
* Whether the field has been already deleted.
*/
protected function storageDefinitionIsDeleted(FieldStorageDefinitionInterface $storage_definition) {
// Configurable fields are marked for deletion.
if ($storage_definition instanceOf FieldStorageConfigInterface) {
return $storage_definition->isDeleted();
}
// For non configurable fields check whether they are still in the last
// installed schema repository.
return !array_key_exists($storage_definition->getName(), $this->entityManager->getLastInstalledFieldStorageDefinitions($this->entityTypeId));
}
......
......@@ -188,13 +188,16 @@ public function onException(GetResponseForExceptionEvent $event) {
if (!method_exists($this, $method)) {
if ($exception instanceof HttpExceptionInterface) {
$this->onFormatUnknown($event);
$response = $event->getResponse();
$response->headers->set('Content-Type', 'text/plain');
}
else {
$this->onHtml($event);
}
return;
}
$this->$method($event);
else {
$this->$method($event);
}
}
/**
......
......@@ -172,7 +172,7 @@ function getProjectName(Extension $file) {
* @return
* Array of .info.yml file data we need for the update manager.
*
* @see \Drupal\Core\Utility\ProjectInfo->processInfoList()
* @see \Drupal\Core\Utility\ProjectInfo::processInfoList()
*/
function filterProjectInfo($info, $additional_whitelist = array()) {
$whitelist = array(
......
......@@ -108,10 +108,10 @@ public function getDefaultOperations(EntityInterface $entity) {
* {@inheritdoc}
*/
public function render() {
$build['action_header']['#markup'] = '<h3>' . t('Available actions:') . '</h3>';
$build['action_header']['#markup'] = '<h3>' . $this->t('Available actions:') . '</h3>';
$build['action_table'] = parent::render();
if (!$this->hasConfigurableActions) {
unset($build['action_table']['#header']['operations']);
unset($build['action_table']['table']['#header']['operations']);
}
$build['action_admin_manage_form'] = \Drupal::formBuilder()->getForm('Drupal\action\Form\ActionAdminManageForm');
return $build;
......
<?php
namespace Drupal\action\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Test behaviors when visiting the action listing page.
*
* @group action
*/
class ActionListTest extends WebTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('action');
/**
* Tests the behavior when there are no actions to list in the admin page.
*/
public function testEmptyActionList() {
// Create a user with permission to view the actions administration pages.
$this->drupalLogin($this->drupalCreateUser(['administer actions']));
// Ensure the empty text appears on the action list page.
/** @var $storage \Drupal\Core\Entity\EntityStorageInterface */
$storage = $this->container->get('entity.manager')->getStorage('action');
$actions = $storage->loadMultiple();
$storage->delete($actions);
$this->drupalGet('/admin/config/system/actions');
$this->assertRaw('There is no Action yet.');
}
}
......@@ -104,9 +104,15 @@ public function getTheme() {
*/
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
static::invalidateBlockPluginCache();
}
// Invalidate the block cache to update custom block-based derivatives.
\Drupal::service('plugin.manager.block')->clearCachedDefinitions();
/**
* {@inheritdoc}
*/
public static function postDelete(EntityStorageInterface $storage, array $entities) {
parent::postDelete($storage, $entities);
static::invalidateBlockPluginCache();
}
/**
......@@ -237,4 +243,12 @@ public function setRevisionLog($revision_log) {
return $this;
}
/**
* Invalidates the block plugin cache after changes and deletions.
*/
protected static function invalidateBlockPluginCache() {
// Invalidate the block cache to update custom block-based derivatives.
\Drupal::service('plugin.manager.block')->clearCachedDefinitions();
}
}
......@@ -44,6 +44,8 @@ public static function create(ContainerInterface $container, $base_plugin_id) {
*/
public function getDerivativeDefinitions($base_plugin_definition) {
$block_contents = $this->blockContentStorage->loadMultiple();
// Reset the discovered definitions.
$this->derivatives = [];
/** @var $block_content \Drupal\block_content\Entity\BlockContent */
foreach ($block_contents as $block_content) {
$this->derivatives[$block_content->uuid()] = $base_plugin_definition;
......
<?php
namespace Drupal\Tests\block_content\Kernel;
use Drupal\block_content\Entity\BlockContent;
use Drupal\block_content\Entity\BlockContentType;
use Drupal\Component\Plugin\PluginBase;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests that deleting a block clears the cached definitions.
*
* @group block_content
*/
class BlockContentDeletionTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['block', 'block_content', 'system', 'user'];
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$this->installSchema('system', ['sequence']);
$this->installEntitySchema('user');
$this->installEntitySchema('block_content');
}
/**
* Tests deleting a block_content updates the discovered block plugin.
*/
public function testDeletingBlockContentShouldClearPluginCache() {
// Create a block content type.
$block_content_type = BlockContentType::create([
'id' => 'spiffy',
'label' => 'Mucho spiffy',
'description' => "Provides a block type that increases your site's spiffiness by upto 11%",
]);
$block_content_type->save();
// And a block content entity.
$block_content = BlockContent::create([
'info' => 'Spiffy prototype',
'type' => 'spiffy',
]);
$block_content->save();
// Make sure the block content provides a derivative block plugin in the
// block repository.
/** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
$block_manager = $this->container->get('plugin.manager.block');
$plugin_id = 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid();
$this->assertTrue($block_manager->hasDefinition($plugin_id));
// Now delete the block content entity.
$block_content->delete();
// The plugin should no longer exist.
$this->assertFalse($block_manager->hasDefinition($plugin_id));
}
}
......@@ -2,7 +2,9 @@
namespace Drupal\comment;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Session\AccountInterface;
/**
* Defines a item list class for comment fields.
......@@ -37,4 +39,28 @@ public function offsetExists($offset) {
return parent::offsetExists($offset);
}
/**
* {@inheritdoc}
*/
public function access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE) {
if ($operation === 'edit') {
// Only users with administer comments permission can edit the comment
// status field.
$result = AccessResult::allowedIfHasPermission($account ?: \Drupal::currentUser(), 'administer comments');
return $return_as_object ? $result : $result->isAllowed();
}
if ($operation === 'view') {
// Only users with either post comments or access comments permisison can
// view the field value. The formatter,
// Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter,
// takes care of showing the thread and form based on individual
// permissions, so if a user only has ‘post comments’ access, only the
// form will be shown and not the comments.
$result = AccessResult::allowedIfHasPermission($account ?: \Drupal::currentUser(), 'access comments')
->orIf(AccessResult::allowedIfHasPermission($account ?: \Drupal::currentUser(), 'post comments'));
return $return_as_object ? $result : $result->isAllowed();
}
return parent::access($operation, $account, $return_as_object);
}
}
......@@ -384,6 +384,7 @@ function testCommentFunctionality() {
'administer entity_test fields',
'view test entity',
'administer entity_test content',
'administer comments',
));
$this->drupalLogin($limited_user);
$this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment');
......
<?php
namespace Drupal\Tests\comment\Functional;
use Drupal\comment\Tests\CommentTestTrait;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\BrowserTestBase;
/**
* Tests comment status field access.
*
* @group comment
*/
class CommentStatusFieldAccessTest extends BrowserTestBase {
use CommentTestTrait;
/**
* {@inheritdoc}
*/
public $profile = 'testing';
/**
* Comment admin.
*
* @var \Drupal\user\UserInterface
*/
protected $commentAdmin;
/**
* Node author.
*
* @var \Drupal\user\UserInterface
*/
protected $nodeAuthor;
/**
* {@inheritdoc}
*/
public static $modules = [
'node',
'comment',
'user',
'system',
'text',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$node_type = NodeType::create([
'type' => 'article',
'name' => t('Article'),
]);
$node_type->save();
$this->nodeAuthor = $this->drupalCreateUser([
'create article content',
'skip comment approval',
'post comments',
'edit own comments',
'access comments',
'administer nodes',
]);
$this->commentAdmin = $this->drupalCreateUser([
'administer comments',
'create article content',
'edit own comments',
'skip comment approval',
'post comments',
'access comments',
'administer nodes',
]);
$this->addDefaultCommentField('node', 'article');
}
/**
* Tests comment status field access.
*/
public function testCommentStatusFieldAccessStatus() {
$this->drupalLogin($this->nodeAuthor);
$this->drupalGet('node/add/article');
$assert = $this->assertSession();
$assert->fieldNotExists('comment[0][status]');
$this->submitForm([
'title[0][value]' => 'Node 1',
], t('Save and publish'));
$assert->fieldExists('subject[0][value]');
$this->drupalLogin($this->commentAdmin);
$this->drupalGet('node/add/article');
$assert->fieldExists('comment[0][status]');
$this->submitForm([
'title[0][value]' => 'Node 2',
], t('Save and publish'));
$assert->fieldExists('subject[0][value]');
}
}
......@@ -65,14 +65,17 @@ function config_file_download($uri) {
$scheme = file_uri_scheme($uri);
$target = file_uri_target($uri);
if ($scheme == 'temporary' && $target == 'config.tar.gz') {
$request = \Drupal::request();
$date = DateTime::createFromFormat('U', $request->server->get('REQUEST_TIME'));
$date_string = $date->format('Y-m-d-H-i');
$hostname = str_replace('.', '-', $request->getHttpHost());
$filename = 'config' . '-' . $hostname . '-' . $date_string . '.tar.gz';
$disposition = 'attachment; filename="' . $filename . '"';
return array(
'Content-disposition' => $disposition,
);
if (\Drupal::currentUser()->hasPermission('export configuration')) {
$request = \Drupal::request();
$date = DateTime::createFromFormat('U', $request->server->get('REQUEST_TIME'));
$date_string = $date->format('Y-m-d-H-i');
$hostname = str_replace('.', '-', $request->getHttpHost());
$filename = 'config' . '-' . $hostname . '-' . $date_string . '.tar.gz';
$disposition = 'attachment; filename="' . $filename . '"';
return array(
'Content-disposition' => $disposition,
);
}
return -1;
}
}
......@@ -88,6 +88,12 @@ function testExport() {
// Check the single export form doesn't have "form-required" elements.
$this->drupalGet('admin/config/development/configuration/single/export');
$this->assertNoRaw('js-form-required form-required', 'No form required fields are found.');
// Ensure the temporary file is not available to users without the
// permission.
$this->drupalLogout();
$this->drupalGet('system/temporary', ['query' => ['file' => 'config.tar.gz']]);
$this->assertResponse(403);
}
}
......@@ -3,12 +3,12 @@
namespace Drupal\field\Plugin\migrate\process;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Plugin\migrate\process\StaticMap;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -21,7 +21,7 @@ class FieldType extends StaticMap implements ContainerFactoryPluginInterface {
/**
* The cckfield plugin manager.
*
* @var \Drupal\Component\Plugin\PluginManagerInterface
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface
*/
protected $cckPluginManager;
......@@ -41,12 +41,12 @@ class FieldType extends StaticMap implements ContainerFactoryPluginInterface {
* The plugin ID.
* @param mixed $plugin_definition
* The plugin definition.
* @param \Drupal\Component\Plugin\PluginManagerInterface $cck_plugin_manager
* @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_plugin_manager
* The cckfield plugin manager.
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* The migration being run.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, PluginManagerInterface $cck_plugin_manager, MigrationInterface $migration = NULL) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrateCckFieldPluginManagerInterface $cck_plugin_manager, MigrationInterface $migration = NULL) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->cckPluginManager = $cck_plugin_manager;
$this->migration = $migration;
......@@ -72,7 +72,8 @@ public function transform($value, MigrateExecutableInterface $migrate_executable
$field_type = is_array($value) ? $value[0] : $value;
try {
return $this->cckPluginManager->createInstance($field_type, [], $this->migration)->getFieldType($row);
$plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, [], $this->migration);
return $this->cckPluginManager->createInstance($plugin_id, [], $this->migration)->getFieldType($row);
}
catch (PluginNotFoundException $e) {
return parent::transform($value, $migrate_executable, $row, $destination_property);
......