Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663
This commit is contained in:
parent
eb34d130a8
commit
f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions
|
@ -5,6 +5,11 @@
|
|||
* Hooks provided by the Actions module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup hooks
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Executes code after an action is deleted.
|
||||
*
|
||||
|
@ -16,3 +21,7 @@ function hook_action_delete($aid) {
|
|||
->condition('aid', $aid)
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup hooks".
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
action.admin:
|
||||
title: Actions
|
||||
description: 'Manage the actions defined for your site.'
|
||||
description: 'Create tasks that the system can execute.'
|
||||
route_name: entity.action.collection
|
||||
parent: system.admin_config_system
|
||||
|
|
|
@ -15,13 +15,13 @@ function action_help($route_name, RouteMatchInterface $route_match) {
|
|||
case 'help.page.action':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Actions module provides tasks that can be executed by the site such as unpublishing content, sending email messages, or blocking a user. Other modules can trigger these actions when specific system events happen; for example, when new content is posted or when a user logs in. Modules can also provide additional actions. For more information, see the <a href="!documentation">online documentation for the Action module</a>.', array('!documentation' => 'https://www.drupal.org/documentation/modules/action')) . '</p>';
|
||||
$output .= '<p>' . t('The Actions module provides tasks that can be executed by the site such as unpublishing content, sending email messages, or blocking a user. Other modules can trigger these actions when specific system events happen; for example, when new content is posted or when a user logs in. Modules can also provide additional actions. For more information, see the <a href=":documentation">online documentation for the Actions module</a>.', array(':documentation' => 'https://www.drupal.org/documentation/modules/action')) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Using simple actions') . '</dt>';
|
||||
$output .= '<dd>' . t('<em>Simple actions</em> do not require configuration and are listed automatically as available on the <a href="!actions">Actions page</a>.', array('!actions' => \Drupal::url('entity.action.collection'))) . '</dd>';
|
||||
$output .= '<dd>' . t('<em>Simple actions</em> do not require configuration and are listed automatically as available on the <a href=":actions">Actions page</a>.', array(':actions' => \Drupal::url('entity.action.collection'))) . '</dd>';
|
||||
$output .= '<dt>' . t('Creating and configuring advanced actions') . '</dt>';
|
||||
$output .= '<dd>' . t('<em>Advanced actions</em> are user-created and have to be configured individually. Create an advanced action on the <a href="!actions">Actions page</a> by selecting an action type from the drop-down list. Then configure your action, for example by specifying the recipient of an automated email message.', array('!actions' => \Drupal::url('entity.action.collection'))) . '</dd>';
|
||||
$output .= '<dd>' . t('<em>Advanced actions</em> are user-created and have to be configured individually. Create an advanced action on the <a href=":actions">Actions page</a> by selecting an action type from the drop-down list. Then configure your action, for example by specifying the recipient of an automated email message.', array(':actions' => \Drupal::url('entity.action.collection'))) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
id: d6_action_settings
|
||||
label: Drupal 6 action configuration
|
||||
label: Action configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\action\Plugin\Action;
|
||||
|
||||
use Drupal\Component\Render\PlainTextOutput;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Action\ConfigurableActionBase;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
|
@ -127,7 +128,7 @@ class EmailAction extends ConfigurableActionBase implements ContainerFactoryPlug
|
|||
$this->configuration['node'] = $entity;
|
||||
}
|
||||
|
||||
$recipient = $this->token->replace($this->configuration['recipient'], $this->configuration);
|
||||
$recipient = PlainTextOutput::renderFromHtml($this->token->replace($this->configuration['recipient'], $this->configuration));
|
||||
|
||||
// If the recipient is a registered user with a language preference, use
|
||||
// the recipient's preferred language. Otherwise, use the system default
|
||||
|
@ -185,7 +186,7 @@ class EmailAction extends ConfigurableActionBase implements ContainerFactoryPlug
|
|||
'#default_value' => $this->configuration['message'],
|
||||
'#cols' => '80',
|
||||
'#rows' => '20',
|
||||
'#description' => t('The message that should be sent. You may include placeholders like [node:title], [user:name], and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
|
||||
'#description' => t('The message that should be sent. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
|
||||
namespace Drupal\action\Plugin\Action;
|
||||
|
||||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Action\ConfigurableActionBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Routing\UrlGeneratorInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Utility\UnroutedUrlAssemblerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
@ -37,11 +38,11 @@ class GotoAction extends ConfigurableActionBase implements ContainerFactoryPlugi
|
|||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* The url generator service.
|
||||
* The unrouted URL assembler service.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\UrlGeneratorInterface
|
||||
* @var \Drupal\Core\Utility\UnroutedUrlAssemblerInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
protected $unroutedUrlAssembler;
|
||||
|
||||
/**
|
||||
* Constructs a new DeleteNode object.
|
||||
|
@ -54,29 +55,47 @@ class GotoAction extends ConfigurableActionBase implements ContainerFactoryPlugi
|
|||
* The plugin implementation definition.
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
|
||||
* The tempstore factory.
|
||||
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
|
||||
* The url generator service.
|
||||
* @param \Drupal\Core\Utility\UnroutedUrlAssemblerInterface $url_assembler
|
||||
* The unrouted URL assembler service.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $dispatcher, UrlGeneratorInterface $url_generator) {
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $dispatcher, UnroutedUrlAssemblerInterface $url_assembler) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->urlGenerator = $url_generator;
|
||||
$this->unroutedUrlAssembler = $url_assembler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static($configuration, $plugin_id, $plugin_definition, $container->get('event_dispatcher'), $container->get('url_generator'));
|
||||
return new static($configuration, $plugin_id, $plugin_definition, $container->get('event_dispatcher'), $container->get('unrouted_url_assembler'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($object = NULL) {
|
||||
$url = $this->urlGenerator
|
||||
->generateFromPath($this->configuration['url'], array('absolute' => TRUE));
|
||||
$url = $this->configuration['url'];
|
||||
// Leave external URLs unchanged, and assemble others as absolute URLs
|
||||
// relative to the site's base URL.
|
||||
if (!UrlHelper::isExternal($url)) {
|
||||
$parts = UrlHelper::parse($url);
|
||||
// @todo '<front>' is valid input for BC reasons, may be removed by
|
||||
// https://www.drupal.org/node/2421941
|
||||
if ($parts['path'] === '<front>') {
|
||||
$parts['path'] = '';
|
||||
}
|
||||
$uri = 'base:' . $parts['path'];
|
||||
$options = [
|
||||
'query' => $parts['query'],
|
||||
'fragment' => $parts['fragment'],
|
||||
'absolute' => TRUE,
|
||||
];
|
||||
// Treat this as if it's user input of a path relative to the site's
|
||||
// base URL.
|
||||
$url = $this->unroutedUrlAssembler->assemble($uri, $options);
|
||||
}
|
||||
$response = new RedirectResponse($url);
|
||||
$listener = function($event) use ($response) {
|
||||
$event->setResponse($response);
|
||||
|
@ -101,7 +120,7 @@ class GotoAction extends ConfigurableActionBase implements ContainerFactoryPlugi
|
|||
$form['url'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('URL'),
|
||||
'#description' => t('The URL to which the user should be redirected. This can be an internal URL like node/1234 or an external URL like @url.', array('@url' => 'http://example.com')),
|
||||
'#description' => t('The URL to which the user should be redirected. This can be an internal URL like /node/1234 or an external URL like @url.', array('@url' => 'http://example.com')),
|
||||
'#default_value' => $this->configuration['url'],
|
||||
'#required' => TRUE,
|
||||
);
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
namespace Drupal\action\Plugin\Action;
|
||||
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Action\ConfigurableActionBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Utility\Token;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -33,19 +33,40 @@ class MessageAction extends ConfigurableActionBase implements ContainerFactoryPl
|
|||
protected $token;
|
||||
|
||||
/**
|
||||
* Constructs a MessageAction object.
|
||||
* The renderer.
|
||||
*
|
||||
* @var \Drupal\Core\Render\RendererInterface
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token) {
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* Constructs a MessageAction object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin_id for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Utility\Token
|
||||
* The token service.
|
||||
* @param \Drupal\Core\Utility\Token $token
|
||||
* The token replacement service.
|
||||
* @param \Drupal\Core\Render\RendererInterface $renderer
|
||||
* The renderer.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token, RendererInterface $renderer) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->token = $token;
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static($configuration, $plugin_id, $plugin_definition, $container->get('token'));
|
||||
return new static($configuration, $plugin_id, $plugin_definition, $container->get('token'), $container->get('renderer'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,8 +76,13 @@ class MessageAction extends ConfigurableActionBase implements ContainerFactoryPl
|
|||
if (empty($this->configuration['node'])) {
|
||||
$this->configuration['node'] = $entity;
|
||||
}
|
||||
$message = $this->token->replace(Xss::filterAdmin($this->configuration['message']), $this->configuration);
|
||||
drupal_set_message($message);
|
||||
$message = $this->token->replace($this->configuration['message'], $this->configuration);
|
||||
$build = [
|
||||
'#markup' => $message,
|
||||
];
|
||||
|
||||
// @todo Fix in https://www.drupal.org/node/2577827
|
||||
drupal_set_message($this->renderer->renderPlain($build));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,7 +104,7 @@ class MessageAction extends ConfigurableActionBase implements ContainerFactoryPl
|
|||
'#default_value' => $this->configuration['message'],
|
||||
'#required' => TRUE,
|
||||
'#rows' => '8',
|
||||
'#description' => t('The message to be displayed to the current user. You may include placeholders like [node:title], [user:name], and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
|
||||
'#description' => t('The message to be displayed to the current user. You may include placeholders like [node:title], [user:account-name], [user:display-name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,9 @@ class MigrateActionConfigsTest extends MigrateDrupal6TestBase {
|
|||
use SchemaCheckTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('action');
|
||||
public static $modules = ['action'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -6,6 +6,5 @@ version: VERSION
|
|||
core: 8.x
|
||||
configure: aggregator.admin_settings
|
||||
dependencies:
|
||||
- entity_reference
|
||||
- file
|
||||
- options
|
||||
|
|
|
@ -18,7 +18,7 @@ function aggregator_requirements($phase) {
|
|||
);
|
||||
if (!$has_curl) {
|
||||
$requirements['curl']['severity'] = REQUIREMENT_ERROR;
|
||||
$requirements['curl']['description'] = t('The Aggregator module could not be installed because the PHP <a href="@curl_url">cURL</a> library is not available.', array('@curl_url' => 'http://php.net/manual/curl.setup.php'));
|
||||
$requirements['curl']['description'] = t('The Aggregator module could not be installed because the PHP <a href=":curl_url">cURL</a> library is not available.', array(':curl_url' => 'http://php.net/manual/curl.setup.php'));
|
||||
}
|
||||
return $requirements;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
aggregator.admin_overview:
|
||||
title: 'Feed aggregator'
|
||||
description: 'Configure which content your site aggregates from other sites, how often it polls them, and how they''re categorized.'
|
||||
description: 'Add feeds or import OPMLs to gather external content and configure how often they are updated.'
|
||||
route_name: aggregator.admin_overview
|
||||
parent: system.admin_config_services
|
||||
weight: 10
|
||||
|
|
|
@ -22,30 +22,35 @@ function aggregator_help($route_name, RouteMatchInterface $route_match) {
|
|||
$path_validator = \Drupal::pathValidator();
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Aggregator module is an on-site syndicator and news reader that gathers and displays fresh content from RSS-, RDF-, and Atom-based feeds made available across the web. Thousands of sites (particularly news sites and blogs) publish their latest headlines in feeds, using a number of standardized XML-based formats. For more information, see the <a href="!aggregator-module">online documentation for the Aggregator module</a>.', array('!aggregator-module' => 'https://www.drupal.org/documentation/modules/aggregator')) . '</p>';
|
||||
$output .= '<p>' . t('The Aggregator module is an on-site syndicator and news reader that gathers and displays fresh content from RSS-, RDF-, and Atom-based feeds made available across the web. Thousands of sites (particularly news sites and blogs) publish their latest headlines in feeds, using a number of standardized XML-based formats. For more information, see the <a href=":aggregator-module">online documentation for the Aggregator module</a>.', array(':aggregator-module' => 'https://www.drupal.org/documentation/modules/aggregator')) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
// Check if the aggregator sources View is enabled.
|
||||
if ($url = $path_validator->getUrlIfValid('aggregator/sources')) {
|
||||
$output .= '<dt>' . t('Viewing feeds') . '</dt>';
|
||||
$output .= '<dd>' . t('Users view feed content in the <a href="!aggregator">main aggregator display</a>, or by <a href="!aggregator-sources">their source</a> (usually via an RSS feed reader). The most recent content in a feed can be displayed as a block through the <a href="!admin-block">Blocks administration page</a>.', array('!aggregator' => \Drupal::url('aggregator.page_last'), '!aggregator-sources' => $url->toString(), '!admin-block' => (\Drupal::moduleHandler()->moduleExists('block')) ? \Drupal::url('block.admin_display') : '#')) . '</dd>';
|
||||
$output .= '<dd>' . t('Users view feed content in the <a href=":aggregator">main aggregator display</a>, or by <a href=":aggregator-sources">their source</a> (usually via an RSS feed reader). The most recent content in a feed can be displayed as a block through the <a href=":admin-block">Blocks administration page</a>.', array(':aggregator' => \Drupal::url('aggregator.page_last'), ':aggregator-sources' => $url->toString(), ':admin-block' => (\Drupal::moduleHandler()->moduleExists('block')) ? \Drupal::url('block.admin_display') : '#')) . '</dd>';
|
||||
}
|
||||
$output .= '<dt>' . t('Adding, editing, and deleting feeds') . '</dt>';
|
||||
$output .= '<dd>' . t('Administrators can add, edit, and delete feeds, and choose how often to check each feed for newly updated items on the <a href="!feededit">Feed aggregator administration page</a>.', array('!feededit' => \Drupal::url('aggregator.admin_overview'))) . '</dd>';
|
||||
$output .= '<dd>' . t('Administrators can add, edit, and delete feeds, and choose how often to check each feed for newly updated items on the <a href=":feededit">Feed aggregator page</a>.', array(':feededit' => \Drupal::url('aggregator.admin_overview'))) . '</dd>';
|
||||
$output .= '<dt>' . t('Configuring the display of feed items') . '</dt>';
|
||||
$output .= '<dd>' . t('Administrators can choose how many items are displayed in the listing pages, which HTML tags are allowed in the content of feed items, and whether they should be trimmed to a maximum number of characters on the <a href=":settings">Feed aggregator settings page</a>.', array(':settings' => \Drupal::url('aggregator.admin_settings'))) . '</dd>';
|
||||
$output .= '<dt>' . t('Discarding old feed items') . '</dt>';
|
||||
$output .= '<dd>' . t('Administrators can choose whether to discard feed items that are older than a specified period of time on the <a href=":settings">Feed aggregator settings page</a>. This requires a correctly configured cron maintenance task (see below).', array(':settings' => \Drupal::url('aggregator.admin_settings'))) . '<dd>';
|
||||
|
||||
$output .= '<dt>' . t('<abbr title="Outline Processor Markup Language">OPML</abbr> integration') . '</dt>';
|
||||
// Check if the aggregator opml View is enabled.
|
||||
if ($url = $path_validator->getUrlIfValid('aggregator/opml')) {
|
||||
$output .= '<dd>' . t('A <a href="!aggregator-opml">machine-readable OPML file</a> of all feeds is available. OPML is an XML-based file format used to share outline-structured information such as a list of RSS feeds. Feeds can also be <a href="!import-opml">imported via an OPML file</a>.', array('!aggregator-opml' => $url->toString(), '!import-opml' => \Drupal::url('aggregator.opml_add'))) . '</dd>';
|
||||
$output .= '<dd>' . t('A <a href=":aggregator-opml">machine-readable OPML file</a> of all feeds is available. OPML is an XML-based file format used to share outline-structured information such as a list of RSS feeds. Feeds can also be <a href=":import-opml">imported via an OPML file</a>.', array(':aggregator-opml' => $url->toString(), ':import-opml' => \Drupal::url('aggregator.opml_add'))) . '</dd>';
|
||||
}
|
||||
$output .= '<dt>' . t('Configuring cron') . '</dt>';
|
||||
$output .= '<dd>' . t('A working <a href="!cron">cron maintenance task</a> is required to update feeds automatically.', array('!cron' => \Drupal::url('system.cron_settings'))) . '</dd>';
|
||||
$output .= '<dd>' . t('A working <a href=":cron">cron maintenance task</a> is required to update feeds automatically.', array(':cron' => \Drupal::url('system.cron_settings'))) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
case 'aggregator.admin_overview':
|
||||
// Don't use placeholders for possibility to change URLs for translators.
|
||||
$output = '<p>' . t('Many sites publish their headlines and posts in feeds, using a number of standardized XML-based formats. The aggregator supports <a href="http://en.wikipedia.org/wiki/Rss">RSS</a>, <a href="http://en.wikipedia.org/wiki/Resource_Description_Framework">RDF</a>, and <a href="http://en.wikipedia.org/wiki/Atom_%28standard%29">Atom</a>.') . '</p>';
|
||||
$output .= '<p>' . t('Current feeds are listed below, and <a href="!addfeed">new feeds may be added</a>. For each feed, the <em>latest items</em> block may be enabled at the <a href="!block">blocks administration page</a>.', array('!addfeed' => \Drupal::url('aggregator.feed_add'), '!block' => (\Drupal::moduleHandler()->moduleExists('block')) ? \Drupal::url('block.admin_display') : '#')) . '</p>';
|
||||
$output .= '<p>' . t('Current feeds are listed below, and <a href=":addfeed">new feeds may be added</a>. For each feed, the <em>latest items</em> block may be enabled at the <a href=":block">blocks administration page</a>.', array(':addfeed' => \Drupal::url('aggregator.feed_add'), ':block' => (\Drupal::moduleHandler()->moduleExists('block')) ? \Drupal::url('block.admin_display') : '#')) . '</p>';
|
||||
return $output;
|
||||
|
||||
case 'aggregator.feed_add':
|
||||
|
|
|
@ -10,7 +10,7 @@ aggregator.admin_settings:
|
|||
path: '/admin/config/services/aggregator/settings'
|
||||
defaults:
|
||||
_form: '\Drupal\aggregator\Form\SettingsForm'
|
||||
_title: 'Settings'
|
||||
_title: 'Feed aggregator settings'
|
||||
requirements:
|
||||
_permission: 'administer news feeds'
|
||||
|
||||
|
|
|
@ -1,31 +1,32 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- aggregator
|
||||
id: aggregator_feed.aggregator_feed.default
|
||||
targetEntityType: aggregator_feed
|
||||
bundle: aggregator_feed
|
||||
mode: default
|
||||
status: true
|
||||
content:
|
||||
items:
|
||||
weight: 0
|
||||
checked:
|
||||
type: timestamp_ago
|
||||
weight: 1
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
label: inline
|
||||
image:
|
||||
weight: 2
|
||||
description:
|
||||
weight: 3
|
||||
feed_icon:
|
||||
weight: 5
|
||||
image:
|
||||
weight: 2
|
||||
items:
|
||||
weight: 0
|
||||
link:
|
||||
type: uri_link
|
||||
weight: 4
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
label: inline
|
||||
feed_icon:
|
||||
weight: 5
|
||||
hidden:
|
||||
more_link: true
|
||||
dependencies:
|
||||
module:
|
||||
- aggregator
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
id: aggregator_feed.aggregator_feed.summary
|
||||
targetEntityType: aggregator_feed
|
||||
bundle: aggregator_feed
|
||||
mode: summary
|
||||
status: true
|
||||
content:
|
||||
items:
|
||||
weight: 0
|
||||
more_link:
|
||||
weight: 1
|
||||
hidden:
|
||||
link: true
|
||||
checked: true
|
||||
description: true
|
||||
image: true
|
||||
feed_icon: true
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- core.entity_view_mode.aggregator_feed.summary
|
||||
module:
|
||||
- aggregator
|
||||
id: aggregator_feed.aggregator_feed.summary
|
||||
targetEntityType: aggregator_feed
|
||||
bundle: aggregator_feed
|
||||
mode: summary
|
||||
content:
|
||||
items:
|
||||
weight: 0
|
||||
more_link:
|
||||
weight: 1
|
||||
hidden:
|
||||
checked: true
|
||||
description: true
|
||||
feed_icon: true
|
||||
image: true
|
||||
link: true
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
id: aggregator_item.aggregator_item.summary
|
||||
targetEntityType: aggregator_item
|
||||
bundle: aggregator_item
|
||||
mode: summary
|
||||
status: true
|
||||
content:
|
||||
timestamp:
|
||||
weight: 0
|
||||
hidden:
|
||||
link: true
|
||||
author: true
|
||||
feed: true
|
||||
description: true
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- core.entity_view_mode.aggregator_item.summary
|
||||
module:
|
||||
- aggregator
|
||||
- entity_reference
|
||||
id: aggregator_item.aggregator_item.summary
|
||||
targetEntityType: aggregator_item
|
||||
bundle: aggregator_item
|
||||
mode: summary
|
||||
content:
|
||||
timestamp:
|
||||
weight: 0
|
||||
hidden:
|
||||
author: true
|
||||
description: true
|
||||
feed: true
|
||||
link: true
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
id: aggregator_feed.summary
|
||||
label: Summary
|
||||
langcode: en
|
||||
status: true
|
||||
cache: true
|
||||
targetEntityType: aggregator_feed
|
||||
dependencies:
|
||||
module:
|
||||
- aggregator
|
||||
id: aggregator_feed.summary
|
||||
label: Summary
|
||||
targetEntityType: aggregator_feed
|
||||
cache: true
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
id: aggregator_item.summary
|
||||
label: Summary
|
||||
langcode: en
|
||||
status: true
|
||||
cache: true
|
||||
targetEntityType: aggregator_item
|
||||
dependencies:
|
||||
module:
|
||||
- aggregator
|
||||
id: aggregator_item.summary
|
||||
label: Summary
|
||||
targetEntityType: aggregator_item
|
||||
cache: true
|
||||
|
|
|
@ -59,10 +59,10 @@ display:
|
|||
offset: false
|
||||
offset_label: Offset
|
||||
tags:
|
||||
previous: '‹ previous'
|
||||
next: 'next ›'
|
||||
first: '« first'
|
||||
last: 'last »'
|
||||
previous: '‹ Previous'
|
||||
next: 'Next ›'
|
||||
first: '« First'
|
||||
last: 'Last »'
|
||||
quantity: 9
|
||||
style:
|
||||
type: default
|
||||
|
@ -129,6 +129,14 @@ display:
|
|||
empty: { }
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- user.permissions
|
||||
cacheable: false
|
||||
feed_items:
|
||||
display_plugin: feed
|
||||
id: feed_items
|
||||
|
@ -139,3 +147,10 @@ display:
|
|||
display_description: ''
|
||||
defaults:
|
||||
arguments: true
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- user.permissions
|
||||
cacheable: false
|
||||
|
|
|
@ -63,10 +63,10 @@ display:
|
|||
offset: false
|
||||
offset_label: Offset
|
||||
tags:
|
||||
previous: '‹ previous'
|
||||
next: 'next ›'
|
||||
first: '« first'
|
||||
last: 'last »'
|
||||
previous: '‹ Previous'
|
||||
next: 'Next ›'
|
||||
first: '« First'
|
||||
last: 'Last »'
|
||||
quantity: 9
|
||||
style:
|
||||
type: default
|
||||
|
@ -141,7 +141,9 @@ display:
|
|||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
cacheable: false
|
||||
- url.query_args
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
feed_1:
|
||||
display_plugin: feed
|
||||
id: feed_1
|
||||
|
@ -398,7 +400,8 @@ display:
|
|||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
cacheable: false
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
|
@ -418,4 +421,6 @@ display:
|
|||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
cacheable: false
|
||||
- url.query_args
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
id: d6_aggregator_feed
|
||||
label: Drupal 6 aggregator feeds
|
||||
label: Aggregator feeds
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: d6_aggregator_feed
|
||||
plugin: aggregator_feed
|
||||
process:
|
||||
fid: fid
|
||||
title: title
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
id: d6_aggregator_item
|
||||
label: Drupal 6 aggregator items
|
||||
label: Aggregator items
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: d6_aggregator_item
|
||||
plugin: aggregator_item
|
||||
process:
|
||||
iid: iid
|
||||
fid:
|
||||
plugin: migration
|
||||
migration: d6_aggregator_feed
|
||||
source:
|
||||
- fid
|
||||
source: fid
|
||||
title: title
|
||||
link: link
|
||||
author: author
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
id: d6_aggregator_settings
|
||||
label: Drupal 6 aggregator configuration
|
||||
label: Aggregator configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
id: d7_aggregator_feed
|
||||
label: Aggregator feeds
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: aggregator_feed
|
||||
process:
|
||||
fid: fid
|
||||
title: title
|
||||
url: url
|
||||
refresh: refresh
|
||||
checked: checked
|
||||
queued: queued
|
||||
link: link
|
||||
description: description
|
||||
image: image
|
||||
etag: etag
|
||||
modified: modified
|
||||
destination:
|
||||
plugin: entity:aggregator_feed
|
|
@ -0,0 +1,23 @@
|
|||
id: d7_aggregator_item
|
||||
label: Aggregator items
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: aggregator_item
|
||||
process:
|
||||
iid: iid
|
||||
fid:
|
||||
plugin: migration
|
||||
migration: d7_aggregator_feed
|
||||
source: fid
|
||||
title: title
|
||||
link: link
|
||||
author: author
|
||||
description: description
|
||||
timestamp: timestamp
|
||||
guid: guid
|
||||
destination:
|
||||
plugin: entity:aggregator_item
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d7_aggregator_feed
|
|
@ -1,5 +1,5 @@
|
|||
id: d7_aggregator_settings
|
||||
label: Drupal 7 aggregator configuration
|
||||
label: Aggregator configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Drupal\aggregator\Controller;
|
|||
|
||||
use Drupal\Component\Utility\Xss;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\aggregator\FeedInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -24,17 +24,17 @@ class AggregatorController extends ControllerBase {
|
|||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
/**
|
||||
* Constructs a \Drupal\aggregator\Controller\AggregatorController object.
|
||||
*
|
||||
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
*/
|
||||
public function __construct(DateFormatter $date_formatter) {
|
||||
public function __construct(DateFormatterInterface $date_formatter) {
|
||||
$this->dateFormatter = $date_formatter;
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ class AggregatorController extends ControllerBase {
|
|||
'#type' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
'#empty' => $this->t('No feeds available. <a href="@link">Add feed</a>.', array('@link' => $this->url('aggregator.feed_add'))),
|
||||
'#empty' => $this->t('No feeds available. <a href=":link">Add feed</a>.', array(':link' => $this->url('aggregator.feed_add'))),
|
||||
);
|
||||
|
||||
return $build;
|
||||
|
|
|
@ -151,7 +151,7 @@ class Feed extends ContentEntityBase implements FeedInterface {
|
|||
'weight' => -5,
|
||||
))
|
||||
->setDisplayConfigurable('form', TRUE)
|
||||
->addConstraint('FeedTitle', []);
|
||||
->addConstraint('FeedTitle');
|
||||
|
||||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language code'))
|
||||
|
@ -173,7 +173,7 @@ class Feed extends ContentEntityBase implements FeedInterface {
|
|||
'weight' => -3,
|
||||
))
|
||||
->setDisplayConfigurable('form', TRUE)
|
||||
->addConstraint('FeedUrl', []);
|
||||
->addConstraint('FeedUrl');
|
||||
|
||||
$intervals = array(900, 1800, 3600, 7200, 10800, 21600, 32400, 43200, 64800, 86400, 172800, 259200, 604800, 1209600, 2419200);
|
||||
$period = array_map(array(\Drupal::service('date.formatter'), 'formatInterval'), array_combine($intervals, $intervals));
|
||||
|
@ -218,7 +218,7 @@ class Feed extends ContentEntityBase implements FeedInterface {
|
|||
|
||||
$fields['description'] = BaseFieldDefinition::create('string_long')
|
||||
->setLabel(t('Description'))
|
||||
->setDescription(t("The parent website's description that comes from the !description element in the feed.", array('!description' => '<description>')));
|
||||
->setDescription(t("The parent website's description that comes from the @description element in the feed.", array('@description' => '<description>')));
|
||||
|
||||
$fields['image'] = BaseFieldDefinition::create('uri')
|
||||
->setLabel(t('Image'))
|
||||
|
|
|
@ -22,7 +22,7 @@ class FeedAccessControlHandler extends EntityAccessControlHandler {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
switch ($operation) {
|
||||
case 'view':
|
||||
return AccessResult::allowedIfHasPermission($account, 'access news feeds');
|
||||
|
|
|
@ -52,8 +52,8 @@ class FeedViewBuilder extends EntityViewBuilder {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildComponents(array &$build, array $entities, array $displays, $view_mode, $langcode = NULL) {
|
||||
parent::buildComponents($build, $entities, $displays, $view_mode, $langcode);
|
||||
public function buildComponents(array &$build, array $entities, array $displays, $view_mode) {
|
||||
parent::buildComponents($build, $entities, $displays, $view_mode);
|
||||
|
||||
foreach ($entities as $id => $entity) {
|
||||
$bundle = $entity->bundle();
|
||||
|
@ -69,7 +69,7 @@ class FeedViewBuilder extends EntityViewBuilder {
|
|||
|
||||
$build[$id]['items'] = $this->entityManager
|
||||
->getViewBuilder('aggregator_item')
|
||||
->viewMultiple($items, $view_mode, $langcode);
|
||||
->viewMultiple($items, $view_mode, $entity->language()->getId());
|
||||
|
||||
if ($view_mode == 'full') {
|
||||
// Also add the pager.
|
||||
|
@ -114,7 +114,7 @@ class FeedViewBuilder extends EntityViewBuilder {
|
|||
$build[$id]['feed_icon'] = array(
|
||||
'#theme' => 'feed_icon',
|
||||
'#url' => $entity->getUrl(),
|
||||
'#title' => t('!title feed', array('!title' => $entity->label())),
|
||||
'#title' => t('@title feed', array('@title' => $entity->label())),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ class OpmlFeedAdd extends FormBase {
|
|||
'#title' => $this->t('Update interval'),
|
||||
'#default_value' => 3600,
|
||||
'#options' => $period,
|
||||
'#description' => $this->t('The length of time between feed updates. Requires a correctly configured <a href="@cron">cron maintenance task</a>.', array('@cron' => $this->url('system.status'))),
|
||||
'#description' => $this->t('The length of time between feed updates. Requires a correctly configured <a href=":cron">cron maintenance task</a>.', array(':cron' => $this->url('system.status'))),
|
||||
);
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
|
|
|
@ -17,8 +17,8 @@ class ItemViewBuilder extends EntityViewBuilder {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildComponents(array &$build, array $entities, array $displays, $view_mode, $langcode = NULL) {
|
||||
parent::buildComponents($build, $entities, $displays, $view_mode, $langcode);
|
||||
public function buildComponents(array &$build, array $entities, array $displays, $view_mode) {
|
||||
parent::buildComponents($build, $entities, $displays, $view_mode);
|
||||
|
||||
foreach ($entities as $id => $entity) {
|
||||
$bundle = $entity->bundle();
|
||||
|
|
|
@ -54,7 +54,7 @@ class AggregatorTitleFormatter extends FormatterBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function viewElements(FieldItemListInterface $items) {
|
||||
public function viewElements(FieldItemListInterface $items, $langcode) {
|
||||
$elements = [];
|
||||
|
||||
if ($items->getEntity()->getEntityTypeId() == 'aggregator_feed') {
|
||||
|
|
|
@ -30,7 +30,7 @@ class AggregatorXSSFormatter extends FormatterBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function viewElements(FieldItemListInterface $items) {
|
||||
public function viewElements(FieldItemListInterface $items, $langcode) {
|
||||
$elements = [];
|
||||
|
||||
foreach ($items as $delta => $item) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\aggregator\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldConstraint;
|
||||
|
||||
/**
|
||||
* Supports validating feed titles.
|
||||
|
@ -17,15 +17,8 @@ use Symfony\Component\Validator\Constraint;
|
|||
* label = @Translation("Feed title", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class FeedTitleConstraint extends Constraint {
|
||||
class FeedTitleConstraint extends UniqueFieldConstraint {
|
||||
|
||||
public $message = 'A feed named %value already exists. Enter a unique title.';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validatedBy() {
|
||||
return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\aggregator\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldConstraint;
|
||||
|
||||
/**
|
||||
* Supports validating feed URLs.
|
||||
|
@ -17,15 +17,8 @@ use Symfony\Component\Validator\Constraint;
|
|||
* label = @Translation("Feed URL", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class FeedUrlConstraint extends Constraint {
|
||||
class FeedUrlConstraint extends UniqueFieldConstraint {
|
||||
|
||||
public $message = 'A feed with this URL %value already exists. Enter a unique URL.';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validatedBy() {
|
||||
return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use Drupal\aggregator\FeedInterface;
|
|||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Entity\Query\QueryInterface;
|
||||
use Drupal\Core\Form\ConfigFormBaseTrait;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
@ -61,7 +61,7 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor
|
|||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
|
@ -80,10 +80,10 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor
|
|||
* The entity query object for feed items.
|
||||
* @param \Drupal\aggregator\ItemStorageInterface $item_storage
|
||||
* The entity storage for feed items.
|
||||
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, QueryInterface $item_query, ItemStorageInterface $item_storage, DateFormatter $date_formatter) {
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, QueryInterface $item_query, ItemStorageInterface $item_storage, DateFormatterInterface $date_formatter) {
|
||||
$this->configFactory = $config;
|
||||
$this->itemStorage = $item_storage;
|
||||
$this->itemQuery = $item_query;
|
||||
|
@ -154,7 +154,7 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor
|
|||
'#title' => t('Discard items older than'),
|
||||
'#default_value' => $config->get('items.expire'),
|
||||
'#options' => $period,
|
||||
'#description' => t('Requires a correctly configured <a href="@cron">cron maintenance task</a>.', array('@cron' => $this->url('system.status'))),
|
||||
'#description' => t('Requires a correctly configured <a href=":cron">cron maintenance task</a>.', array(':cron' => $this->url('system.status'))),
|
||||
);
|
||||
|
||||
$lengths = array(0, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000);
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\aggregator\Plugin\migrate\source\d6\AggregatorFeed.
|
||||
* Contains \Drupal\aggregator\Plugin\migrate\source\AggregatorFeed.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Plugin\migrate\source\d6;
|
||||
namespace Drupal\aggregator\Plugin\migrate\source;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 6 feed source from database.
|
||||
* Drupal feed source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_aggregator_feed",
|
||||
* id = "aggregator_feed",
|
||||
* source_provider = "aggregator"
|
||||
* )
|
||||
*/
|
||||
|
@ -23,30 +23,15 @@ class AggregatorFeed extends DrupalSqlBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->select('aggregator_feed', 'af')
|
||||
->fields('af', array(
|
||||
'fid',
|
||||
'title',
|
||||
'url',
|
||||
'refresh',
|
||||
'checked',
|
||||
'link',
|
||||
'description',
|
||||
'image',
|
||||
'etag',
|
||||
'modified',
|
||||
'block',
|
||||
));
|
||||
|
||||
$query->orderBy('fid');
|
||||
return $query;
|
||||
return $this->select('aggregator_feed', 'af')
|
||||
->fields('af');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return array(
|
||||
$fields = array(
|
||||
'fid' => $this->t('The feed ID.'),
|
||||
'title' => $this->t('Title of the feed.'),
|
||||
'url' => $this->t('URL to the feed.'),
|
||||
|
@ -59,6 +44,10 @@ class AggregatorFeed extends DrupalSqlBase {
|
|||
'modified' => $this->t('When the feed was last modified.'),
|
||||
'block' => $this->t("Number of items to display in the feed's block."),
|
||||
);
|
||||
if ($this->getModuleSchemaVersion('system') >= 7000) {
|
||||
$fields['queued'] = $this->t('Time when this feed was queued for refresh, 0 if not queued.');
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\aggregator\Plugin\migrate\source\d6\AggregatorItem.
|
||||
* Contains \Drupal\aggregator\Plugin\migrate\source\AggregatorItem.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Plugin\migrate\source\d6;
|
||||
namespace Drupal\aggregator\Plugin\migrate\source;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 6 aggregator item source from database.
|
||||
* Drupal aggregator item source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_aggregator_item",
|
||||
* id = "aggregator_item",
|
||||
* source_provider = "aggregator"
|
||||
* )
|
||||
*/
|
||||
|
@ -23,11 +23,9 @@ class AggregatorItem extends DrupalSqlBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->select('aggregator_item', 'ai')
|
||||
->fields('ai', array('iid', 'fid', 'title', 'link', 'author',
|
||||
'description', 'timestamp', 'guid'))
|
||||
return $this->select('aggregator_item', 'ai')
|
||||
->fields('ai')
|
||||
->orderBy('iid');
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
use Drupal\Component\Utility\Html;
|
||||
|
||||
/**
|
||||
* Add feed test.
|
||||
|
@ -13,6 +14,13 @@ namespace Drupal\aggregator\Tests;
|
|||
* @group aggregator
|
||||
*/
|
||||
class AddFeedTest extends AggregatorTestBase {
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and ensures that a feed is unique, checks source, and deletes feed.
|
||||
*/
|
||||
|
@ -44,6 +52,23 @@ class AddFeedTest extends AggregatorTestBase {
|
|||
$this->deleteFeed($feed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the feed label is escaping when rendering the feed icon.
|
||||
*/
|
||||
public function testFeedLabelEscaping() {
|
||||
$feed = $this->createFeed(NULL, ['title[0][value]' => 'Test feed title <script>alert(123);</script>']);
|
||||
$this->checkForMetaRefresh();
|
||||
|
||||
$this->drupalGet('aggregator/sources/' . $feed->id());
|
||||
$this->assertResponse(200);
|
||||
|
||||
$result = $this->xpath('//h1');
|
||||
$this->assertEqual((string) $result[0], 'Test feed title alert(123);');
|
||||
|
||||
// Ensure the feed icon title is escaped.
|
||||
$this->assertTrue(strpos(str_replace(["\n", "\r"], '', $this->getRawContent()), 'class="feed-icon"> Subscribe to Test feed title <script>alert(123);</script> feed</a>') !== FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests feeds with very long URLs.
|
||||
*/
|
||||
|
|
|
@ -23,6 +23,12 @@ class AggregatorRenderingTest extends AggregatorTestBase {
|
|||
*/
|
||||
public static $modules = array('block', 'test_page_test');
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a feed block to the page and checks its links.
|
||||
*/
|
||||
|
|
|
@ -66,7 +66,7 @@ abstract class AggregatorTestBase extends WebTestBase {
|
|||
public function createFeed($feed_url = NULL, array $edit = array()) {
|
||||
$edit = $this->getFeedEditArray($feed_url, $edit);
|
||||
$this->drupalPostForm('aggregator/sources/add', $edit, t('Save'));
|
||||
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title[0][value]'])), format_string('The feed !name has been added.', array('!name' => $edit['title[0][value]'])));
|
||||
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title[0][value]'])), format_string('The feed @name has been added.', array('@name' => $edit['title[0][value]'])));
|
||||
|
||||
$fid = db_query("SELECT fid FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $edit['title[0][value]'], ':url' => $edit['url[0][value]']))->fetchField();
|
||||
$this->assertTrue(!empty($fid), 'The feed found in database.');
|
||||
|
@ -185,7 +185,7 @@ abstract class AggregatorTestBase extends WebTestBase {
|
|||
|
||||
if ($expected_count !== NULL) {
|
||||
$feed->item_count = count($feed->items);
|
||||
$this->assertEqual($expected_count, $feed->item_count, format_string('Total items in feed equal to the total items in database (!val1 != !val2)', array('!val1' => $expected_count, '!val2' => $feed->item_count)));
|
||||
$this->assertEqual($expected_count, $feed->item_count, format_string('Total items in feed equal to the total items in database (@val1 != @val2)', array('@val1' => $expected_count, '@val2' => $feed->item_count)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ class AggregatorTitleTest extends KernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('file', 'field', 'options', 'aggregator', 'entity_reference');
|
||||
public static $modules = ['file', 'field', 'options', 'aggregator'];
|
||||
|
||||
/**
|
||||
* The field name that is tested.
|
||||
|
|
|
@ -20,11 +20,9 @@ class MigrateAggregatorConfigsTest extends MigrateDrupal6TestBase {
|
|||
use SchemaCheckTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('aggregator');
|
||||
public static $modules = ['aggregator'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -11,13 +11,16 @@ use Drupal\aggregator\Entity\Feed;
|
|||
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Upgrade variables to aggregator_feed entities.
|
||||
* Tests migration of aggregator feeds.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateAggregatorFeedTest extends MigrateDrupal6TestBase {
|
||||
|
||||
static $modules = array('aggregator');
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['aggregator'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -32,9 +35,8 @@ class MigrateAggregatorFeedTest extends MigrateDrupal6TestBase {
|
|||
* Tests migration of aggregator feeds.
|
||||
*/
|
||||
public function testAggregatorFeedImport() {
|
||||
/** @var Feed $feed */
|
||||
/** @var \Drupal\aggregator\Entity\Feed $feed */
|
||||
$feed = Feed::load(5);
|
||||
$this->assertNotNull($feed->uuid());
|
||||
$this->assertIdentical('Know Your Meme', $feed->title->value);
|
||||
$this->assertIdentical('en', $feed->language()->getId());
|
||||
$this->assertIdentical('http://knowyourmeme.com/newsfeed.rss', $feed->url->value);
|
||||
|
|
|
@ -11,13 +11,16 @@ use Drupal\aggregator\Entity\Item;
|
|||
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Upgrade aggregator items.
|
||||
* Tests migration of aggregator items.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateAggregatorItemTest extends MigrateDrupal6TestBase {
|
||||
|
||||
static $modules = array('aggregator');
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['aggregator'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -26,33 +29,14 @@ class MigrateAggregatorItemTest extends MigrateDrupal6TestBase {
|
|||
parent::setUp();
|
||||
$this->installEntitySchema('aggregator_feed');
|
||||
$this->installEntitySchema('aggregator_item');
|
||||
|
||||
// Add some id mappings for the dependant migrations.
|
||||
$id_mappings = array(
|
||||
'd6_aggregator_feed' => array(
|
||||
array(array(5), array(5)),
|
||||
),
|
||||
);
|
||||
$this->prepareMigrations($id_mappings);
|
||||
|
||||
$entity = entity_create('aggregator_feed', array(
|
||||
'fid' => 5,
|
||||
'title' => 'Drupal Core',
|
||||
'url' => 'https://groups.drupal.org/not_used/167169',
|
||||
'refresh' => 900,
|
||||
'checked' => 1389919932,
|
||||
'description' => 'Drupal Core Group feed',
|
||||
));
|
||||
$entity->enforceIsNew();
|
||||
$entity->save();
|
||||
$this->executeMigration('d6_aggregator_item');
|
||||
$this->executeMigrations(['d6_aggregator_feed', 'd6_aggregator_item']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Drupal 6 aggregator item migration to Drupal 8.
|
||||
*/
|
||||
public function testAggregatorItem() {
|
||||
/** @var Item $item */
|
||||
/** @var \Drupal\aggregator\Entity\Item $item */
|
||||
$item = Item::load(1);
|
||||
$this->assertIdentical('1', $item->id());
|
||||
$this->assertIdentical('5', $item->getFeedId());
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\aggregator\Tests\Migrate\d7\MigrateAggregatorFeedTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests\Migrate\d7;
|
||||
|
||||
use Drupal\aggregator\Entity\Feed;
|
||||
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Test migration to aggregator_feed entities.
|
||||
*
|
||||
* @group aggregator
|
||||
*/
|
||||
class MigrateAggregatorFeedTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = array('aggregator');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('aggregator_feed');
|
||||
$this->executeMigration('d7_aggregator_feed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migration of aggregator feeds.
|
||||
*/
|
||||
public function testAggregatorFeedImport() {
|
||||
/** @var \Drupal\aggregator\Entity\Feed $feed */
|
||||
$feed = Feed::load(1);
|
||||
$this->assertIdentical('Know Your Meme', $feed->title->value);
|
||||
$this->assertIdentical('en', $feed->language()->getId());
|
||||
$this->assertIdentical('http://knowyourmeme.com/newsfeed.rss', $feed->url->value);
|
||||
$this->assertIdentical('900', $feed->refresh->value);
|
||||
$this->assertIdentical('1387659487', $feed->checked->value);
|
||||
$this->assertIdentical('0', $feed->queued->value);
|
||||
$this->assertIdentical('http://knowyourmeme.com', $feed->link->value);
|
||||
$this->assertIdentical('New items added to the News Feed', $feed->description->value);
|
||||
$this->assertIdentical('http://b.thumbs.redditmedia.com/harEHsUUZVajabtC.png', $feed->image->value);
|
||||
$this->assertIdentical('"213cc1365b96c310e92053c5551f0504"', $feed->etag->value);
|
||||
$this->assertIdentical('0', $feed->modified->value);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\aggregator\Tests\Migrate\d7\MigrateAggregatorItemTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests\Migrate\d7;
|
||||
|
||||
use Drupal\aggregator\Entity\Item;
|
||||
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of aggregator items.
|
||||
*
|
||||
* @group aggregator
|
||||
*/
|
||||
class MigrateAggregatorItemTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = array('aggregator');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('aggregator_feed');
|
||||
$this->installEntitySchema('aggregator_item');
|
||||
$this->executeMigration('d7_aggregator_feed');
|
||||
$this->executeMigration('d7_aggregator_item');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Drupal 7 aggregator item migration to Drupal 8.
|
||||
*/
|
||||
public function testAggregatorItem() {
|
||||
/** @var \Drupal\aggregator\Entity\Item $item */
|
||||
$item = Item::load(1);
|
||||
$this->assertIdentical('1', $item->id());
|
||||
$this->assertIdentical('1', $item->getFeedId());
|
||||
$this->assertIdentical('This (three) weeks in Drupal Core - January 10th 2014', $item->label());
|
||||
$this->assertIdentical('larowlan', $item->getAuthor());
|
||||
$this->assertIdentical("<h2 id='new'>What's new with Drupal 8?</h2>", $item->getDescription());
|
||||
$this->assertIdentical('https://groups.drupal.org/node/395218', $item->getLink());
|
||||
$this->assertIdentical('1389297196', $item->getPostedTime());
|
||||
$this->assertIdentical('en', $item->language()->getId());
|
||||
$this->assertIdentical('395218 at https://groups.drupal.org', $item->getGuid());
|
||||
}
|
||||
|
||||
}
|
|
@ -37,10 +37,10 @@ class UpdateFeedItemTest extends AggregatorTestBase {
|
|||
);
|
||||
|
||||
$this->drupalGet($edit['url[0][value]']);
|
||||
$this->assertResponse(array(200), format_string('URL !url is accessible', array('!url' => $edit['url[0][value]'])));
|
||||
$this->assertResponse(200);
|
||||
|
||||
$this->drupalPostForm('aggregator/sources/add', $edit, t('Save'));
|
||||
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title[0][value]'])), format_string('The feed !name has been added.', array('!name' => $edit['title[0][value]'])));
|
||||
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title[0][value]'])), format_string('The feed @name has been added.', array('@name' => $edit['title[0][value]'])));
|
||||
|
||||
$fid = db_query("SELECT fid FROM {aggregator_feed} WHERE url = :url", array(':url' => $edit['url[0][value]']))->fetchField();
|
||||
$feed = Feed::load($fid);
|
||||
|
@ -62,7 +62,7 @@ class UpdateFeedItemTest extends AggregatorTestBase {
|
|||
$feed->refreshItems();
|
||||
|
||||
$after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->id()))->fetchField();
|
||||
$this->assertTrue($before === $after, format_string('Publish timestamp of feed item was not updated (!before === !after)', array('!before' => $before, '!after' => $after)));
|
||||
$this->assertTrue($before === $after, format_string('Publish timestamp of feed item was not updated (@before === @after)', array('@before' => $before, '@after' => $after)));
|
||||
|
||||
// Make sure updating items works even after uninstalling a module
|
||||
// that provides the selected plugins.
|
||||
|
|
|
@ -2,28 +2,26 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\aggregator\Unit\Plugin\migrate\source\d6\AggregatorItemTest.
|
||||
* Contains \Drupal\Tests\aggregator\Unit\Plugin\migrate\source\AggregatorItemTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\aggregator\Unit\Plugin\migrate\source\d6;
|
||||
namespace Drupal\Tests\aggregator\Unit\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests D6 aggregator item source plugin.
|
||||
* Tests aggregator item source plugin.
|
||||
*
|
||||
* @group aggregator
|
||||
*/
|
||||
class AggregatorItemTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\aggregator\Plugin\migrate\source\d6\AggregatorItem';
|
||||
const PLUGIN_CLASS = 'Drupal\aggregator\Plugin\migrate\source\AggregatorItem';
|
||||
|
||||
// The fake Migration configuration entity.
|
||||
protected $migrationConfiguration = array(
|
||||
// The ID of the entity, can be any string.
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'd6_aggregator_item',
|
||||
'plugin' => 'aggregator_item',
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -40,16 +38,12 @@ class AggregatorItemTest extends MigrateSqlSourceTestCase {
|
|||
),
|
||||
);
|
||||
|
||||
protected $databaseContents = array('aggregator_item' => array(array(
|
||||
'iid' => 1,
|
||||
'fid' => 1,
|
||||
'title' => 'This (three) weeks in Drupal Core - January 10th 2014',
|
||||
'link' => 'https://groups.drupal.org/node/395218',
|
||||
'author' => 'larowlan',
|
||||
'description' => "<h2 id='new'>What's new with Drupal 8?</h2>",
|
||||
'timestamp' => 1389297196,
|
||||
'guid' => '395218 at https://groups.drupal.org',
|
||||
),
|
||||
));
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['aggregator_item'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,7 @@ use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
|||
*/
|
||||
class AggregatorFeedTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\aggregator\Plugin\migrate\source\d6\AggregatorFeed';
|
||||
const PLUGIN_CLASS = 'Drupal\aggregator\Plugin\migrate\source\AggregatorFeed';
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
|
@ -58,9 +58,7 @@ class AggregatorFeedTest extends MigrateSqlSourceTestCase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
foreach ($this->expectedResults as $k => $row) {
|
||||
$this->databaseContents['aggregator_feed'][$k] = $row;
|
||||
}
|
||||
$this->databaseContents['aggregator_feed'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\aggregator\Unit\Plugin\migrate\source\d7\AggregatorFeedTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\aggregator\Unit\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests D7 aggregator feed source plugin.
|
||||
*
|
||||
* @group aggregator
|
||||
*/
|
||||
class AggregatorFeedTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\aggregator\Plugin\migrate\source\AggregatorFeed';
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'd7_aggregator_feed',
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'fid' => 1,
|
||||
'title' => 'feed title 1',
|
||||
'url' => 'http://example.com/feed.rss',
|
||||
'refresh' => 900,
|
||||
'checked' => 0,
|
||||
'queued' => 0,
|
||||
'link' => 'http://example.com',
|
||||
'description' => 'A vague description',
|
||||
'image' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
'block' => 5,
|
||||
),
|
||||
array(
|
||||
'fid' => 2,
|
||||
'title' => 'feed title 2',
|
||||
'url' => 'http://example.net/news.rss',
|
||||
'refresh' => 1800,
|
||||
'checked' => 0,
|
||||
'queued' => 0,
|
||||
'link' => 'http://example.net',
|
||||
'description' => 'An even more vague description',
|
||||
'image' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
'block' => 5,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['aggregator_feed'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
6
core/modules/automated_cron/automated_cron.info.yml
Normal file
6
core/modules/automated_cron/automated_cron.info.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
name: 'Automated Cron'
|
||||
type: module
|
||||
description: 'Provides an automated way to run cron jobs, by executing them at the end of a server response.'
|
||||
package: Core
|
||||
version: VERSION
|
||||
core: 8.x
|
74
core/modules/automated_cron/automated_cron.module
Normal file
74
core/modules/automated_cron/automated_cron.module
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides an automated cron by executing it at the end of a response.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function automated_cron_help($route_name, RouteMatchInterface $route_match) {
|
||||
switch ($route_name) {
|
||||
case 'help.page.automated_cron':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Automated Cron module runs cron operations for your site using normal browser/page requests instead of having to set up a separate cron job. The Automated Cron module checks at the end of each server response when cron operation was last ran and, if it has been too long since last run, it executes the cron tasks after sending a server response. For more information, see the <a href=":automated_cron-documentation">online documentation for the Automated Cron module</a>.', [':automated_cron-documentation' => 'https://www.drupal.org/documentation/modules/automated_cron']) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Configuring Automated Cron') . '</dt>';
|
||||
$output .= '<dd>' . t('On the <a href=":cron-settings">Cron page</a>, you can set the frequency (time interval) for running cron jobs.', [':cron-settings' => \Drupal::url('system.cron_settings')]) . '</dd>';
|
||||
$output .= '<dt>' . t('Disabling Automated Cron') . '</dt>';
|
||||
$output .= '<dd>' . t('To disable automated cron, the recommended method is to uninstall the module, to reduce site overhead. If you only want to disable it temporarily, you can set the frequency to Never on the Cron page, and then change the frequency back when you want to start it up again.') . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter() for the system_cron_settings() form.
|
||||
*/
|
||||
function automated_cron_form_system_cron_settings_alter(&$form, &$form_state) {
|
||||
$automated_cron_settings = \Drupal::config('automated_cron.settings');
|
||||
|
||||
// Add automated cron settings.
|
||||
$form['automated_cron'] = [
|
||||
'#title' => t('Cron settings'),
|
||||
'#type' => 'details',
|
||||
'#open' => TRUE,
|
||||
];
|
||||
$options = [3600, 10800, 21600, 43200, 86400, 604800];
|
||||
$form['automated_cron']['interval'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => t('Run cron every'),
|
||||
'#description' => t('More information about setting up scheduled tasks can be found by <a href="@url">reading the cron tutorial on drupal.org</a>.', ['@url' => 'https://www.drupal.org/cron']),
|
||||
'#default_value' => $automated_cron_settings->get('interval'),
|
||||
'#options' => [0 => t('Never')] + array_map([\Drupal::service('date.formatter'), 'formatInterval'], array_combine($options, $options)),
|
||||
];
|
||||
|
||||
$form['actions']['#type'] = 'actions';
|
||||
$form['actions']['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save configuration'),
|
||||
'#button_type' => 'primary',
|
||||
];
|
||||
|
||||
// Add submit callback.
|
||||
$form['#submit'][] = 'automated_cron_settings_submit';
|
||||
|
||||
// Theme this form as a config form.
|
||||
$form['#theme'] = 'system_config_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for system_cron_settings().
|
||||
*/
|
||||
function automated_cron_settings_submit(array $form, FormStateInterface $form_state) {
|
||||
\Drupal::configFactory()->getEditable('automated_cron.settings')
|
||||
->set('interval', $form_state->getValue('interval'))
|
||||
->save();
|
||||
drupal_set_message(t('The configuration options have been saved.'));
|
||||
}
|
6
core/modules/automated_cron/automated_cron.services.yml
Normal file
6
core/modules/automated_cron/automated_cron.services.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
services:
|
||||
automated_cron.subscriber:
|
||||
class: Drupal\automated_cron\EventSubscriber\AutomatedCron
|
||||
arguments: ['@cron', '@config.factory', '@state']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
|
@ -0,0 +1 @@
|
|||
interval: 10800
|
|
@ -0,0 +1,9 @@
|
|||
# Schema for the configuration files of the Automated cron module.
|
||||
|
||||
automated_cron.settings:
|
||||
type: config_object
|
||||
label: 'Automated cron settings'
|
||||
mapping:
|
||||
interval:
|
||||
type: integer
|
||||
label: 'Run cron every'
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\EventSubscriber\AutomaticCron.
|
||||
* Contains \Drupal\automated_cron\EventSubscriber\AutomatedCron.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\EventSubscriber;
|
||||
namespace Drupal\automated_cron\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\CronInterface;
|
||||
|
@ -15,9 +15,9 @@ use Symfony\Component\HttpKernel\Event\PostResponseEvent;
|
|||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* A subscriber running cron when a request terminates.
|
||||
* A subscriber running cron after a response is sent.
|
||||
*/
|
||||
class AutomaticCron implements EventSubscriberInterface {
|
||||
class AutomatedCron implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The cron service.
|
||||
|
@ -36,43 +36,38 @@ class AutomaticCron implements EventSubscriberInterface {
|
|||
/**
|
||||
* The state key value store.
|
||||
*
|
||||
* Drupal\Core\State\StateInterface;
|
||||
* @var \Drupal\Core\State\StateInterface;
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Construct a new automatic cron runner.
|
||||
* Constructs a new automated cron runner.
|
||||
*
|
||||
* @param \Drupal\Core\CronInterface $cron
|
||||
* The cron service.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory.
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state key value store.
|
||||
* The state key-value store service.
|
||||
*/
|
||||
public function __construct(CronInterface $cron, ConfigFactoryInterface $config_factory, StateInterface $state) {
|
||||
$this->cron = $cron;
|
||||
$this->config = $config_factory->get('system.cron');
|
||||
$this->config = $config_factory->get('automated_cron.settings');
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the automated cron if enabled.
|
||||
*
|
||||
* @param Symfony\Component\HttpKernel\Event\PostResponseEvent $event
|
||||
* @param \Symfony\Component\HttpKernel\Event\PostResponseEvent $event
|
||||
* The Event to process.
|
||||
*/
|
||||
public function onTerminate(PostResponseEvent $event) {
|
||||
// If the site is not fully installed, suppress the automated cron run.
|
||||
// Otherwise it could be triggered prematurely by Ajax requests during
|
||||
// installation.
|
||||
if ($this->state->get('install_task') == 'done') {
|
||||
$threshold = $this->config->get('threshold.autorun');
|
||||
if ($threshold > 0) {
|
||||
$cron_next = $this->state->get('system.cron_last', 0) + $threshold;
|
||||
if (REQUEST_TIME > $cron_next) {
|
||||
$this->cron->run();
|
||||
}
|
||||
$interval = $this->config->get('interval');
|
||||
if ($interval > 0) {
|
||||
$cron_next = $this->state->get('system.cron_last', 0) + $interval;
|
||||
if ((int) $event->getRequest()->server->get('REQUEST_TIME') > $cron_next) {
|
||||
$this->cron->run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,9 +79,7 @@ class AutomaticCron implements EventSubscriberInterface {
|
|||
* An array of event listener definitions.
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
|
||||
|
||||
return $events;
|
||||
return [KernelEvents::TERMINATE => [['onTerminate', 100]]];
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
ban.admin_page:
|
||||
title: 'IP address bans'
|
||||
description: 'Manage banned IP addresses.'
|
||||
description: 'Ban visits from specific IP addresses.'
|
||||
route_name: ban.admin_page
|
||||
weight: 10
|
||||
parent: user.admin_index
|
||||
|
|
|
@ -15,11 +15,11 @@ function ban_help($route_name, RouteMatchInterface $route_match) {
|
|||
case 'help.page.ban':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Ban module allows administrators to ban visits to their site from individual IP addresses. For more information, see <a href="!url">the online documentation for the Ban module</a>.', array('!url' => 'https://www.drupal.org/documentation/modules/ban')) . '</p>';
|
||||
$output .= '<p>' . t('The Ban module allows administrators to ban visits to their site from individual IP addresses. For more information, see the <a href=":url">online documentation for the Ban module</a>.', array(':url' => 'https://www.drupal.org/documentation/modules/ban')) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Banning IP addresses') . '</dt>';
|
||||
$output .= '<dd>' . t('Administrators can enter IP addresses to ban on the <a href="!bans">IP address bans</a> page.', array('!bans' => \Drupal::url('ban.admin_page'))) . '</dd>';
|
||||
$output .= '<dd>' . t('Administrators can enter IP addresses to ban on the <a href=":bans">IP address bans</a> page.', array(':bans' => \Drupal::url('ban.admin_page'))) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
id: d7_blocked_ips
|
||||
label: Drupal 7 blocked IPs
|
||||
label: Blocked IPs
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
|
|
|
@ -50,7 +50,7 @@ class BanMiddleware implements HttpKernelInterface {
|
|||
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
|
||||
$ip = $request->getClientIp();
|
||||
if ($this->banIpManager->isBanned($ip)) {
|
||||
return new Response(SafeMarkup::format('Sorry @ip has been banned', ['@ip' => $ip]), 403);
|
||||
return new Response(SafeMarkup::format('@ip has been banned', ['@ip' => $ip]), 403);
|
||||
}
|
||||
return $this->httpKernel->handle($request, $type, $catch);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ function basic_auth_help($route_name, RouteMatchInterface $route_match) {
|
|||
case 'help.page.basic_auth':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The HTTP Basic Authentication module supplies an <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">HTTP Basic authentication</a> provider for web service requests. This authentication provider authenticates requests using the HTTP Basic Authentication username and password, as an alternative to using Drupal\'s standard cookie-based authentication system. It is only useful if your site provides web services configured to use this type of authentication (for instance, the <a href="!rest_help">RESTful Web Services module</a>). For more information, see <a href="!hba_do">the online documentation for the HTTP Basic Authentication module</a>.', array('!hba_do' => 'https://www.drupal.org/documentation/modules/basic_auth', '!rest_help' => (\Drupal::moduleHandler()->moduleExists('rest')) ? \Drupal::url('help.page', array('name' => 'rest')) : '#')) . '</p>';
|
||||
$output .= '<p>' . t('The HTTP Basic Authentication module supplies an <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">HTTP Basic authentication</a> provider for web service requests. This authentication provider authenticates requests using the HTTP Basic Authentication username and password, as an alternative to using Drupal\'s standard cookie-based authentication system. It is only useful if your site provides web services configured to use this type of authentication (for instance, the <a href=":rest_help">RESTful Web Services module</a>). For more information, see the <a href=":hba_do">online documentation for the HTTP Basic Authentication module</a>.', array(':hba_do' => 'https://www.drupal.org/documentation/modules/basic_auth', ':rest_help' => (\Drupal::moduleHandler()->moduleExists('rest')) ? \Drupal::url('help.page', array('name' => 'rest')) : '#')) . '</p>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ class BasicAuth implements AuthenticationProviderInterface, AuthenticationProvid
|
|||
$challenge = SafeMarkup::format('Basic realm="@realm"', array(
|
||||
'@realm' => !empty($site_name) ? $site_name : 'Access restricted',
|
||||
));
|
||||
return new UnauthorizedHttpException($challenge, 'No authentication credentials provided.', $previous);
|
||||
return new UnauthorizedHttpException((string) $challenge, 'No authentication credentials provided.', $previous);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -193,8 +193,6 @@ function hook_block_build_BASE_BLOCK_ID_alter(array &$build, \Drupal\Core\Block\
|
|||
* The operation to be performed, e.g., 'view', 'create', 'delete', 'update'.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user object to perform the access check operation on.
|
||||
* @param string $langcode
|
||||
* The language code to perform the access check operation on.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result. If all implementations of this hook return
|
||||
|
@ -206,7 +204,7 @@ function hook_block_build_BASE_BLOCK_ID_alter(array &$build, \Drupal\Core\Block\
|
|||
* @see \Drupal\block\BlockAccessControlHandler::checkAccess()
|
||||
* @ingroup block_api
|
||||
*/
|
||||
function hook_block_access(\Drupal\block\Entity\Block $block, $operation, \Drupal\Core\Session\AccountInterface $account, $langcode) {
|
||||
function hook_block_access(\Drupal\block\Entity\Block $block, $operation, \Drupal\Core\Session\AccountInterface $account) {
|
||||
// Example code that would prevent displaying the 'Powered by Drupal' block in
|
||||
// a region different than the footer.
|
||||
if ($operation == 'view' && $block->getPluginId() == 'system_powered_by_block') {
|
||||
|
|
|
@ -45,8 +45,9 @@ function block_update_8001() {
|
|||
}
|
||||
|
||||
// Contributed modules should leverage hook_update_dependencies() in order to
|
||||
// be executed before block_update_8002(), so they can update their context
|
||||
// mappings, if wanted.
|
||||
// be executed after block_update_8001(). The blocks are then disabled if the
|
||||
// contexts are still missing via
|
||||
// block_post_update_disable_blocks_with_missing_contexts().
|
||||
$config_factory = \Drupal::configFactory();
|
||||
$backup_values = $update_backup = [];
|
||||
|
||||
|
@ -95,50 +96,31 @@ function block_update_8001() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Disable all blocks with missing context IDs in block_update_8001().
|
||||
* Placeholder for the previous 8002 update.
|
||||
*/
|
||||
function block_update_8002() {
|
||||
$block_update_8001 = \Drupal::keyValue('update_backup')->get('block_update_8001', []);
|
||||
\Drupal::state()->set('block_update_8002_placeholder', TRUE);
|
||||
}
|
||||
|
||||
$block_ids = array_keys($block_update_8001);
|
||||
/**
|
||||
* Remove 'cache' setting.
|
||||
*/
|
||||
function block_update_8003() {
|
||||
$config_factory = \Drupal::configFactory();
|
||||
/** @var \Drupal\Core\Config\Config[] $blocks */
|
||||
$blocks = [];
|
||||
foreach ($block_ids as $block_id) {
|
||||
$blocks[$block_id] = $block = $config_factory->getEditable('block.block.' . $block_id);
|
||||
// This block will have an invalid context mapping service and must be
|
||||
// disabled in order to prevent information disclosure.
|
||||
foreach ($config_factory->listAll('block.block.') as $block_config_name) {
|
||||
$block = $config_factory->getEditable($block_config_name);
|
||||
|
||||
// Disable currently enabled blocks.
|
||||
if ($block_update_8001[$block_id]['status']) {
|
||||
$block->set('status', FALSE);
|
||||
$block->save(TRUE);
|
||||
}
|
||||
// Remove the 'cache' setting.
|
||||
$settings = $block->get('settings');
|
||||
unset($settings['cache']);
|
||||
$block->set('settings', $settings);
|
||||
|
||||
// Mark the resulting configuration as trusted data. This avoids issues with
|
||||
// future schema changes.
|
||||
$block->save(TRUE);
|
||||
}
|
||||
|
||||
// Provides a list of plugin labels, keyed by plugin ID.
|
||||
$condition_plugin_id_label_map = array_column(\Drupal::service('plugin.manager.condition')->getDefinitions(), 'label', 'id');
|
||||
|
||||
// Override with the UI labels we are aware of. Sadly they are not machine
|
||||
// accessible, see
|
||||
// \Drupal\node\Plugin\Condition\NodeType::buildConfigurationForm().
|
||||
$condition_plugin_id_label_map['node_type'] = t('Content types');
|
||||
$condition_plugin_id_label_map['request_path'] = t('Pages');
|
||||
$condition_plugin_id_label_map['user_role'] = t('Roles');
|
||||
|
||||
if (count($block_ids) > 0) {
|
||||
$message = t('Encountered an unknown context mapping key coming probably from a contributed or custom module: One or more mappings could not be updated. Please manually review your visibility settings for the following blocks, which are disabled now:');
|
||||
$message .= '<ul>';
|
||||
foreach ($blocks as $disabled_block_id => $disabled_block) {
|
||||
$message .= '<li>' . t('@label (Visibility: @plugin_ids)', array(
|
||||
'@label' => $disabled_block->get('settings.label'),
|
||||
'@plugin_ids' => implode(', ', array_intersect_key($condition_plugin_id_label_map, array_flip(array_keys($block_update_8001[$disabled_block_id]['missing_context_ids']))))
|
||||
)) . '</li>';
|
||||
}
|
||||
$message .= '</ul>';
|
||||
|
||||
return $message;
|
||||
}
|
||||
return t('Block settings updated.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,28 +22,28 @@ function block_help($route_name, RouteMatchInterface $route_match) {
|
|||
$block_content = \Drupal::moduleHandler()->moduleExists('block_content') ? \Drupal::url('help.page', array('name' => 'block_content')) : '#';
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Block module allows you to place blocks in regions of your installed themes, and configure block settings. For more information, see the <a href="!blocks-documentation">online documentation for the Block module</a>.', array('!blocks-documentation' => 'https://www.drupal.org/documentation/modules/block/')) . '</p>';
|
||||
$output .= '<p>' . t('The Block module allows you to place blocks in regions of your installed themes, and configure block settings. For more information, see the <a href=":blocks-documentation">online documentation for the Block module</a>.', array(':blocks-documentation' => 'https://www.drupal.org/documentation/modules/block/')) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Placing and moving blocks') . '</dt>';
|
||||
$output .= '<dd>' . t('You can place a new block by clicking on its title in the <em>Place blocks</em> list on the <a href="!blocks">Block layout page</a> and choosing a region to place it in. Once a block is placed, it can be moved to a different region by dragging or using the drop-down <em>Region</em> list, and then clicking <em>Save blocks</em>.', array('!blocks' => \Drupal::url('block.admin_display'))) . '</dd>';
|
||||
$output .= '<dd>' . t('You can place a new block in a region by selecting <em>Place block</em> on the <a href=":blocks">Block layout page</a>. Once a block is placed, it can be moved to a different region by drag-and-drop or by using the <em>Region</em> drop-down list, and then clicking <em>Save blocks</em>.', array(':blocks' => \Drupal::url('block.admin_display'))) . '</dd>';
|
||||
$output .= '<dt>' . t('Toggling between different themes') . '</dt>';
|
||||
$output .= '<dd>' . t('Blocks are placed and configured specifically for each theme. The Block layout page opens with the default theme, but you can toggle to other installed themes.') . '</dd>';
|
||||
$output .= '<dt>' . t('Demonstrating block regions for a theme') . '</dt>';
|
||||
$output .= '<dd>' . t('You can see where the regions are for the current theme by clicking the <em>Demonstrate block regions</em> link on the <a href="!blocks">Block layout page</a>. Regions are specific to each theme.', array('!blocks' => \Drupal::url('block.admin_display'))) . '</dd>';
|
||||
$output .= '<dd>' . t('You can see where the regions are for the current theme by clicking the <em>Demonstrate block regions</em> link on the <a href=":blocks">Block layout page</a>. Regions are specific to each theme.', array(':blocks' => \Drupal::url('block.admin_display'))) . '</dd>';
|
||||
$output .= '<dt>' . t('Configuring block settings') . '</dt>';
|
||||
$output .= '<dd>' . t('To change the settings of an individual block click on the <em>Configure</em> link on the <a href="!blocks">Block layout page</a>. The available options vary depending on the module that provides the block. For all blocks you can change the block title and toggle whether to display it.', array('!blocks' => Drupal::url('block.admin_display'))) . '</dd>';
|
||||
$output .= '<dd>' . t('To change the settings of an individual block click on the <em>Configure</em> link on the <a href=":blocks">Block layout page</a>. The available options vary depending on the module that provides the block. For all blocks you can change the block title and toggle whether to display it.', array(':blocks' => Drupal::url('block.admin_display'))) . '</dd>';
|
||||
$output .= '<dt>' . t('Controlling visibility') . '</dt>';
|
||||
$output .= '<dd>' . t('You can control the visibility of a block by restricting it to specific pages, content types, and/or roles by setting the appropriate options under <em>Visibility settings</em> of the block configuration.') . '</dd>';
|
||||
$output .= '<dt>' . t('Adding custom blocks') . '</dt>';
|
||||
$output .= '<dd>' . t('You can add custom blocks, if the <em>Custom Block</em> module is installed. For more information, see the <a href="!blockcontent-help">Custom Block help page</a>.', array('!blockcontent-help' => $block_content)) . '</dd>';
|
||||
$output .= '<dd>' . t('You can add custom blocks, if the <em>Custom Block</em> module is installed. For more information, see the <a href=":blockcontent-help">Custom Block help page</a>.', array(':blockcontent-help' => $block_content)) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
}
|
||||
if ($route_name == 'block.admin_display' || $route_name == 'block.admin_display_theme') {
|
||||
$demo_theme = $route_match->getParameter('theme') ?: \Drupal::config('system.theme')->get('default');
|
||||
$themes = \Drupal::service('theme_handler')->listInfo();
|
||||
$output = '<p>' . t('This page provides a drag-and-drop interface for adding a block to a region, and for controlling the order of blocks within regions. To add a block to a region, or to configure its specific title and visibility settings, click the block title under <em>Place blocks</em>. Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the <em>Save blocks</em> button at the bottom of the page.') . '</p>';
|
||||
$output = '<p>' . t('Block placement is specific to each theme on your site. Changes will not be saved until you click <em>Save blocks</em> at the bottom of the page.') . '</p>';
|
||||
$output .= '<p>' . \Drupal::l(t('Demonstrate block regions (@theme)', array('@theme' => $themes[$demo_theme]->info['name'])), new Url('block.admin_demo', array('theme' => $demo_theme))) . '</p>';
|
||||
return $output;
|
||||
}
|
||||
|
|
79
core/modules/block/block.post_update.php
Normal file
79
core/modules/block/block.post_update.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Post update functions for Block.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup updates-8.0.0-beta
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Disable all blocks with missing context IDs in block_update_8001().
|
||||
*/
|
||||
function block_post_update_disable_blocks_with_missing_contexts() {
|
||||
// Don't execute the function if block_update_8002() got executed already,
|
||||
// which used to do the same. Note: Its okay to check here, because
|
||||
// update_do_one() does not update the installed schema version until the
|
||||
// batch is finished.
|
||||
$module_schema = drupal_get_installed_schema_version('block');
|
||||
|
||||
// The state entry 'block_update_8002_placeholder' is used in order to
|
||||
// indicate that the placeholder block_update_8002() function has been
|
||||
// executed, so this function needs to be executed as well. If the non
|
||||
// placeholder version of block_update_8002() got executed already, the state
|
||||
// won't be set and we skip this update.
|
||||
if ($module_schema >= 8002 && !\Drupal::state()->get('block_update_8002_placeholder', FALSE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cleanup the state entry as its no longer needed.
|
||||
\Drupal::state()->delete('block_update_8002');
|
||||
|
||||
$block_update_8001 = \Drupal::keyValue('update_backup')->get('block_update_8001', []);
|
||||
|
||||
$block_ids = array_keys($block_update_8001);
|
||||
$block_storage = \Drupal::entityManager()->getStorage('block');
|
||||
$blocks = $block_storage->loadMultiple($block_ids);
|
||||
/** @var $blocks \Drupal\block\BlockInterface[] */
|
||||
foreach ($blocks as $block) {
|
||||
// This block has had conditions removed due to an inability to resolve
|
||||
// contexts in block_update_8001() so disable it.
|
||||
|
||||
// Disable currently enabled blocks.
|
||||
if ($block_update_8001[$block->id()]['status']) {
|
||||
$block->setStatus(FALSE);
|
||||
$block->save();
|
||||
}
|
||||
}
|
||||
|
||||
// Provides a list of plugin labels, keyed by plugin ID.
|
||||
$condition_plugin_id_label_map = array_column(\Drupal::service('plugin.manager.condition')->getDefinitions(), 'label', 'id');
|
||||
|
||||
// Override with the UI labels we are aware of. Sadly they are not machine
|
||||
// accessible, see
|
||||
// \Drupal\node\Plugin\Condition\NodeType::buildConfigurationForm().
|
||||
$condition_plugin_id_label_map['node_type'] = t('Content types');
|
||||
$condition_plugin_id_label_map['request_path'] = t('Pages');
|
||||
$condition_plugin_id_label_map['user_role'] = t('Roles');
|
||||
|
||||
if (count($block_ids) > 0) {
|
||||
$message = t('Encountered an unknown context mapping key coming probably from a contributed or custom module: One or more mappings could not be updated. Please manually review your visibility settings for the following blocks, which are disabled now:');
|
||||
$message .= '<ul>';
|
||||
foreach ($blocks as $disabled_block_id => $disabled_block) {
|
||||
$message .= '<li>' . t('@label (Visibility: @plugin_ids)', array(
|
||||
'@label' => $disabled_block->get('settings')['label'],
|
||||
'@plugin_ids' => implode(', ', array_intersect_key($condition_plugin_id_label_map, array_flip(array_keys($block_update_8001[$disabled_block_id]['missing_context_ids']))))
|
||||
)) . '</li>';
|
||||
}
|
||||
$message .= '</ul>';
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-8.0.0-beta".
|
||||
*/
|
|
@ -1,8 +1,9 @@
|
|||
/* Block listing page */
|
||||
.region-title .button {
|
||||
.region-title__action {
|
||||
display: inline-block;
|
||||
margin-left: 1em; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .region-title .button {
|
||||
[dir="rtl"] .region-title__action {
|
||||
margin-left: 0;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
// Add a handler for when a row is swapped, update empty regions.
|
||||
tableDrag.row.prototype.onSwap = function (swappedRow) {
|
||||
checkEmptyRegions(table, this);
|
||||
updateLastPlaced(table, this);
|
||||
};
|
||||
|
||||
// Add a handler so when a row is dropped, update fields dropped into
|
||||
|
@ -132,10 +133,28 @@
|
|||
updateBlockWeights(table, select[0].value);
|
||||
// Modify empty regions with added or removed fields.
|
||||
checkEmptyRegions(table, row);
|
||||
// Update last placed block indication.
|
||||
updateLastPlaced(table, row);
|
||||
// Show unsaved changes warning.
|
||||
if (!tableDrag.changed) {
|
||||
$(Drupal.theme('tableDragChangedWarning')).insertBefore(tableDrag.table).hide().fadeIn('slow');
|
||||
tableDrag.changed = true;
|
||||
}
|
||||
// Remove focus from selectbox.
|
||||
select.trigger('blur');
|
||||
});
|
||||
|
||||
var updateLastPlaced = function ($table, rowObject) {
|
||||
// Remove the color-success class from new block if applicable.
|
||||
$table.find('.color-success').removeClass('color-success');
|
||||
|
||||
var $rowObject = $(rowObject);
|
||||
if (!$rowObject.is('.drag-previous')) {
|
||||
$table.find('.drag-previous').removeClass('drag-previous');
|
||||
$rowObject.addClass('drag-previous');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update block weights in the given region.
|
||||
*
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
id: d6_block
|
||||
label: Drupal 6 blocks
|
||||
label: Blocks
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: d6_block
|
||||
plugin: block
|
||||
process:
|
||||
# Drupal 8 does not have a status but it doesn't matter; this is here to
|
||||
# skip disabled blocks.
|
||||
# Block status is not a thing in Drupal 8, so this is how we skip over
|
||||
# disabled blocks.
|
||||
status:
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
|
@ -50,19 +50,22 @@ process:
|
|||
2: views_block:who_s_new-block_1
|
||||
3: views_block:who_s_online-who_s_online_block
|
||||
-
|
||||
plugin: d6_block_plugin_id
|
||||
plugin: block_plugin_id
|
||||
-
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
theme:
|
||||
plugin: d6_block_theme
|
||||
plugin: block_theme
|
||||
source:
|
||||
- theme
|
||||
- default_theme
|
||||
- admin_theme
|
||||
region:
|
||||
plugin: d6_block_region
|
||||
plugin: block_region
|
||||
source:
|
||||
- region
|
||||
- theme
|
||||
- @theme
|
||||
- '@theme'
|
||||
region_map:
|
||||
left: sidebar_first
|
||||
right: sidebar_second
|
||||
|
@ -74,17 +77,20 @@ process:
|
|||
label: title
|
||||
weight: weight
|
||||
settings:
|
||||
plugin: d6_block_settings
|
||||
plugin: block_settings
|
||||
source:
|
||||
- @plugin
|
||||
- '@plugin'
|
||||
- delta
|
||||
- settings
|
||||
visibility:
|
||||
plugin: d6_block_visibility
|
||||
plugin: block_visibility
|
||||
source:
|
||||
- visibility
|
||||
- pages
|
||||
- roles
|
||||
- visibility
|
||||
# If the block uses PHP visibility, don't migrate it unless the PHP module
|
||||
# is enabled.
|
||||
skip_php: true
|
||||
destination:
|
||||
plugin: entity:block
|
||||
migration_dependencies:
|
||||
|
|
100
core/modules/block/migration_templates/d7_block.yml
Executable file
100
core/modules/block/migration_templates/d7_block.yml
Executable file
|
@ -0,0 +1,100 @@
|
|||
id: d7_block
|
||||
label: Blocks
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: block
|
||||
process:
|
||||
# Block status is not a thing in Drupal 8, so this is how we skip over
|
||||
# disabled blocks.
|
||||
status:
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
source: status
|
||||
id:
|
||||
-
|
||||
plugin: concat
|
||||
source:
|
||||
- theme
|
||||
- module
|
||||
- delta
|
||||
delimiter: _
|
||||
plugin:
|
||||
-
|
||||
plugin: static_map
|
||||
bypass: true
|
||||
source:
|
||||
- module
|
||||
- delta
|
||||
map:
|
||||
book:
|
||||
navigation: book_navigation
|
||||
comment:
|
||||
recent: views_block:comments_recent-block_1
|
||||
forum:
|
||||
active: forum_active_block
|
||||
new: forum_new_block
|
||||
# locale:
|
||||
# 0: language_block
|
||||
node:
|
||||
syndicate: node_syndicate_block
|
||||
search:
|
||||
form: search_form_block
|
||||
statistics:
|
||||
popular: statistics_popular_block
|
||||
system:
|
||||
main: system_main_block
|
||||
'powered-by': system_powered_by_block
|
||||
user:
|
||||
login: user_login_block
|
||||
# 1: system_menu_block:tools
|
||||
new: views_block:who_s_new-block_1
|
||||
online: views_block:who_s_online-who_s_online_block
|
||||
-
|
||||
plugin: block_plugin_id
|
||||
-
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
theme:
|
||||
plugin: block_theme
|
||||
source:
|
||||
- theme
|
||||
- default_theme
|
||||
- admin_theme
|
||||
region:
|
||||
plugin: block_region
|
||||
source:
|
||||
- region
|
||||
- theme
|
||||
- '@theme'
|
||||
region_map:
|
||||
left: sidebar_first
|
||||
right: sidebar_second
|
||||
sidebar_first: sidebar_first
|
||||
sidebar_second: sidebar_second
|
||||
help: help
|
||||
header: header
|
||||
footer: footer
|
||||
label: title
|
||||
weight: weight
|
||||
settings:
|
||||
plugin: block_settings
|
||||
source:
|
||||
- '@plugin'
|
||||
- delta
|
||||
- settings
|
||||
visibility:
|
||||
plugin: block_visibility
|
||||
source:
|
||||
- visibility
|
||||
- pages
|
||||
- roles
|
||||
# If the block uses PHP visibility, don't migrate it unless the PHP module
|
||||
# is enabled.
|
||||
skip_php: true
|
||||
destination:
|
||||
plugin: entity:block
|
||||
migration_dependencies:
|
||||
optional:
|
||||
- d7_custom_block
|
||||
- d7_user_role
|
|
@ -88,10 +88,10 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
/** @var \Drupal\block\BlockInterface $entity */
|
||||
if ($operation != 'view') {
|
||||
return parent::checkAccess($entity, $operation, $langcode, $account);
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
|
||||
// Don't grant access to disabled blocks.
|
||||
|
|
|
@ -335,6 +335,12 @@ class BlockForm extends EntityForm {
|
|||
|
||||
// Call the plugin submit handler.
|
||||
$entity->getPlugin()->submitConfigurationForm($form, $settings);
|
||||
$block = $entity->getPlugin();
|
||||
// If this block is context-aware, set the context mapping.
|
||||
if ($block instanceof ContextAwarePluginInterface && $block->getContextDefinitions()) {
|
||||
$context_mapping = $settings->getValue('context_mapping', []);
|
||||
$block->setContextMapping($context_mapping);
|
||||
}
|
||||
// Update the original form values.
|
||||
$form_state->setValue('settings', $settings->getValues());
|
||||
|
||||
|
|
|
@ -214,6 +214,11 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
|
|||
),
|
||||
);
|
||||
$form['region-' . $region]['title'] = array(
|
||||
'#theme_wrappers' => array(
|
||||
'container' => array(
|
||||
'#attributes' => array('class' => 'region-title__action'),
|
||||
)
|
||||
),
|
||||
'#prefix' => $region != BlockInterface::BLOCK_REGION_NONE ? $title : $block_regions_with_disabled[$region],
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Place block <span class="visually-hidden">in the %region region</span>', ['%region' => $block_regions_with_disabled[$region]]),
|
||||
|
@ -256,7 +261,7 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
|
|||
),
|
||||
);
|
||||
if ($placement && $placement == Html::getClass($entity_id)) {
|
||||
$form[$entity_id]['#attributes']['class'][] = 'color-warning';
|
||||
$form[$entity_id]['#attributes']['class'][] = 'color-success';
|
||||
$form[$entity_id]['#attributes']['class'][] = 'js-block-placed';
|
||||
}
|
||||
$form[$entity_id]['info'] = array(
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Core\Block\MainContentBlockPluginInterface;
|
||||
use Drupal\Core\Block\TitleBlockPluginInterface;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
|
@ -16,6 +17,7 @@ use Drupal\Core\Entity\EntityViewBuilder;
|
|||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
|
@ -63,7 +65,7 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildComponents(array &$build, array $entities, array $displays, $view_mode, $langcode = NULL) {
|
||||
public function buildComponents(array &$build, array $entities, array $displays, $view_mode) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,12 +101,13 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
'tags' => $cache_tags,
|
||||
'max-age' => $plugin->getCacheMaxAge(),
|
||||
],
|
||||
'#weight' => $entity->getWeight(),
|
||||
);
|
||||
|
||||
// Allow altering of cacheability metadata or setting #create_placeholder.
|
||||
$this->moduleHandler->alter(['block_build', "block_build_" . $plugin->getBaseId()], $build[$entity_id], $plugin);
|
||||
|
||||
if ($plugin instanceof MainContentBlockPluginInterface) {
|
||||
if ($plugin instanceof MainContentBlockPluginInterface || $plugin instanceof TitleBlockPluginInterface) {
|
||||
// Immediately build a #pre_render-able block, since this block cannot
|
||||
// be built lazily.
|
||||
$build[$entity_id] += static::buildPreRenderableBlock($entity, $this->moduleHandler());
|
||||
|
@ -139,6 +142,12 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
$derivative_id = $plugin->getDerivativeId();
|
||||
$configuration = $plugin->getConfiguration();
|
||||
|
||||
// Inject runtime contexts.
|
||||
if ($plugin instanceof ContextAwarePluginInterface) {
|
||||
$contexts = \Drupal::service('context.repository')->getRuntimeContexts($plugin->getContextMapping());
|
||||
\Drupal::service('context.handler')->applyContextMapping($plugin, $contexts);
|
||||
}
|
||||
|
||||
// Create the render array for the block as a whole.
|
||||
// @see template_preprocess_block().
|
||||
$build = [
|
||||
|
@ -183,7 +192,7 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
* @return array
|
||||
* A render array with a #pre_render callback to render the block.
|
||||
*/
|
||||
public static function lazyBuilder($entity_id, $view_mode, $langcode) {
|
||||
public static function lazyBuilder($entity_id, $view_mode) {
|
||||
return static::buildPreRenderableBlock(entity_load('block', $entity_id), \Drupal::service('module_handler'));
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\block\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Extension\ThemeHandler;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
|
@ -55,7 +56,7 @@ class BlockController extends ControllerBase {
|
|||
*/
|
||||
public function demo($theme) {
|
||||
$page = [
|
||||
'#title' => $this->themeHandler->getName($theme),
|
||||
'#title' => Html::escape($this->themeHandler->getName($theme)),
|
||||
'#type' => 'page',
|
||||
'#attached' => array(
|
||||
'drupalSettings' => [
|
||||
|
|
|
@ -12,6 +12,7 @@ use Drupal\Core\Block\BlockManagerInterface;
|
|||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
|
||||
use Drupal\Core\Menu\LocalActionManagerInterface;
|
||||
use Drupal\Core\Plugin\Context\LazyContextRepository;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -29,6 +30,13 @@ class BlockLibraryController extends ControllerBase {
|
|||
*/
|
||||
protected $blockManager;
|
||||
|
||||
/**
|
||||
* The context repository.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\Context\LazyContextRepository
|
||||
*/
|
||||
protected $contextRepository;
|
||||
|
||||
/**
|
||||
* The route match.
|
||||
*
|
||||
|
@ -48,15 +56,18 @@ class BlockLibraryController extends ControllerBase {
|
|||
*
|
||||
* @param \Drupal\Core\Block\BlockManagerInterface $block_manager
|
||||
* The block manager.
|
||||
* @param \Drupal\Core\Plugin\Context\LazyContextRepository $context_repository
|
||||
* The context repository.
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The current route match.
|
||||
* @param \Drupal\Core\Menu\LocalActionManagerInterface $local_action_manager
|
||||
* The local action manager.
|
||||
*/
|
||||
public function __construct(BlockManagerInterface $block_manager, RouteMatchInterface $route_match, LocalActionManagerInterface $local_action_manager) {
|
||||
public function __construct(BlockManagerInterface $block_manager, LazyContextRepository $context_repository, RouteMatchInterface $route_match, LocalActionManagerInterface $local_action_manager) {
|
||||
$this->blockManager = $block_manager;
|
||||
$this->routeMatch = $route_match;
|
||||
$this->localActionManager = $local_action_manager;
|
||||
$this->contextRepository = $context_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,6 +76,7 @@ class BlockLibraryController extends ControllerBase {
|
|||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('plugin.manager.block'),
|
||||
$container->get('context.repository'),
|
||||
$container->get('current_route_match'),
|
||||
$container->get('plugin.manager.menu.local_action')
|
||||
);
|
||||
|
@ -95,7 +107,7 @@ class BlockLibraryController extends ControllerBase {
|
|||
];
|
||||
|
||||
// Only add blocks which work without any available context.
|
||||
$definitions = $this->blockManager->getDefinitionsForContexts();
|
||||
$definitions = $this->blockManager->getDefinitionsForContexts($this->contextRepository->getAvailableContexts());
|
||||
// Order by category, and then by admin label.
|
||||
$definitions = $this->blockManager->getSortedDefinitions($definitions);
|
||||
|
||||
|
@ -104,9 +116,11 @@ class BlockLibraryController extends ControllerBase {
|
|||
foreach ($definitions as $plugin_id => $plugin_definition) {
|
||||
$row = [];
|
||||
$row['title']['data'] = [
|
||||
'#markup' => $plugin_definition['admin_label'],
|
||||
'#prefix' => '<div class="block-filter-text-source">',
|
||||
'#suffix' => '</div>',
|
||||
'#type' => 'inline_template',
|
||||
'#template' => '<div class="block-filter-text-source">{{ label }}</div>',
|
||||
'#context' => [
|
||||
'label' => $plugin_definition['admin_label'],
|
||||
],
|
||||
];
|
||||
$row['category']['data'] = $plugin_definition['category'];
|
||||
$links['add'] = [
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
namespace Drupal\block\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Block\BlockManagerInterface;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
@ -59,7 +59,7 @@ class CategoryAutocompleteController implements ContainerInjectionInterface {
|
|||
$matches = array();
|
||||
foreach ($this->blockManager->getCategories() as $category) {
|
||||
if (stripos($category, $typed_category) === 0) {
|
||||
$matches[] = array('value' => $category, 'label' => SafeMarkup::checkPlain($category));
|
||||
$matches[] = array('value' => $category, 'label' => Html::escape($category));
|
||||
}
|
||||
}
|
||||
return new JsonResponse($matches);
|
||||
|
|
|
@ -231,7 +231,7 @@ class Block extends ConfigEntityBase implements BlockInterface, EntityWithPlugin
|
|||
public function calculateDependencies() {
|
||||
parent::calculateDependencies();
|
||||
$this->addDependency('theme', $this->theme);
|
||||
return $this->dependencies;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\block\Plugin\DisplayVariant;
|
|||
|
||||
use Drupal\block\BlockRepositoryInterface;
|
||||
use Drupal\Core\Block\MainContentBlockPluginInterface;
|
||||
use Drupal\Core\Block\TitleBlockPluginInterface;
|
||||
use Drupal\Core\Block\MessagesBlockPluginInterface;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Display\PageVariantInterface;
|
||||
|
@ -63,6 +64,13 @@ class BlockPageVariant extends VariantBase implements PageVariantInterface, Cont
|
|||
*/
|
||||
protected $mainContent = [];
|
||||
|
||||
/**
|
||||
* The page title: a string (plain title) or a render array (formatted title).
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $title = '';
|
||||
|
||||
/**
|
||||
* Constructs a new BlockPageVariant.
|
||||
*
|
||||
|
@ -108,6 +116,14 @@ class BlockPageVariant extends VariantBase implements PageVariantInterface, Cont
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setTitle($title) {
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -131,6 +147,9 @@ class BlockPageVariant extends VariantBase implements PageVariantInterface, Cont
|
|||
$block_plugin->setMainContent($this->mainContent);
|
||||
$main_content_block_displayed = TRUE;
|
||||
}
|
||||
elseif ($block_plugin instanceof TitleBlockPluginInterface) {
|
||||
$block_plugin->setTitle($this->title);
|
||||
}
|
||||
elseif ($block_plugin instanceof MessagesBlockPluginInterface) {
|
||||
$messages_block_displayed = TRUE;
|
||||
}
|
||||
|
@ -138,8 +157,9 @@ class BlockPageVariant extends VariantBase implements PageVariantInterface, Cont
|
|||
|
||||
// The main content block cannot be cached: it is a placeholder for the
|
||||
// render array returned by the controller. It should be rendered as-is,
|
||||
// with other placed blocks "decorating" it.
|
||||
if ($block_plugin instanceof MainContentBlockPluginInterface) {
|
||||
// with other placed blocks "decorating" it. Analogous reasoning for the
|
||||
// title block.
|
||||
if ($block_plugin instanceof MainContentBlockPluginInterface || $block_plugin instanceof TitleBlockPluginInterface) {
|
||||
unset($build[$region][$key]['#cache']['keys']);
|
||||
}
|
||||
}
|
||||
|
@ -165,6 +185,12 @@ class BlockPageVariant extends VariantBase implements PageVariantInterface, Cont
|
|||
];
|
||||
}
|
||||
|
||||
// If any render arrays are manually placed, render arrays and blocks must
|
||||
// be sorted.
|
||||
if (!$main_content_block_displayed || !$messages_block_displayed) {
|
||||
unset($build['content']['#sorted']);
|
||||
}
|
||||
|
||||
// The access results' cacheability is currently added to the top level of the
|
||||
// render array. This is done to prevent issues with empty regions being
|
||||
// displayed.
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\destination\EntityBlock.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\destination;
|
||||
|
||||
use Drupal\migrate\Plugin\migrate\destination\EntityConfigBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* @MigrateDestination(
|
||||
* id = "entity:block"
|
||||
* )
|
||||
*/
|
||||
class EntityBlock extends EntityConfigBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEntityId(Row $row) {
|
||||
// Try to find the block by its plugin ID and theme.
|
||||
$properties = array(
|
||||
'plugin' => $row->getDestinationProperty('plugin'),
|
||||
'theme' => $row->getDestinationProperty('theme'),
|
||||
);
|
||||
$blocks = array_keys($this->storage->loadByProperties($properties));
|
||||
return reset($blocks);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,34 +2,38 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\process\d6\BlockPluginId.
|
||||
* Contains \Drupal\block\Plugin\migrate\process\BlockPluginId.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process\d6;
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\Entity\MigrationInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\MigrateSkipRowException;
|
||||
use Drupal\migrate\Plugin\MigratePluginManager;
|
||||
use Drupal\migrate\Plugin\MigrateProcessInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "d6_block_plugin_id"
|
||||
* id = "block_plugin_id"
|
||||
* )
|
||||
*/
|
||||
class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* @var \Drupal\migrate\Plugin\MigratePluginManager
|
||||
* The migration process plugin, configured for lookups in d6_custom_block
|
||||
* and d7_custom_block.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*/
|
||||
protected $processPluginManager;
|
||||
protected $migrationPlugin;
|
||||
|
||||
/**
|
||||
* The block_content entity storage handler.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockContentStorage;
|
||||
|
@ -37,11 +41,10 @@ class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginI
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, MigratePluginManager $process_plugin_manager) {
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, EntityStorageInterface $storage, MigrateProcessInterface $migration_plugin) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->blockContentStorage = $storage;
|
||||
$this->migration = $migration;
|
||||
$this->processPluginManager = $process_plugin_manager;
|
||||
$this->migrationPlugin = $migration_plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,13 +52,18 @@ class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginI
|
|||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
|
||||
$entity_manager = $container->get('entity.manager');
|
||||
$migration_configuration = array(
|
||||
'migration' => array(
|
||||
'd6_custom_block',
|
||||
'd7_custom_block',
|
||||
),
|
||||
);
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$migration,
|
||||
$entity_manager->getDefinition('block_content') ? $entity_manager->getStorage('block_content') : NULL,
|
||||
$container->get('plugin.manager.migrate.process')
|
||||
$container->get('plugin.manager.migrate.process')->createInstance('migration', $migration_configuration, $migration)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -70,31 +78,28 @@ class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginI
|
|||
switch ($module) {
|
||||
case 'aggregator':
|
||||
list($type, $id) = explode('-', $delta);
|
||||
if ($type == 'category') {
|
||||
// @TODO skip row.
|
||||
// throw new MigrateSkipRowException();
|
||||
if ($type == 'feed') {
|
||||
return 'aggregator_feed_block';
|
||||
}
|
||||
$value = 'aggregator_feed_block';
|
||||
break;
|
||||
case 'menu':
|
||||
$value = "system_menu_block:$delta";
|
||||
break;
|
||||
return "system_menu_block:$delta";
|
||||
case 'block':
|
||||
if ($this->blockContentStorage) {
|
||||
$block_ids = $this->processPluginManager
|
||||
->createInstance('migration', array('migration' => 'd6_custom_block'), $this->migration)
|
||||
$block_id = $this->migrationPlugin
|
||||
->transform($delta, $migrate_executable, $row, $destination_property);
|
||||
$value = 'block_content:' . $this->blockContentStorage->load($block_ids[0])->uuid();
|
||||
}
|
||||
else {
|
||||
throw new MigrateSkipRowException();
|
||||
if ($block_id) {
|
||||
return 'block_content:' . $this->blockContentStorage->load($block_id)->uuid();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new MigrateSkipRowException();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\process\BlockRegion.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "block_region"
|
||||
* )
|
||||
*/
|
||||
class BlockRegion extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* List of regions, keyed by theme.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $regions;
|
||||
|
||||
/**
|
||||
* Constructs a BlockRegion plugin instance.
|
||||
*
|
||||
* @param array $configuration
|
||||
* The plugin configuration.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin definition.
|
||||
* @param array $regions
|
||||
* Array of region maps, keyed by theme.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, array $regions) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->regions = $regions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
$regions = array();
|
||||
foreach ($container->get('theme_handler')->listInfo() as $key => $theme) {
|
||||
$regions[$key] = $theme->info['regions'];
|
||||
}
|
||||
return new static($configuration, $plugin_id, $plugin_definition, $regions);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
// Set the destination region, based on the source region and theme as well
|
||||
// as the current destination default theme.
|
||||
list($region, $source_theme, $destination_theme) = $value;
|
||||
|
||||
// Theme is the same on both source and destination, so ensure that the
|
||||
// region exists in the destination theme.
|
||||
if (strtolower($source_theme) == strtolower($destination_theme)) {
|
||||
if (isset($this->regions[$destination_theme][$region])) {
|
||||
return $region;
|
||||
}
|
||||
}
|
||||
|
||||
// If the source and destination theme are different, try to use the
|
||||
// mappings defined in the configuration.
|
||||
$region_map = $this->configuration['region_map'];
|
||||
if (isset($region_map[$region])) {
|
||||
return $region_map[$region];
|
||||
}
|
||||
|
||||
// Oh well, we tried. Put the block in the main content region.
|
||||
return 'content';
|
||||
}
|
||||
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\process\d6\BlockSettings.
|
||||
* Contains \Drupal\block\Plugin\migrate\process\BlockSettings.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process\d6;
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
|
@ -13,7 +13,7 @@ use Drupal\migrate\Row;
|
|||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "d6_block_settings"
|
||||
* id = "block_settings"
|
||||
* )
|
||||
*/
|
||||
class BlockSettings extends ProcessPluginBase {
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\process\d6\BlockTheme.
|
||||
* Contains \Drupal\block\Plugin\migrate\process\BlockTheme.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process\d6;
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\Entity\MigrationInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
|
@ -17,7 +17,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "d6_block_theme"
|
||||
* id = "block_theme"
|
||||
* )
|
||||
*/
|
||||
class BlockTheme extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
@ -74,11 +74,9 @@ class BlockTheme extends ProcessPluginBase implements ContainerFactoryPluginInte
|
|||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Set the block theme, based on the current default theme.
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($theme, $d6_default_theme, $d6_admin_theme) = $value;
|
||||
list($theme, $default_theme, $admin_theme) = $value;
|
||||
|
||||
// If the source theme exists on the destination, we're good.
|
||||
if (isset($this->themes[$theme])) {
|
||||
|
@ -87,13 +85,13 @@ class BlockTheme extends ProcessPluginBase implements ContainerFactoryPluginInte
|
|||
|
||||
// If the source block is assigned to a region in the source default theme,
|
||||
// then assign it to the destination default theme.
|
||||
if (strtolower($theme) == strtolower($d6_default_theme)) {
|
||||
if (strtolower($theme) == strtolower($default_theme)) {
|
||||
return $this->themeConfig->get('default');
|
||||
}
|
||||
|
||||
// If the source block is assigned to a region in the source admin theme,
|
||||
// then assign it to the destination admin theme.
|
||||
if (strtolower($theme) == strtolower($d6_admin_theme)) {
|
||||
if (strtolower($theme) == strtolower($admin_theme)) {
|
||||
return $this->themeConfig->get('admin');
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\process\BlockVisibility.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\Entity\MigrationInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\MigrateSkipRowException;
|
||||
use Drupal\migrate\Plugin\MigrateProcessInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "block_visibility"
|
||||
* )
|
||||
*/
|
||||
class BlockVisibility extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The migration process plugin, configured for lookups in the d6_user_role
|
||||
* and d7_user_role migrations.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*/
|
||||
protected $migrationPlugin;
|
||||
|
||||
/**
|
||||
* Whether or not to skip blocks that use PHP for visibility. Only applies
|
||||
* if the PHP module is not enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $skipPHP = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, ModuleHandlerInterface $module_handler, MigrateProcessInterface $migration_plugin) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->migrationPlugin = $migration_plugin;
|
||||
|
||||
if (isset($configuration['skip_php'])) {
|
||||
$this->skipPHP = $configuration['skip_php'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
|
||||
$migration_configuration = array(
|
||||
'migration' => array(
|
||||
'd6_user_role',
|
||||
'd7_user_role',
|
||||
),
|
||||
);
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('module_handler'),
|
||||
$container->get('plugin.manager.migrate.process')->createInstance('migration', $migration_configuration, $migration)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($old_visibility, $pages, $roles) = $value;
|
||||
|
||||
$visibility = array();
|
||||
|
||||
// If the block is assigned to specific roles, add the user_role condition.
|
||||
if ($roles) {
|
||||
$visibility['user_role'] = array(
|
||||
'id' => 'user_role',
|
||||
'roles' => array(),
|
||||
'context_mapping' => array(
|
||||
'user' => '@user.current_user_context:current_user',
|
||||
),
|
||||
'negate' => FALSE,
|
||||
);
|
||||
|
||||
foreach ($roles as $key => $role_id) {
|
||||
$roles[$key] = $this->migrationPlugin->transform($role_id, $migrate_executable, $row, $destination_property);
|
||||
}
|
||||
$visibility['user_role']['roles'] = array_combine($roles, $roles);
|
||||
}
|
||||
|
||||
if ($pages) {
|
||||
// 2 == BLOCK_VISIBILITY_PHP in Drupal 6 and 7.
|
||||
if ($old_visibility == 2) {
|
||||
// If the PHP module is present, migrate the visibility code unaltered.
|
||||
if ($this->moduleHandler->moduleExists('php')) {
|
||||
$visibility['php'] = array(
|
||||
'id' => 'php',
|
||||
// PHP code visibility could not be negated in Drupal 6 or 7.
|
||||
'negate' => FALSE,
|
||||
'php' => $pages,
|
||||
);
|
||||
}
|
||||
// Skip the row if we're configured to. If not, we don't need to do
|
||||
// anything else -- the block will simply have no PHP or request_path
|
||||
// visibility configuration.
|
||||
elseif ($this->skipPHP) {
|
||||
throw new MigrateSkipRowException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$paths = preg_split("(\r\n?|\n)", $pages);
|
||||
foreach ($paths as $key => $path) {
|
||||
$paths[$key] = $path === '<front>' ? $path : '/' . ltrim($path, '/');
|
||||
}
|
||||
$visibility['request_path'] = array(
|
||||
'id' => 'request_path',
|
||||
'negate' => !$old_visibility,
|
||||
'pages' => implode("\n", $paths),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $visibility;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\process\d6\BlockRegion.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process\d6;
|
||||
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "d6_block_region"
|
||||
* )
|
||||
*/
|
||||
class BlockRegion extends ProcessPluginBase {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Set the destination block region, based on the source region and theme as
|
||||
* well as the current destination default theme.
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($region, $source_theme, $destination_theme) = $value;
|
||||
|
||||
// Theme is the same on both source and destination, we will assume they
|
||||
// have the same regions.
|
||||
if (strtolower($source_theme) == strtolower($destination_theme)) {
|
||||
return $region;
|
||||
}
|
||||
|
||||
// If the source and destination theme are different, try to use the
|
||||
// mappings defined in the configuration.
|
||||
$region_map = $this->configuration['region_map'];
|
||||
if (isset($region_map[$region])) {
|
||||
return $region_map[$region];
|
||||
}
|
||||
|
||||
// Oh well, we tried. Put the block in the main content region.
|
||||
return 'content';
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\process\d6\BlockVisibility.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process\d6;
|
||||
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate\Entity\MigrationInterface;
|
||||
use Drupal\migrate\Plugin\MigrateProcessInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "d6_block_visibility"
|
||||
* )
|
||||
*/
|
||||
class BlockVisibility extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The migration plugin.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*/
|
||||
protected $migrationPlugin;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, MigrateProcessInterface $migration_plugin) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->migration = $migration;
|
||||
$this->migrationPlugin = $migration_plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$migration,
|
||||
$container->get('plugin.manager.migrate.process')->createInstance('migration', array('migration' => 'd6_user_role'), $migration)
|
||||
);
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Set the block visibility settings.
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($pages, $roles, $old_visibility) = $value;
|
||||
$visibility = array();
|
||||
|
||||
if (!empty($pages)) {
|
||||
$visibility['request_path']['pages'] = $pages;
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = !$old_visibility;
|
||||
}
|
||||
|
||||
if (!empty($roles)) {
|
||||
foreach ($roles as $key => $role_id) {
|
||||
$new_role = $this->migrationPlugin->transform($role_id, $migrate_executable, $row, $destination_property);
|
||||
$visibility['user_role']['roles'][$new_role] = $new_role;
|
||||
}
|
||||
$visibility['user_role']['id'] = 'user_role';
|
||||
$visibility['user_role']['context_mapping']['user'] = 'user.current_user';
|
||||
}
|
||||
return $visibility;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,22 +2,24 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Plugin\migrate\source\d6\Block.
|
||||
* Contains \Drupal\block\Plugin\migrate\source\Block.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\source\d6;
|
||||
namespace Drupal\block\Plugin\migrate\source;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 6 block source from database.
|
||||
* Drupal block source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_block"
|
||||
* id = "block",
|
||||
* source_provider = "block"
|
||||
* )
|
||||
*/
|
||||
class Block extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* The default theme name.
|
||||
*
|
||||
|
@ -32,14 +34,33 @@ class Block extends DrupalSqlBase {
|
|||
*/
|
||||
protected $adminTheme;
|
||||
|
||||
/**
|
||||
* Table containing block configuration.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $blockTable;
|
||||
|
||||
/**
|
||||
* Table mapping blocks to user roles.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $blockRoleTable;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->select('blocks', 'b')
|
||||
->fields('b', array('bid', 'module', 'delta', 'theme', 'status', 'weight', 'region', 'visibility', 'pages', 'title', 'cache'))
|
||||
->orderBy('bid');
|
||||
return $query;
|
||||
if ($this->getModuleSchemaVersion('system') >= 7000) {
|
||||
$this->blockTable = 'block';
|
||||
$this->blockRoleTable = 'block_role';
|
||||
}
|
||||
else {
|
||||
$this->blockTable = 'blocks';
|
||||
$this->blockRoleTable = 'blocks_roles';
|
||||
}
|
||||
return $this->select($this->blockTable, 'b')->fields('b');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,36 +88,54 @@ class Block extends DrupalSqlBase {
|
|||
'pages' => $this->t('Pages list.'),
|
||||
'title' => $this->t('Block title.'),
|
||||
'cache' => $this->t('Cache rule.'),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['module']['type'] = 'string';
|
||||
$ids['delta']['type'] = 'string';
|
||||
$ids['theme']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$row->setSourceProperty('default_theme', $this->defaultTheme);
|
||||
$row->setSourceProperty('admin_theme', $this->adminTheme);
|
||||
|
||||
$module = $row->getSourceProperty('module');
|
||||
$delta = $row->getSourceProperty('delta');
|
||||
$roles = $this->select('blocks_roles', 'br')
|
||||
|
||||
$roles = $this->select($this->blockRoleTable, 'br')
|
||||
->fields('br', array('rid'))
|
||||
->condition('module', $module)
|
||||
->condition('delta', $delta)
|
||||
->execute()
|
||||
->fetchCol();
|
||||
$row->setSourceProperty('roles', $roles);
|
||||
|
||||
$settings = array();
|
||||
// Contrib can use hook_migration_d6_block_prepare_row() to add similar
|
||||
// variables via $migration->getSource()->variableGet().
|
||||
switch ($module) {
|
||||
case 'aggregator':
|
||||
list($type, $id) = explode('-', $delta);
|
||||
if ($type == 'feed') {
|
||||
$item_count = $this->database->query('SELECT block FROM {aggregator_feed} WHERE fid = :fid', array(':fid' => $id))->fetchField();
|
||||
$item_count = $this->select('aggregator_feed', 'af')
|
||||
->fields('af', ['block'])
|
||||
->condition('fid', $id)
|
||||
->execute()
|
||||
->fetchField();
|
||||
}
|
||||
else {
|
||||
$item_count = $this->database->query('SELECT block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchField();
|
||||
$item_count = $this->select('aggregator_category', 'ac')
|
||||
->fields('ac', ['block'])
|
||||
->condition('cid', $id)
|
||||
->execute()
|
||||
->fetchField();
|
||||
}
|
||||
$settings['aggregator']['item_count'] = $item_count;
|
||||
break;
|
||||
|
@ -114,9 +153,11 @@ class Block extends DrupalSqlBase {
|
|||
case 'user':
|
||||
switch ($delta) {
|
||||
case 2:
|
||||
case 'new':
|
||||
$settings['user']['block_whois_new_count'] = $this->variableGet('user_block_whois_new_count', 5);
|
||||
break;
|
||||
case 3:
|
||||
case 'online':
|
||||
$settings['user']['block_seconds_online'] = $this->variableGet('user_block_seconds_online', 900);
|
||||
$settings['user']['max_list_count'] = $this->variableGet('user_block_max_list_count', 10);
|
||||
break;
|
||||
|
@ -126,14 +167,5 @@ class Block extends DrupalSqlBase {
|
|||
$row->setSourceProperty('settings', $settings);
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['module']['type'] = 'string';
|
||||
$ids['delta']['type'] = 'string';
|
||||
$ids['theme']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@ class BlockAdminThemeTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block');
|
||||
public static $modules = array('block', 'contextual');
|
||||
|
||||
/**
|
||||
* Check for the accessibility of the admin theme on the block admin page.
|
||||
|
@ -43,4 +43,40 @@ class BlockAdminThemeTest extends WebTestBase {
|
|||
$this->drupalGet('admin/structure/block/list/bartik');
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure contextual links are disabled in Seven theme.
|
||||
*/
|
||||
function testSevenAdminTheme() {
|
||||
// Create administrative user.
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'access administration pages',
|
||||
'administer themes',
|
||||
'access contextual links',
|
||||
'view the administration theme',
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Install admin theme and confirm that tab is accessible.
|
||||
\Drupal::service('theme_handler')->install(['seven']);
|
||||
$edit['admin_theme'] = 'seven';
|
||||
$this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
|
||||
|
||||
// Define our block settings.
|
||||
$settings = [
|
||||
'theme' => 'seven',
|
||||
'region' => 'header',
|
||||
];
|
||||
|
||||
// Place a block.
|
||||
$block = $this->drupalPlaceBlock('local_tasks_block', $settings);
|
||||
|
||||
// Open admin page.
|
||||
$this->drupalGet('admin');
|
||||
|
||||
// Check if contextual link classes are unavailable.
|
||||
$this->assertNoRaw('<div data-contextual-id="block:block=' . $block->id() . ':langcode=en"></div>');
|
||||
$this->assertNoRaw('contextual-region');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -148,9 +148,7 @@ class BlockCacheTest extends WebTestBase {
|
|||
* Test non-cacheable block.
|
||||
*/
|
||||
function testNoCache() {
|
||||
$this->setBlockCacheConfig(array(
|
||||
'max_age' => 0,
|
||||
));
|
||||
\Drupal::state()->set('block_test.cache_max_age', 0);
|
||||
|
||||
$current_content = $this->randomMachineName();
|
||||
\Drupal::state()->set('block_test.content', $current_content);
|
||||
|
@ -219,13 +217,4 @@ class BlockCacheTest extends WebTestBase {
|
|||
$this->assertText($old_content, 'Block content cached for the test page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method to set the test block's cache configuration.
|
||||
*/
|
||||
private function setBlockCacheConfig($cache_config) {
|
||||
$block = $this->block->getPlugin();
|
||||
$block->setConfigurationValue('cache', $cache_config);
|
||||
$this->block->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
use Drupal\block\BlockInterface;
|
||||
|
@ -44,9 +43,6 @@ class BlockInterfaceTest extends KernelTestBase {
|
|||
'label' => 'Custom Display Message',
|
||||
'provider' => 'block_test',
|
||||
'label_display' => BlockInterface::BLOCK_LABEL_VISIBLE,
|
||||
'cache' => array(
|
||||
'max_age' => Cache::PERMANENT,
|
||||
),
|
||||
'display_message' => 'no message set',
|
||||
);
|
||||
// Initial configuration of the block at construction time.
|
||||
|
@ -60,10 +56,6 @@ class BlockInterfaceTest extends KernelTestBase {
|
|||
$this->assertIdentical($display_block->getConfiguration(), $expected_configuration, 'The block configuration was updated correctly.');
|
||||
$definition = $display_block->getPluginDefinition();
|
||||
|
||||
$period = array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400);
|
||||
$period = array_map(array(\Drupal::service('date.formatter'), 'formatInterval'), array_combine($period, $period));
|
||||
$period[0] = '<' . t('no caching') . '>';
|
||||
$period[\Drupal\Core\Cache\Cache::PERMANENT] = t('Forever');
|
||||
$expected_form = array(
|
||||
'provider' => array(
|
||||
'#type' => 'value',
|
||||
|
@ -87,17 +79,7 @@ class BlockInterfaceTest extends KernelTestBase {
|
|||
'#default_value' => TRUE,
|
||||
'#return_value' => 'visible',
|
||||
),
|
||||
'cache' => array(
|
||||
'#type' => 'details',
|
||||
'#title' => t('Cache settings'),
|
||||
'max_age' => array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Maximum age'),
|
||||
'#description' => t('The maximum time this block may be cached.'),
|
||||
'#default_value' => Cache::PERMANENT,
|
||||
'#options' => $period,
|
||||
),
|
||||
),
|
||||
'context_mapping' => array(),
|
||||
'display_message' => array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Display message'),
|
||||
|
@ -109,7 +91,7 @@ class BlockInterfaceTest extends KernelTestBase {
|
|||
$actual_form = $display_block->buildConfigurationForm(array(), $form_state);
|
||||
// Remove the visibility sections, as that just tests condition plugins.
|
||||
unset($actual_form['visibility'], $actual_form['visibility_tabs']);
|
||||
$this->assertIdentical($actual_form, $expected_form, 'Only the expected form elements were present.');
|
||||
$this->assertIdentical($this->castSafeStrings($actual_form), $this->castSafeStrings($expected_form), 'Only the expected form elements were present.');
|
||||
|
||||
$expected_build = array(
|
||||
'#children' => 'My custom display message.',
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityStorage;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
use Drupal\block_test\Plugin\Block\TestHtmlBlock;
|
||||
|
@ -99,9 +98,6 @@ class BlockStorageUnitTest extends KernelTestBase {
|
|||
'label' => '',
|
||||
'provider' => 'block_test',
|
||||
'label_display' => BlockInterface::BLOCK_LABEL_VISIBLE,
|
||||
'cache' => array(
|
||||
'max_age' => Cache::PERMANENT,
|
||||
),
|
||||
),
|
||||
'visibility' => array(),
|
||||
);
|
||||
|
|
|
@ -135,6 +135,9 @@ class BlockTest extends BlockTestBase {
|
|||
* Test configuring and moving a module-define block to specific regions.
|
||||
*/
|
||||
function testBlock() {
|
||||
// Place page title block to test error messages.
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
|
||||
// Select the 'Powered by Drupal' block to be configured and moved.
|
||||
$block = array();
|
||||
$block['id'] = 'system_powered_by_block';
|
||||
|
|
|
@ -86,6 +86,10 @@ class BlockUiTest extends WebTestBase {
|
|||
$this->clickLink(t('Demonstrate block regions (@theme)', array('@theme' => 'Classy')));
|
||||
$elements = $this->xpath('//div[contains(@class, "region-highlighted")]/div[contains(@class, "block-region") and contains(text(), :title)]', array(':title' => 'Highlighted'));
|
||||
$this->assertTrue(!empty($elements), 'Block demo regions are shown.');
|
||||
|
||||
\Drupal::service('theme_handler')->install(array('test_theme'));
|
||||
$this->drupalGet('admin/structure/block/demo/test_theme');
|
||||
$this->assertEscaped('<strong>Test theme</strong>');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,21 +166,57 @@ class BlockUiTest extends WebTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of context-aware blocks.
|
||||
* Tests the behavior of unsatisfied context-aware blocks.
|
||||
*/
|
||||
public function testContextAwareBlocks() {
|
||||
public function testContextAwareUnsatisfiedBlocks() {
|
||||
$arguments = array(
|
||||
':ul_class' => 'block-list',
|
||||
':li_class' => 'test-context-aware',
|
||||
':href' => 'admin/structure/block/add/test_context_aware/classy',
|
||||
':text' => 'Test context-aware block',
|
||||
':category' => 'Block test',
|
||||
':href' => 'admin/structure/block/add/test_context_aware_unsatisfied/classy',
|
||||
':text' => 'Test context-aware unsatisfied block',
|
||||
);
|
||||
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$elements = $this->xpath('//details[@id="edit-category-block-test"]//ul[contains(@class, :ul_class)]/li[contains(@class, :li_class)]/a[contains(@href, :href) and text()=:text]', $arguments);
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$elements = $this->xpath('//tr[.//td/div[text()=:text] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]', $arguments);
|
||||
$this->assertTrue(empty($elements), 'The context-aware test block does not appear.');
|
||||
|
||||
$definition = \Drupal::service('plugin.manager.block')->getDefinition('test_context_aware_unsatisfied');
|
||||
$this->assertTrue(!empty($definition), 'The context-aware test block does not exist.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of context-aware blocks.
|
||||
*/
|
||||
public function testContextAwareBlocks() {
|
||||
$expected_text = '<div id="test_context_aware--username">' . \Drupal::currentUser()->getUsername() . '</div>';
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText('Test context-aware block');
|
||||
$this->assertNoRaw($expected_text);
|
||||
|
||||
$block_url = 'admin/structure/block/add/test_context_aware/classy';
|
||||
$arguments = array(
|
||||
':title' => 'Test context-aware block',
|
||||
':category' => 'Block test',
|
||||
':href' => $block_url,
|
||||
);
|
||||
$pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]';
|
||||
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue(!empty($elements), 'The context-aware test block appears.');
|
||||
$definition = \Drupal::service('plugin.manager.block')->getDefinition('test_context_aware');
|
||||
$this->assertTrue(!empty($definition), 'The context-aware test block exists.');
|
||||
|
||||
$edit = [
|
||||
'region' => 'content',
|
||||
'settings[context_mapping][user]' => '@block_test.multiple_static_context:user2',
|
||||
];
|
||||
$this->drupalPostForm($block_url, $edit, 'Save block');
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText('Test context-aware block');
|
||||
$this->assertRaw($expected_text);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,12 +26,23 @@ class BlockXssTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'block_content', 'block_test', 'menu_ui', 'views'];
|
||||
public static $modules = ['block', 'block_content', 'menu_ui', 'views'];
|
||||
|
||||
/**
|
||||
* Test XSS in title.
|
||||
* Tests that nothing is escaped other than the blocks explicitly tested.
|
||||
*/
|
||||
public function testNoUnexpectedEscaping() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$this->assertNoEscaped('<');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS in title.
|
||||
*/
|
||||
public function testXssInTitle() {
|
||||
$this->container->get('module_installer')->install(['block_test']);
|
||||
$this->drupalPlaceBlock('test_xss_title', ['label' => '<script>alert("XSS label");</script>']);
|
||||
|
||||
\Drupal::state()->set('block_test.content', $this->randomMachineName());
|
||||
|
@ -48,6 +59,7 @@ class BlockXssTest extends WebTestBase {
|
|||
* Tests XSS in category.
|
||||
*/
|
||||
public function testXssInCategory() {
|
||||
$this->container->get('module_installer')->install(['block_test']);
|
||||
$this->drupalPlaceBlock('test_xss_title');
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
|
@ -64,24 +76,60 @@ class BlockXssTest extends WebTestBase {
|
|||
$this->doViewTest();
|
||||
$this->doMenuTest();
|
||||
$this->doBlockContentTest();
|
||||
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$this->assertNoRaw('&lt;', 'The page does not have double escaped HTML tags.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS coming from View block labels.
|
||||
*/
|
||||
protected function doViewTest() {
|
||||
// Create a View without a custom label for its block Display. The
|
||||
// admin_label of the block then becomes just the View's label.
|
||||
$view = View::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'label' => '<script>alert("view");</script>',
|
||||
'label' => '<script>alert("view1");</script>',
|
||||
]);
|
||||
$view->addDisplay('block');
|
||||
$view->save();
|
||||
|
||||
// Create a View with a custom label for its block Display. The
|
||||
// admin_label of the block then becomes the View's label combined with
|
||||
// the Display's label.
|
||||
$view = View::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'label' => '<script>alert("view2");</script>',
|
||||
]);
|
||||
$view->addDisplay('block', 'Fish & chips');
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
// The block admin label is automatically XSS admin filtered.
|
||||
$this->assertRaw('alert("view");');
|
||||
$this->assertNoRaw('<script>alert("view");</script>');
|
||||
|
||||
// \Drupal\views\Plugin\Derivative\ViewsBlock::getDerivativeDefinitions()
|
||||
// has a different code path for an admin label based only on the View
|
||||
// label versus one based on both the View label and the Display label.
|
||||
// Ensure that this test is covering both code paths by asserting the
|
||||
// absence of a ":" for the first View and the presence of a ":" for the
|
||||
// second one. Note that the second assertion is redundant with the one
|
||||
// further down which also checks for the Display label, but is included
|
||||
// here for clarity.
|
||||
$this->assertNoEscaped('<script>alert("view1");</script>:');
|
||||
$this->assertEscaped('<script>alert("view2");</script>:');
|
||||
|
||||
// Assert that the blocks have their admin labels escaped and
|
||||
// don't appear anywhere unescaped.
|
||||
$this->assertEscaped('<script>alert("view1");</script>');
|
||||
$this->assertNoRaw('<script>alert("view1");</script>');
|
||||
$this->assertEscaped('<script>alert("view2");</script>: Fish & chips');
|
||||
$this->assertNoRaw('<script>alert("view2");</script>');
|
||||
$this->assertNoRaw('Fish & chips');
|
||||
|
||||
// Assert the Display label doesn't appear anywhere double escaped.
|
||||
$this->assertNoRaw('Fish & chips');
|
||||
$this->assertNoRaw('Fish &amp; chips');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,8 +143,8 @@ class BlockXssTest extends WebTestBase {
|
|||
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
// The block admin label is automatically XSS admin filtered.
|
||||
$this->assertRaw('alert("menu");');
|
||||
|
||||
$this->assertEscaped('<script>alert("menu");</script>');
|
||||
$this->assertNoRaw('<script>alert("menu");</script>');
|
||||
}
|
||||
|
||||
|
@ -116,8 +164,8 @@ class BlockXssTest extends WebTestBase {
|
|||
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
// The block admin label is automatically XSS admin filtered.
|
||||
$this->assertRaw('alert("block_content");');
|
||||
|
||||
$this->assertEscaped('<script>alert("block_content");</script>');
|
||||
$this->assertNoRaw('<script>alert("block_content");</script>');
|
||||
}
|
||||
|
||||
|
|
|
@ -11,57 +11,31 @@ use Drupal\block\Entity\Block;
|
|||
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Upgrade block settings to block.block.*.yml.
|
||||
* Tests migration of blocks to configuration entities.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateBlockTest extends MigrateDrupal6TestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
static $modules = array(
|
||||
public static $modules = [
|
||||
'block',
|
||||
'views',
|
||||
'comment',
|
||||
'menu_ui',
|
||||
'block_content',
|
||||
'node',
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['block_content']);
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
$entities = array(
|
||||
entity_create('menu', array('id' => 'primary-links')),
|
||||
entity_create('menu', array('id' => 'secondary-links')),
|
||||
entity_create('block_content', array('id' => 1, 'type' => 'basic', 'info' => $this->randomMachineName(8))),
|
||||
entity_create('block_content', array('id' => 2, 'type' => 'basic', 'info' => $this->randomMachineName(8))),
|
||||
);
|
||||
foreach ($entities as $entity) {
|
||||
$entity->enforceIsNew(TRUE);
|
||||
$entity->save();
|
||||
}
|
||||
$this->prepareMigrations(array(
|
||||
'd6_custom_block' => array(
|
||||
array(array(1), array(1)),
|
||||
array(array(2), array(2)),
|
||||
),
|
||||
'menu' => array(
|
||||
array(array('menu1'), array('menu')),
|
||||
),
|
||||
'd6_user_role' => array(
|
||||
array(array(2), array('authenticated')),
|
||||
array(array(3), array('migrate_test_role_1')),
|
||||
),
|
||||
));
|
||||
|
||||
// Set Bartik and Seven as the default public and admin theme.
|
||||
$config = $this->config('system.theme');
|
||||
$config->set('default', 'bartik');
|
||||
|
@ -69,114 +43,107 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
$config->save();
|
||||
|
||||
// Install one of D8's test themes.
|
||||
\Drupal::service('theme_handler')->install(array('test_theme'));
|
||||
\Drupal::service('theme_handler')->install(['test_theme']);
|
||||
|
||||
$this->executeMigration('d6_block');
|
||||
$this->executeMigrations([
|
||||
'd6_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd6_custom_block',
|
||||
'menu',
|
||||
'd6_user_role',
|
||||
'd6_block',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the block settings migration.
|
||||
* Asserts various aspects of a block.
|
||||
*
|
||||
* @param string $id
|
||||
* The block ID.
|
||||
* @param string $module
|
||||
* The module.
|
||||
* @param array $visibility
|
||||
* The block visibility settings.
|
||||
* @param string $region
|
||||
* The display region.
|
||||
* @param string $theme
|
||||
* The theme.
|
||||
* @param string $weight
|
||||
* The block weight.
|
||||
*/
|
||||
public function assertEntity($id, $visibility, $region, $theme, $weight) {
|
||||
$block = Block::load($id);
|
||||
$this->assertTrue($block instanceof Block);
|
||||
$this->assertIdentical($visibility, $block->getVisibility());
|
||||
$this->assertIdentical($region, $block->getRegion());
|
||||
$this->assertIdentical($theme, $block->getTheme());
|
||||
$this->assertIdentical($weight, $block->getWeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block migration.
|
||||
*/
|
||||
public function testBlockMigration() {
|
||||
$blocks = Block::loadMultiple();
|
||||
$this->assertIdentical(count($blocks), 10);
|
||||
$this->assertIdentical(9, count($blocks));
|
||||
|
||||
// User blocks
|
||||
$test_block_user = $blocks['user'];
|
||||
$this->assertNotNull($test_block_user);
|
||||
$this->assertIdentical('sidebar_first', $test_block_user->getRegion());
|
||||
$this->assertIdentical('bartik', $test_block_user->getTheme());
|
||||
$visibility = $test_block_user->getVisibility();
|
||||
$this->assertTrue(empty($visibility));
|
||||
$this->assertIdentical(0, $test_block_user->getWeight());
|
||||
$visibility = [];
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = TRUE;
|
||||
$visibility['request_path']['pages'] = "<front>\n/node/1\n/blog/*";
|
||||
$this->assertEntity('user', $visibility, 'sidebar_first', 'bartik', 0);
|
||||
|
||||
$test_block_user_1 = $blocks['user_1'];
|
||||
$this->assertNotNull($test_block_user_1);
|
||||
$this->assertIdentical('sidebar_first', $test_block_user_1->getRegion());
|
||||
$this->assertIdentical('bartik', $test_block_user_1->getTheme());
|
||||
$visibility = $test_block_user_1->getVisibility();
|
||||
$this->assertTrue(empty($visibility));
|
||||
$this->assertIdentical(0, $test_block_user_1->getWeight());
|
||||
$visibility = [];
|
||||
$this->assertEntity('user_1', $visibility, 'sidebar_first', 'bartik', 0);
|
||||
|
||||
$test_block_user_2 = $blocks['user_2'];
|
||||
$this->assertNotNull($test_block_user_2);
|
||||
$this->assertIdentical('sidebar_second', $test_block_user_2->getRegion());
|
||||
$this->assertIdentical('bartik', $test_block_user_2->getTheme());
|
||||
$visibility = $test_block_user_2->getVisibility();
|
||||
$this->assertIdentical($visibility['user_role']['id'], 'user_role');
|
||||
$roles = array();
|
||||
$visibility['user_role']['id'] = 'user_role';
|
||||
$roles['authenticated'] = 'authenticated';
|
||||
$this->assertIdentical($visibility['user_role']['roles'], $roles);
|
||||
$this->assertFalse($visibility['user_role']['negate']);
|
||||
$this->assertIdentical(-9, $test_block_user_2->getWeight());
|
||||
$visibility['user_role']['roles'] = $roles;
|
||||
$context_mapping['user'] = '@user.current_user_context:current_user';
|
||||
$visibility['user_role']['context_mapping'] = $context_mapping;
|
||||
$visibility['user_role']['negate'] = FALSE;
|
||||
$this->assertEntity('user_2', $visibility, 'sidebar_second', 'bartik', -9);
|
||||
|
||||
$test_block_user_3 = $blocks['user_3'];
|
||||
$this->assertNotNull($test_block_user_3);
|
||||
$this->assertIdentical('sidebar_second', $test_block_user_3->getRegion());
|
||||
$this->assertIdentical('bartik', $test_block_user_3->getTheme());
|
||||
$visibility = $test_block_user_3->getVisibility();
|
||||
$this->assertIdentical($visibility['user_role']['id'], 'user_role');
|
||||
$roles = array();
|
||||
$roles['migrate_test_role_1'] = 'migrate_test_role_1';
|
||||
$this->assertIdentical($visibility['user_role']['roles'], $roles);
|
||||
$this->assertFalse($visibility['user_role']['negate']);
|
||||
$this->assertIdentical(-6, $test_block_user_3->getWeight());
|
||||
$visibility = [];
|
||||
$visibility['user_role']['id'] = 'user_role';
|
||||
$visibility['user_role']['roles'] = [
|
||||
'migrate_test_role_1' => 'migrate_test_role_1'
|
||||
];
|
||||
$context_mapping['user'] = '@user.current_user_context:current_user';
|
||||
$visibility['user_role']['context_mapping'] = $context_mapping;
|
||||
$visibility['user_role']['negate'] = FALSE;
|
||||
$this->assertEntity('user_3', $visibility, 'sidebar_second', 'bartik', -6);
|
||||
|
||||
// Check system block
|
||||
$test_block_system = $blocks['system'];
|
||||
$this->assertNotNull($test_block_system);
|
||||
$this->assertIdentical('footer', $test_block_system->getRegion());
|
||||
$this->assertIdentical('bartik', $test_block_system->getTheme());
|
||||
$visibility = $test_block_system->getVisibility();
|
||||
$this->assertIdentical('request_path', $visibility['request_path']['id']);
|
||||
$this->assertIdentical('node/1', $visibility['request_path']['pages']);
|
||||
$this->assertTrue($visibility['request_path']['negate']);
|
||||
$this->assertIdentical(-5, $test_block_system->getWeight());
|
||||
$visibility = [];
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = TRUE;
|
||||
$visibility['request_path']['pages'] = '/node/1';
|
||||
$this->assertEntity('system', $visibility, 'footer', 'bartik', -5);
|
||||
|
||||
// Check menu blocks
|
||||
$test_block_menu = $blocks['menu'];
|
||||
$this->assertNotNull($test_block_menu);
|
||||
$this->assertIdentical('header', $test_block_menu->getRegion());
|
||||
$this->assertIdentical('bartik', $test_block_menu->getTheme());
|
||||
$visibility = $test_block_menu->getVisibility();
|
||||
$this->assertTrue(empty($visibility));
|
||||
$this->assertIdentical(-5, $test_block_menu->getWeight());
|
||||
$visibility = [];
|
||||
$this->assertEntity('menu', $visibility, 'header', 'bartik', -5);
|
||||
|
||||
// Check custom blocks
|
||||
$test_block_block = $blocks['block'];
|
||||
$this->assertNotNull($test_block_block);
|
||||
$this->assertIdentical('content', $test_block_block->getRegion());
|
||||
$this->assertIdentical('bartik', $test_block_block->getTheme());
|
||||
$visibility = $test_block_block->getVisibility();
|
||||
$this->assertIdentical('request_path', $visibility['request_path']['id']);
|
||||
$this->assertIdentical('<front>', $visibility['request_path']['pages']);
|
||||
$this->assertFalse($visibility['request_path']['negate']);
|
||||
$this->assertIdentical(0, $test_block_block->getWeight());
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = FALSE;
|
||||
$visibility['request_path']['pages'] = '<front>';
|
||||
$this->assertEntity('block', $visibility, 'content', 'bartik', 0);
|
||||
|
||||
$test_block_block_1 = $blocks['block_1'];
|
||||
$this->assertNotNull($test_block_block_1);
|
||||
$this->assertIdentical('right', $test_block_block_1->getRegion());
|
||||
$this->assertIdentical('bluemarine', $test_block_block_1->getTheme());
|
||||
$visibility = $test_block_block_1->getVisibility();
|
||||
$this->assertIdentical('request_path', $visibility['request_path']['id']);
|
||||
$this->assertIdentical('node', $visibility['request_path']['pages']);
|
||||
$this->assertFalse($visibility['request_path']['negate']);
|
||||
$this->assertIdentical(-4, $test_block_block_1->getWeight());
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = FALSE;
|
||||
$visibility['request_path']['pages'] = '/node';
|
||||
$this->assertEntity('block_1', $visibility, 'sidebar_second', 'bluemarine', -4);
|
||||
|
||||
$test_block_block_2 = $blocks['block_2'];
|
||||
$this->assertNotNull($test_block_block_2);
|
||||
$this->assertIdentical('right', $test_block_block_2->getRegion());
|
||||
$this->assertIdentical('test_theme', $test_block_block_2->getTheme());
|
||||
$visibility = $test_block_block_2->getVisibility();
|
||||
$this->assertTrue(empty($visibility));
|
||||
$this->assertIdentical(-7, $test_block_block_2->getWeight());
|
||||
$visibility = [];
|
||||
$this->assertEntity('block_2', $visibility, 'right', 'test_theme', -7);
|
||||
|
||||
$test_block_block_3 = $blocks['block_3'];
|
||||
$this->assertNotNull($test_block_block_3);
|
||||
$this->assertIdentical('left', $test_block_block_3->getRegion());
|
||||
$this->assertIdentical('test_theme', $test_block_block_3->getTheme());
|
||||
$visibility = $test_block_block_3->getVisibility();
|
||||
$this->assertTrue(empty($visibility));
|
||||
$this->assertIdentical(-2, $test_block_block_3->getWeight());
|
||||
// Custom block with php code is not migrated.
|
||||
$block = Block::load('block_3');
|
||||
$this->assertFalse($block instanceof Block);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
162
core/modules/block/src/Tests/Migrate/d7/MigrateBlockTest.php
Normal file
162
core/modules/block/src/Tests/Migrate/d7/MigrateBlockTest.php
Normal file
|
@ -0,0 +1,162 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Tests\Migrate\d7\MigrateBlockTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests\Migrate\d7;
|
||||
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of blocks to configuration entities.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class MigrateBlockTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
static $modules = [
|
||||
'block',
|
||||
'views',
|
||||
'comment',
|
||||
'menu_ui',
|
||||
'block_content',
|
||||
'node',
|
||||
'text',
|
||||
'filter',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(static::$modules);
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
// Set Bartik and Seven as the default public and admin theme.
|
||||
$config = $this->config('system.theme');
|
||||
$config->set('default', 'bartik');
|
||||
$config->set('admin', 'seven');
|
||||
$config->save();
|
||||
|
||||
// Install one of D8's test themes.
|
||||
\Drupal::service('theme_handler')->install(['bartik']);
|
||||
|
||||
$this->executeMigrations([
|
||||
'd7_filter_format',
|
||||
'd7_user_role',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd7_custom_block',
|
||||
'd7_block',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts various aspects of a block.
|
||||
*
|
||||
* @param string $id
|
||||
* The block ID.
|
||||
* @param string $plugin_id
|
||||
* The block's plugin ID.
|
||||
* @param array $roles
|
||||
* Role IDs the block is expected to have.
|
||||
* @param string $pages
|
||||
* The list of pages on which the block should appear.
|
||||
* @param string $region
|
||||
* The display region.
|
||||
* @param string $theme
|
||||
* The theme.
|
||||
* @param string $weight
|
||||
* The block weight.
|
||||
*/
|
||||
public function assertEntity($id, $plugin_id, array $roles, $pages, $region, $theme, $weight) {
|
||||
$block = Block::load($id);
|
||||
$this->assertTrue($block instanceof Block);
|
||||
/** @var \Drupal\block\BlockInterface $block */
|
||||
$this->assertIdentical($plugin_id, $block->getPluginId());
|
||||
|
||||
$visibility = $block->getVisibility();
|
||||
if ($roles) {
|
||||
$this->assertIdentical($roles, array_values($visibility['user_role']['roles']));
|
||||
$this->assertIdentical('@user.current_user_context:current_user', $visibility['user_role']['context_mapping']['user']);
|
||||
}
|
||||
if ($pages) {
|
||||
$this->assertIdentical($pages, $visibility['request_path']['pages']);
|
||||
}
|
||||
|
||||
$this->assertIdentical($region, $block->getRegion());
|
||||
$this->assertIdentical($theme, $block->getTheme());
|
||||
$this->assertIdentical($weight, $block->getWeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block migration.
|
||||
*/
|
||||
public function testBlockMigration() {
|
||||
$this->assertEntity('bartik_system_main', 'system_main_block', [], '', 'content', 'bartik', 0);
|
||||
$this->assertEntity('bartik_search_form', 'search_form_block', [], '', 'sidebar_first', 'bartik', -1);
|
||||
$this->assertEntity('bartik_user_login', 'user_login_block', [], '', 'sidebar_first', 'bartik', 0);
|
||||
$this->assertEntity('bartik_system_powered-by', 'system_powered_by_block', [], '', 'footer', 'bartik', 10);
|
||||
$this->assertEntity('seven_system_main', 'system_main_block', [], '', 'content', 'seven', 0);
|
||||
$this->assertEntity('seven_user_login', 'user_login_block', [], '', 'content', 'seven', 10);
|
||||
|
||||
// The d7_custom_block migration should have migrated a block containing a
|
||||
// mildly amusing limerick. We'll need its UUID to determine
|
||||
// bartik_block_1's plugin ID.
|
||||
$uuid = BlockContent::load(1)->uuid();
|
||||
$this->assertEntity('bartik_block_1', 'block_content:' . $uuid, ['authenticated'], '', 'highlighted', 'bartik', 0);
|
||||
|
||||
// Assert that disabled blocks (or enabled blocks whose plugin IDs could
|
||||
// be resolved) did not migrate.
|
||||
$non_existent_blocks = [
|
||||
'bartik_system_navigation',
|
||||
'bartik_system_help',
|
||||
'seven_user_new',
|
||||
'seven_search_form',
|
||||
'bartik_comment_recent',
|
||||
'bartik_node_syndicate',
|
||||
'bartik_node_recent',
|
||||
'bartik_shortcut_shortcuts',
|
||||
'bartik_system_management',
|
||||
'bartik_system_user-menu',
|
||||
'bartik_system_main-menu',
|
||||
'bartik_user_new',
|
||||
'bartik_user_online',
|
||||
'seven_comment_recent',
|
||||
'seven_node_syndicate',
|
||||
'seven_shortcut_shortcuts',
|
||||
'seven_system_powered-by',
|
||||
'seven_system_navigation',
|
||||
'seven_system_management',
|
||||
'seven_system_user-menu',
|
||||
'seven_system_main-menu',
|
||||
'seven_user_online',
|
||||
'bartik_blog_recent',
|
||||
'bartik_book_navigation',
|
||||
'bartik_locale_language',
|
||||
'bartik_forum_active',
|
||||
'bartik_forum_new',
|
||||
'seven_blog_recent',
|
||||
'seven_book_navigation',
|
||||
'seven_locale_language',
|
||||
'seven_forum_active',
|
||||
'seven_forum_new',
|
||||
'bartik_menu_menu-test-menu',
|
||||
'bartik_statistics_popular',
|
||||
'seven_menu_menu-test-menu',
|
||||
'seven_statistics_popular',
|
||||
'seven_block_1',
|
||||
];
|
||||
$this->assertTrue(empty(Block::loadMultiple($non_existent_blocks)));
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\block\Tests\Views;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\views\Entity\View;
|
||||
use Drupal\views\Views;
|
||||
|
@ -271,6 +272,7 @@ class DisplayBlockTest extends ViewTestBase {
|
|||
* Tests the various testcases of empty block rendering.
|
||||
*/
|
||||
public function testBlockEmptyRendering() {
|
||||
$url = new Url('test_page_test.test_page');
|
||||
// Remove all views_test_data entries.
|
||||
\Drupal::database()->truncate('views_test_data')->execute();
|
||||
/** @var \Drupal\views\ViewEntityInterface $view */
|
||||
|
@ -285,12 +287,12 @@ class DisplayBlockTest extends ViewTestBase {
|
|||
$display['display_options']['block_hide_empty'] = TRUE;
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
// Ensure that the view cachability metadata is propagated even, for an
|
||||
// empty block.
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.path', 'url.query_args', 'user.roles:authenticated']);
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
|
||||
|
||||
// Add a header displayed on empty result.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
|
@ -305,10 +307,10 @@ class DisplayBlockTest extends ViewTestBase {
|
|||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.path', 'url.query_args', 'user.roles:authenticated']);
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
|
||||
|
||||
// Hide the header on empty results.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
|
@ -323,10 +325,10 @@ class DisplayBlockTest extends ViewTestBase {
|
|||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.path', 'url.query_args', 'user.roles:authenticated']);
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
|
||||
|
||||
// Add an empty text.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
|
@ -340,10 +342,10 @@ class DisplayBlockTest extends ViewTestBase {
|
|||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.path', 'url.query_args', 'user.roles:authenticated']);
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue