Update Composer, update everything

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

View file

@ -29,8 +29,9 @@ function action_help($route_name, RouteMatchInterface $route_match) {
$output = '<p>' . t('There are two types of actions: simple and advanced. Simple actions do not require any additional configuration and are listed here automatically. Advanced actions need to be created and configured before they can be used because they have options that need to be specified; for example, sending an email to a specified address or unpublishing content containing certain words. To create an advanced action, select the action from the drop-down list in the advanced action section below and click the <em>Create</em> button.') . '</p>';
return $output;
case 'action.admin_add':
case 'entity.action.edit_form':
return t('An advanced action offers additional configuration options which may be filled out below. Changing the <em>Description</em> field is recommended in order to better identify the precise action taking place.');
return t('An advanced action offers additional configuration options which may be filled out below. Changing the <em>Label</em> field is recommended in order to better identify the precise action taking place.');
}
}

View file

@ -29,4 +29,3 @@ entity.action.delete_form:
_title: 'Delete'
requirements:
_permission: 'administer actions'

View file

@ -15,6 +15,6 @@ function action_views_form_substitutions() {
'#attributes' => ['class' => ['action-table-select-all']],
];
return [
'<!--action-bulk-form-select-all-->' => drupal_render($select_all),
'<!--action-bulk-form-select-all-->' => \Drupal::service('renderer')->render($select_all),
];
}

View file

@ -3,10 +3,12 @@ label: Action configuration
migration_tags:
- Drupal 6
- Drupal 7
- Configuration
source:
plugin: variable
variables:
- actions_max_stack
source_module: action
process:
recursion_limit: actions_max_stack
destination:

View file

@ -2,6 +2,7 @@ id: d6_action
label: Actions
migration_tags:
- Drupal 6
- Configuration
source:
plugin: action
process:
@ -23,6 +24,12 @@ process:
imagecache_flush_action: 0
imagecache_generate_all_action: 0
imagecache_generate_action: 0
comment_publish_action: entity:publish_action:comment
comment_unpublish_action: entity:unpublish_action:comment
comment_save_action: entity:save_action:comment
node_publish_action: entity:publish_action:node
node_unpublish_action: entity:unpublish_action:node
node_save_action: entity:save_action:node
bypass: true
-
plugin: skip_on_empty

View file

@ -2,6 +2,7 @@ id: d7_action
label: Actions
migration_tags:
- Drupal 7
- Configuration
source:
plugin: action
process:
@ -20,6 +21,12 @@ process:
system_send_email_action: action_send_email_action
system_message_action: action_message_action
system_block_ip_action: 0
comment_publish_action: entity:publish_action:comment
comment_unpublish_action: entity:unpublish_action:comment
comment_save_action: entity:save_action:comment
node_publish_action: entity:publish_action:node
node_unpublish_action: entity:unpublish_action:node
node_save_action: entity:save_action:node
bypass: true
-
plugin: skip_on_empty

View file

@ -2,67 +2,28 @@
namespace Drupal\action;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Action\ActionManager;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a form for action add forms.
*
* @internal
*/
class ActionAddForm extends ActionFormBase {
/**
* The action manager.
*
* @var \Drupal\Core\Action\ActionManager
*/
protected $actionManager;
/**
* Constructs a new ActionAddForm.
*
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
* The action storage.
* @param \Drupal\Core\Action\ActionManager $action_manager
* The action plugin manager.
*/
public function __construct(EntityStorageInterface $storage, ActionManager $action_manager) {
parent::__construct($storage);
$this->actionManager = $action_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager')->getStorage('action'),
$container->get('plugin.manager.action')
);
}
/**
* {@inheritdoc}
*
* @param string $action_id
* The hashed version of the action ID.
* The action ID.
*/
public function buildForm(array $form, FormStateInterface $form_state, $action_id = NULL) {
// In \Drupal\action\Form\ActionAdminManageForm::buildForm() the action
// are hashed. Here we have to decrypt it to find the desired action ID.
foreach ($this->actionManager->getDefinitions() as $id => $definition) {
$key = Crypt::hashBase64($id);
if ($key === $action_id) {
$this->entity->setPlugin($id);
// Derive the label and type from the action definition.
$this->entity->set('label', $definition['label']);
$this->entity->set('type', $definition['type']);
break;
}
}
$this->entity->setPlugin($action_id);
// Derive the label and type from the action definition.
$definition = $this->entity->getPluginDefinition();
$this->entity->set('label', $definition['label']);
$this->entity->set('type', $definition['type']);
return parent::buildForm($form, $form_state);
}

View file

@ -4,6 +4,8 @@ namespace Drupal\action;
/**
* Provides a form for action edit forms.
*
* @internal
*/
class ActionEditForm extends ActionFormBase {

View file

@ -13,13 +13,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
abstract class ActionFormBase extends EntityForm {
/**
* The action plugin being configured.
*
* @var \Drupal\Core\Action\ActionInterface
*/
protected $plugin;
/**
* The action storage.
*
@ -27,6 +20,13 @@ abstract class ActionFormBase extends EntityForm {
*/
protected $storage;
/**
* The action entity.
*
* @var \Drupal\system\ActionConfigEntityInterface
*/
protected $entity;
/**
* Constructs a new action form.
*
@ -46,14 +46,6 @@ abstract class ActionFormBase extends EntityForm {
);
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$this->plugin = $this->entity->getPlugin();
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
@ -85,8 +77,8 @@ abstract class ActionFormBase extends EntityForm {
'#value' => $this->entity->getType(),
];
if ($this->plugin instanceof PluginFormInterface) {
$form += $this->plugin->buildConfigurationForm($form, $form_state);
if ($plugin = $this->getPlugin()) {
$form += $plugin->buildConfigurationForm($form, $form_state);
}
return parent::form($form, $form_state);
@ -96,7 +88,7 @@ abstract class ActionFormBase extends EntityForm {
* Determines if the action already exists.
*
* @param string $id
* The action ID
* The action ID.
*
* @return bool
* TRUE if the action exists, FALSE otherwise.
@ -120,9 +112,8 @@ abstract class ActionFormBase extends EntityForm {
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
if ($this->plugin instanceof PluginFormInterface) {
$this->plugin->validateConfigurationForm($form, $form_state);
if ($plugin = $this->getPlugin()) {
$plugin->validateConfigurationForm($form, $form_state);
}
}
@ -131,9 +122,8 @@ abstract class ActionFormBase extends EntityForm {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
if ($this->plugin instanceof PluginFormInterface) {
$this->plugin->submitConfigurationForm($form, $form_state);
if ($plugin = $this->getPlugin()) {
$plugin->submitConfigurationForm($form, $form_state);
}
}
@ -142,9 +132,22 @@ abstract class ActionFormBase extends EntityForm {
*/
public function save(array $form, FormStateInterface $form_state) {
$this->entity->save();
drupal_set_message($this->t('The action has been successfully saved.'));
$this->messenger()->addStatus($this->t('The action has been successfully saved.'));
$form_state->setRedirect('entity.action.collection');
}
/**
* Gets the action plugin while ensuring it implements configuration form.
*
* @return \Drupal\Core\Action\ActionInterface|\Drupal\Core\Plugin\PluginFormInterface|null
* The action plugin, or NULL if it does not implement configuration forms.
*/
protected function getPlugin() {
if ($this->entity->getPlugin() instanceof PluginFormInterface) {
return $this->entity->getPlugin();
}
return NULL;
}
}

View file

@ -108,12 +108,12 @@ class ActionListBuilder extends ConfigEntityListBuilder {
* {@inheritdoc}
*/
public function render() {
$build['action_admin_manage_form'] = \Drupal::formBuilder()->getForm('Drupal\action\Form\ActionAdminManageForm');
$build['action_header']['#markup'] = '<h3>' . $this->t('Available actions:') . '</h3>';
$build['action_table'] = parent::render();
if (!$this->hasConfigurableActions) {
unset($build['action_table']['table']['#header']['operations']);
}
$build['action_admin_manage_form'] = \Drupal::formBuilder()->getForm('Drupal\action\Form\ActionAdminManageForm');
return $build;
}

View file

@ -3,13 +3,14 @@
namespace Drupal\action\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Action\ActionManager;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a configuration form for configurable actions.
*
* @internal
*/
class ActionAdminManageForm extends FormBase {
@ -53,10 +54,10 @@ class ActionAdminManageForm extends FormBase {
$actions = [];
foreach ($this->manager->getDefinitions() as $id => $definition) {
if (is_subclass_of($definition['class'], '\Drupal\Core\Plugin\PluginFormInterface')) {
$key = Crypt::hashBase64($id);
$actions[$key] = $definition['label'] . '...';
$actions[$id] = $definition['label'];
}
}
asort($actions);
$form['parent'] = [
'#type' => 'details',
'#title' => $this->t('Create an advanced action'),
@ -68,10 +69,10 @@ class ActionAdminManageForm extends FormBase {
'#title' => $this->t('Action'),
'#title_display' => 'invisible',
'#options' => $actions,
'#empty_option' => $this->t('Choose an advanced action'),
'#empty_option' => $this->t('- Select -'),
];
$form['parent']['actions'] = [
'#type' => 'actions'
'#type' => 'actions',
];
$form['parent']['actions']['submit'] = [
'#type' => 'submit',

View file

@ -7,6 +7,8 @@ use Drupal\Core\Url;
/**
* Builds a form to delete an action.
*
* @internal
*/
class ActionDeleteForm extends EntityDeleteForm {

View file

@ -139,12 +139,11 @@ class EmailAction extends ConfigurableActionBase implements ContainerFactoryPlug
}
$params = ['context' => $this->configuration];
if ($this->mailManager->mail('system', 'action_send_email', $recipient, $langcode, $params)) {
$message = $this->mailManager->mail('system', 'action_send_email', $recipient, $langcode, $params);
// Error logging is handled by \Drupal\Core\Mail\MailManager::mail().
if ($message['result']) {
$this->logger->notice('Sent email to %recipient', ['%recipient' => $recipient]);
}
else {
$this->logger->error('Unable to send email to %recipient', ['%recipient' => $recipient]);
}
}
/**

View file

@ -40,7 +40,7 @@ class GotoAction extends ConfigurableActionBase implements ContainerFactoryPlugi
protected $unroutedUrlAssembler;
/**
* Constructs a new DeleteNode object.
* Constructs a GotoAction object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
@ -92,7 +92,7 @@ class GotoAction extends ConfigurableActionBase implements ContainerFactoryPlugi
$url = $this->unroutedUrlAssembler->assemble($uri, $options);
}
$response = new RedirectResponse($url);
$listener = function($event) use ($response) {
$listener = function ($event) use ($response) {
$event->setResponse($response);
};
// Add the listener to the event dispatcher.

View file

@ -5,6 +5,7 @@ namespace Drupal\action\Plugin\Action;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\AccountInterface;
@ -36,6 +37,13 @@ class MessageAction extends ConfigurableActionBase implements ContainerFactoryPl
*/
protected $renderer;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* Constructs a MessageAction object.
*
@ -49,19 +57,22 @@ class MessageAction extends ConfigurableActionBase implements ContainerFactoryPl
* The token service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token, RendererInterface $renderer) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token, RendererInterface $renderer, MessengerInterface $messenger) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->token = $token;
$this->renderer = $renderer;
$this->messenger = $messenger;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('token'), $container->get('renderer'));
return new static($configuration, $plugin_id, $plugin_definition, $container->get('token'), $container->get('renderer'), $container->get('messenger'));
}
/**
@ -77,7 +88,7 @@ class MessageAction extends ConfigurableActionBase implements ContainerFactoryPl
];
// @todo Fix in https://www.drupal.org/node/2577827
drupal_set_message($this->renderer->renderPlain($build));
$this->messenger->addStatus($this->renderer->renderPlain($build));
}
/**

View file

@ -10,7 +10,7 @@ use Drupal\migrate\Row;
*
* @MigrateSource(
* id = "action",
* source_provider = "system"
* source_module = "system"
* )
*/
class Action extends DrupalSqlBase {

View file

@ -5,6 +5,6 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- action
- views
- node
- drupal:action
- drupal:views
- drupal:node

View file

@ -0,0 +1,7 @@
name: action_form_ajax_test
type: module
description: 'module used for testing ajax in action config entity forms.'
package: Core
version: VERSION
core: 8.x
hidden: true

View file

@ -0,0 +1,7 @@
action.configuration.action_form_ajax_test:
type: action_configuration_default
label: 'action_form_ajax_test action'
mapping:
party_time:
type: string
label: 'The time of the party.'

View file

@ -0,0 +1,89 @@
<?php
namespace Drupal\action_form_ajax_test\Plugin\Action;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Plugin used for testing AJAX in action config entity forms.
*
* @Action(
* id = "action_form_ajax_test",
* label = @Translation("action_form_ajax_test"),
* type = "system"
* )
*/
class ActionAjaxTest extends ConfigurableActionBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'party_time' => '',
];
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
$result = AccessResult::allowed();
return $return_as_object ? $result : $result->isAllowed();
}
/**
* {@inheritdoc}
*/
public function execute() {
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$having_a_party = $form_state->getValue('having_a_party', !empty($this->configuration['party_time']));
$form['having_a_party'] = [
'#type' => 'checkbox',
'#title' => $this->t('Are we having a party?'),
'#ajax' => [
'wrapper' => 'party-container',
'callback' => [$this, 'partyCallback'],
],
'#default_value' => $having_a_party,
];
$form['container'] = [
'#type' => 'container',
'#prefix' => '<div id="party-container">',
'#suffix' => '</div>',
];
if ($having_a_party) {
$form['container']['party_time'] = [
'#type' => 'textfield',
'#title' => $this->t('Party time'),
'#default_value' => $this->configuration['party_time'],
];
}
return $form;
}
/**
* Callback for party checkbox.
*/
public function partyCallback(array $form, FormStateInterface $form_state) {
return $form['container'];
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['party_time'] = $form_state->getValue('party_time');
}
}

View file

@ -28,10 +28,10 @@ class ActionListTest extends BrowserTestBase {
// Ensure the empty text appears on the action list page.
/** @var $storage \Drupal\Core\Entity\EntityStorageInterface */
$storage = $this->container->get('entity.manager')->getStorage('action');
$actions = $storage->loadMultiple();
$actions = $storage->loadMultiple();
$storage->delete($actions);
$this->drupalGet('/admin/config/system/actions');
$this->assertRaw('There is no Action yet.');
$this->assertRaw('There are no actions yet.');
}
}

View file

@ -27,7 +27,7 @@ class ActionUninstallTest extends BrowserTestBase {
$storage = $this->container->get('entity_type.manager')->getStorage('action');
$storage->resetCache(['user_block_user_action']);
$this->assertTrue($storage->load('user_block_user_action'), 'Configuration entity \'user_block_user_action\' still exists after uninstalling action module.' );
$this->assertTrue($storage->load('user_block_user_action'), 'Configuration entity \'user_block_user_action\' still exists after uninstalling action module.');
$admin_user = $this->drupalCreateUser(['administer users']);
$this->drupalLogin($admin_user);

View file

@ -148,7 +148,7 @@ class BulkFormTest extends BrowserTestBase {
$errors = $this->xpath('//div[contains(@class, "messages--status")]');
$this->assertFalse($errors, 'No action message shown.');
$this->drupalPostForm(NULL, [], t('Delete'));
$this->assertText(t('Deleted 5 posts.'));
$this->assertText(t('Deleted 5 content items.'));
// Check if we got redirected to the original page.
$this->assertUrl('test_bulk_form');
}

View file

@ -2,7 +2,6 @@
namespace Drupal\Tests\action\Functional;
use Drupal\Component\Utility\Crypt;
use Drupal\system\Entity\Action;
use Drupal\Tests\BrowserTestBase;
@ -31,7 +30,7 @@ class ConfigurationTest extends BrowserTestBase {
// Make a POST request to admin/config/system/actions.
$edit = [];
$edit['action'] = Crypt::hashBase64('action_goto_action');
$edit['action'] = 'action_goto_action';
$this->drupalPostForm('admin/config/system/actions', $edit, t('Create'));
$this->assertResponse(200);
@ -41,17 +40,18 @@ class ConfigurationTest extends BrowserTestBase {
$edit['label'] = $action_label;
$edit['id'] = strtolower($action_label);
$edit['url'] = 'admin';
$this->drupalPostForm('admin/config/system/actions/add/' . Crypt::hashBase64('action_goto_action'), $edit, t('Save'));
$this->drupalPostForm('admin/config/system/actions/add/action_goto_action', $edit, t('Save'));
$this->assertResponse(200);
$action_id = $edit['id'];
// Make sure that the new complex action was saved properly.
$this->assertText(t('The action has been successfully saved.'), "Make sure we get a confirmation that we've successfully saved the complex action.");
$this->assertText($action_label, "Make sure the action label appears on the configuration page after we've saved the complex action.");
// Make another POST request to the action edit page.
$this->clickLink(t('Configure'));
preg_match('|admin/config/system/actions/configure/(.+)|', $this->getUrl(), $matches);
$aid = $matches[1];
$edit = [];
$new_action_label = $this->randomMachineName();
$edit['label'] = $new_action_label;
@ -73,7 +73,7 @@ class ConfigurationTest extends BrowserTestBase {
$this->clickLink(t('Delete'));
$this->assertResponse(200);
$edit = [];
$this->drupalPostForm("admin/config/system/actions/configure/$aid/delete", $edit, t('Delete'));
$this->drupalPostForm(NULL, $edit, t('Delete'));
$this->assertResponse(200);
// Make sure that the action was actually deleted.
@ -82,7 +82,7 @@ class ConfigurationTest extends BrowserTestBase {
$this->assertResponse(200);
$this->assertNoText($new_action_label, "Make sure the action label does not appear on the overview page after we've deleted the action.");
$action = Action::load($aid);
$action = Action::load($action_id);
$this->assertFalse($action, 'Make sure the action is gone after being deleted.');
}

View file

@ -0,0 +1,68 @@
<?php
namespace Drupal\Tests\action\FunctionalJavascript;
use Drupal\Core\Url;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\system\Entity\Action;
/**
* Tests action plugins using Javascript.
*
* @group action
*/
class ActionFormAjaxTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['action', 'action_form_ajax_test'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$user = $this->drupalCreateUser(['administer actions']);
$this->drupalLogin($user);
}
/**
* Tests action plugins with AJAX save their configuration.
*/
public function testActionConfigurationWithAjax() {
$url = Url::fromRoute('action.admin_add', ['action_id' => 'action_form_ajax_test']);
$this->drupalGet($url);
$page = $this->getSession()->getPage();
$id = 'test_plugin';
$this->assertSession()->waitForElementVisible('named', ['button', 'Edit'])->press();
$this->assertSession()->waitForElementVisible('css', '[name="id"]')->setValue($id);
$page->find('css', '[name="having_a_party"]')
->check();
$this->assertSession()->waitForElementVisible('css', '[name="party_time"]');
$party_time = 'Evening';
$page->find('css', '[name="party_time"]')
->setValue($party_time);
$page->find('css', '[value="Save"]')
->click();
$url = Url::fromRoute('entity.action.collection');
$this->assertSession()->pageTextContains('The action has been successfully saved.');
$this->assertSession()->addressEquals($url);
// Check storage.
$instance = Action::load($id);
$configuration = $instance->getPlugin()->getConfiguration();
$this->assertEquals(['party_time' => $party_time], $configuration);
// Configuration should be shown in edit form.
$this->drupalGet($instance->toUrl('edit-form'));
$this->assertSession()->checkboxChecked('having_a_party');
$this->assertSession()->fieldValueEquals('party_time', $party_time);
}
}

View file

@ -40,7 +40,7 @@ class MigrateActionsTest extends MigrateDrupal6TestBase {
$this->assertEntity('send_e_mail', 'Send e-mail', 'system', [
"recipient" => "test@example.com",
"subject" => "Drupal migration test",
"message" => "Drupal migration test"
"message" => "Drupal migration test",
]);
$this->assertEntity('redirect_to_url', 'Redirect to URL', 'system', ["url" => "https://www.drupal.org"]);

View file

@ -40,7 +40,7 @@ class MigrateActionsTest extends MigrateDrupal7TestBase {
$this->assertEntity('send_e_mail', 'Send e-mail', 'system', [
"recipient" => "test@example.com",
"subject" => "Drupal migration test",
"message" => "Drupal migration test"
"message" => "Drupal migration test",
]);
$this->assertEntity('redirect_to_url', 'Redirect to URL', 'system', ["url" => "https://www.drupal.org"]);

View file

@ -0,0 +1,65 @@
<?php
namespace Drupal\Tests\action\Kernel\Plugin\Action;
use Drupal\Core\Test\AssertMailTrait;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests for the EmailAction plugin.
*
* @group action
*/
class EmailActionTest extends KernelTestBase {
use AssertMailTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['system', 'user', 'action', 'dblog'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installSchema('dblog', ['watchdog']);
}
/**
* Test the email action plugin.
*/
public function testEmailAction() {
/** @var \Drupal\Core\Action\ActionManager $plugin_manager */
$plugin_manager = $this->container->get('plugin.manager.action');
$configuration = [
'recipient' => 'test@example.com',
'subject' => 'Test subject',
'message' => 'Test message',
];
$plugin_manager
->createInstance('action_send_email_action', $configuration)
->execute();
$mails = $this->getMails();
$this->assertCount(1, $this->getMails());
$this->assertEquals('test@example.com', $mails[0]['to']);
$this->assertEquals('Test subject', $mails[0]['subject']);
$this->assertEquals("Test message\n", $mails[0]['body']);
// Ensure that the email sending is logged.
$log = \Drupal::database()
->select('watchdog', 'w')
->fields('w', ['message', 'variables'])
->orderBy('wid', 'DESC')
->range(0, 1)
->execute()
->fetch();
$this->assertEquals($log->message, 'Sent email to %recipient');
$variables = unserialize($log->variables);
$this->assertEquals($variables['%recipient'], 'test@example.com');
}
}

View file

@ -15,7 +15,7 @@ class ActionTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['action', 'migrate_drupal'];
public static $modules = ['action', 'migrate_drupal', 'system'];
/**
* {@inheritdoc}

View file

@ -6,5 +6,5 @@ version: VERSION
core: 8.x
configure: aggregator.admin_settings
dependencies:
- file
- options
- drupal:file
- drupal:options

View file

@ -40,3 +40,13 @@ function aggregator_update_8200() {
$field_definition->setRequired(TRUE);
$definition_update_manager->updateFieldStorageDefinition($field_definition);
}
/**
* Add a default value for the 'Refresh' field for aggregator feed entities.
*/
function aggregator_update_8501() {
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$field_definition = $definition_update_manager->getFieldStorageDefinition('refresh', 'aggregator_feed');
$field_definition->setDefaultValue(3600);
$definition_update_manager->updateFieldStorageDefinition($field_definition);
}

View file

@ -13,6 +13,8 @@ use Drupal\Core\Routing\RouteMatchInterface;
*
* @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0.
* Use \Drupal\aggregator\FeedStorageInterface::CLEAR_NEVER instead.
*
* @see https://www.drupal.org/node/2831620
*/
const AGGREGATOR_CLEAR_NEVER = 0;

View file

@ -1,7 +1,9 @@
id: d6_aggregator_feed
label: Aggregator feeds
audit: true
migration_tags:
- Drupal 6
- Content
source:
plugin: aggregator_feed
process:

View file

@ -1,7 +1,9 @@
id: d6_aggregator_item
label: Aggregator items
audit: true
migration_tags:
- Drupal 6
- Content
source:
plugin: aggregator_item
process:

View file

@ -2,6 +2,7 @@ id: d6_aggregator_settings
label: Aggregator configuration
migration_tags:
- Drupal 6
- Configuration
source:
plugin: variable
variables:
@ -12,6 +13,7 @@ source:
- aggregator_teaser_length
- aggregator_clear
- aggregator_summary_items
source_module: aggregator
process:
fetcher: aggregator_fetcher
parser: aggregator_parser

View file

@ -1,7 +1,9 @@
id: d7_aggregator_feed
label: Aggregator feeds
audit: true
migration_tags:
- Drupal 7
- Content
source:
plugin: aggregator_feed
process:

View file

@ -1,7 +1,9 @@
id: d7_aggregator_item
label: Aggregator items
audit: true
migration_tags:
- Drupal 7
- Content
source:
plugin: aggregator_item
process:

View file

@ -2,6 +2,7 @@ id: d7_aggregator_settings
label: Aggregator configuration
migration_tags:
- Drupal 7
- Configuration
source:
plugin: variable
variables:
@ -12,6 +13,7 @@ source:
- aggregator_teaser_length
- aggregator_clear
- aggregator_summary_items
source_module: aggregator
process:
fetcher: aggregator_fetcher
parser: aggregator_parser

View file

@ -25,7 +25,7 @@ class AggregatorController extends ControllerBase {
* Constructs a \Drupal\aggregator\Controller\AggregatorController object.
*
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The date formatter service.
* The date formatter service.
*/
public function __construct(DateFormatterInterface $date_formatter) {
$this->dateFormatter = $date_formatter;
@ -44,13 +44,11 @@ class AggregatorController extends ControllerBase {
* Presents the aggregator feed creation form.
*
* @return array
* A form array as expected by drupal_render().
* A form array as expected by
* \Drupal\Core\Render\RendererInterface::render().
*/
public function feedAdd() {
$feed = $this->entityManager()->getStorage('aggregator_feed')
->create([
'refresh' => 3600,
]);
$feed = $this->entityManager()->getStorage('aggregator_feed')->create();
return $this->entityFormBuilder()->getForm($feed);
}
@ -96,7 +94,7 @@ class AggregatorController extends ControllerBase {
$message = $aggregator_feed->refreshItems()
? $this->t('There is new syndicated content from %site.', ['%site' => $aggregator_feed->label()])
: $this->t('There is no new syndicated content from %site.', ['%site' => $aggregator_feed->label()]);
drupal_set_message($message);
$this->messenger()->addStatus($message);
return $this->redirect('aggregator.admin_overview');
}
@ -104,7 +102,8 @@ class AggregatorController extends ControllerBase {
* Displays the aggregator administration page.
*
* @return array
* A render array as expected by drupal_render().
* A render array as expected by
* \Drupal\Core\Render\RendererInterface::render().
*/
public function adminOverview() {
$entity_manager = $this->entityManager();

View file

@ -14,6 +14,13 @@ use Drupal\aggregator\FeedInterface;
* @ContentEntityType(
* id = "aggregator_feed",
* label = @Translation("Aggregator feed"),
* label_collection = @Translation("Aggregator feeds"),
* label_singular = @Translation("aggregator feed"),
* label_plural = @Translation("aggregator feeds"),
* label_count = @PluralTranslation(
* singular = "@count aggregator feed",
* plural = "@count aggregator feeds",
* ),
* handlers = {
* "storage" = "Drupal\aggregator\FeedStorage",
* "storage_schema" = "Drupal\aggregator\FeedStorageSchema",
@ -168,6 +175,7 @@ class Feed extends ContentEntityBase implements FeedInterface {
$fields['refresh'] = BaseFieldDefinition::create('list_integer')
->setLabel(t('Update interval'))
->setDescription(t('The length of time between feed updates. Requires a correctly configured cron maintenance task.'))
->setDefaultValue(3600)
->setSetting('unsigned', TRUE)
->setRequired(TRUE)
->setSetting('allowed_values', $period)

View file

@ -16,6 +16,13 @@ use Drupal\Core\Url;
* @ContentEntityType(
* id = "aggregator_item",
* label = @Translation("Aggregator feed item"),
* label_collection = @Translation("Aggregator feed items"),
* label_singular = @Translation("aggregator feed item"),
* label_plural = @Translation("aggregator feed items"),
* label_count = @PluralTranslation(
* singular = "@count aggregator feed item",
* plural = "@count aggregator feed items",
* ),
* handlers = {
* "storage" = "Drupal\aggregator\ItemStorage",
* "storage_schema" = "Drupal\aggregator\ItemStorageSchema",
@ -232,7 +239,6 @@ class Item extends ContentEntityBase implements ItemInterface {
return Feed::load($this->getFeedId())->getCacheTags();
}
/**
* Entity URI callback.
*/

View file

@ -8,6 +8,8 @@ use Drupal\Core\Url;
/**
* Form handler for the aggregator feed edit forms.
*
* @internal
*/
class FeedForm extends ContentEntityForm {
@ -20,12 +22,12 @@ class FeedForm extends ContentEntityForm {
$label = $feed->label();
$view_link = $feed->link($label, 'canonical');
if ($status == SAVED_UPDATED) {
drupal_set_message($this->t('The feed %feed has been updated.', ['%feed' => $view_link]));
$this->messenger()->addStatus($this->t('The feed %feed has been updated.', ['%feed' => $view_link]));
$form_state->setRedirectUrl($feed->urlInfo('canonical'));
}
else {
$this->logger('aggregator')->notice('Feed %feed added.', ['%feed' => $feed->label(), 'link' => $this->l($this->t('View'), new Url('aggregator.admin_overview'))]);
drupal_set_message($this->t('The feed %feed has been added.', ['%feed' => $view_link]));
$this->messenger()->addStatus($this->t('The feed %feed has been added.', ['%feed' => $view_link]));
}
}

View file

@ -16,7 +16,7 @@ class FeedStorage extends SqlContentEntityStorage implements FeedStorageInterfac
* {@inheritdoc}
*/
public function getFeedIdsToRefresh() {
return $this->database->query('SELECT fid FROM {aggregator_feed} WHERE queued = 0 AND checked + refresh < :time AND refresh <> :never', [
return $this->database->query('SELECT fid FROM {' . $this->getBaseTable() . '} WHERE queued = 0 AND checked + refresh < :time AND refresh <> :never', [
':time' => REQUEST_TIME,
':never' => AGGREGATOR_CLEAR_NEVER,
])->fetchCol();

View file

@ -17,7 +17,7 @@ class FeedStorageSchema extends SqlContentEntityStorageSchema {
$schema = parent::getSharedTableFieldSchema($storage_definition, $table_name, $column_mapping);
$field_name = $storage_definition->getName();
if ($table_name == 'aggregator_feed') {
if ($table_name == $this->storage->getBaseTable()) {
switch ($field_name) {
case 'url':
$this->addSharedTableFieldIndex($storage_definition, $schema, TRUE, 255);

View file

@ -7,6 +7,8 @@ use Drupal\Core\Url;
/**
* Provides a form for deleting a feed.
*
* @internal
*/
class FeedDeleteForm extends ContentEntityDeleteForm {

View file

@ -8,6 +8,8 @@ use Drupal\Core\Url;
/**
* Provides a deletion confirmation form for items that belong to a feed.
*
* @internal
*/
class FeedItemsDeleteForm extends ContentEntityConfirmFormBase {

View file

@ -12,6 +12,8 @@ use GuzzleHttp\ClientInterface;
/**
* Imports feeds from OPML.
*
* @internal
*/
class OpmlFeedAdd extends FormBase {
@ -121,14 +123,14 @@ class OpmlFeedAdd extends FormBase {
}
catch (RequestException $e) {
$this->logger('aggregator')->warning('Failed to download OPML file due to "%error".', ['%error' => $e->getMessage()]);
drupal_set_message($this->t('Failed to download OPML file due to "%error".', ['%error' => $e->getMessage()]));
$this->messenger()->addStatus($this->t('Failed to download OPML file due to "%error".', ['%error' => $e->getMessage()]));
return;
}
}
$feeds = $this->parseOpml($data);
if (empty($feeds)) {
drupal_set_message($this->t('No new feed has been added.'));
$this->messenger()->addStatus($this->t('No new feed has been added.'));
return;
}
@ -136,7 +138,7 @@ class OpmlFeedAdd extends FormBase {
foreach ($feeds as $feed) {
// Ensure URL is valid.
if (!UrlHelper::isValid($feed['url'], TRUE)) {
drupal_set_message($this->t('The URL %url is invalid.', ['%url' => $feed['url']]), 'warning');
$this->messenger()->addWarning($this->t('The URL %url is invalid.', ['%url' => $feed['url']]));
continue;
}
@ -151,11 +153,11 @@ class OpmlFeedAdd extends FormBase {
$result = $this->feedStorage->loadMultiple($ids);
foreach ($result as $old) {
if (strcasecmp($old->label(), $feed['title']) == 0) {
drupal_set_message($this->t('A feed named %title already exists.', ['%title' => $old->label()]), 'warning');
$this->messenger()->addWarning($this->t('A feed named %title already exists.', ['%title' => $old->label()]));
continue 2;
}
if (strcasecmp($old->getUrl(), $feed['url']) == 0) {
drupal_set_message($this->t('A feed with the URL %url already exists.', ['%url' => $old->getUrl()]), 'warning');
$this->messenger()->addWarning($this->t('A feed with the URL %url already exists.', ['%url' => $old->getUrl()]));
continue 2;
}
}

View file

@ -3,7 +3,7 @@
namespace Drupal\aggregator\Form;
use Drupal\aggregator\Plugin\AggregatorPluginManager;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginFormInterface;
@ -13,6 +13,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Configures aggregator settings for this site.
*
* @internal
*/
class SettingsForm extends ConfigFormBase {
@ -66,7 +68,7 @@ class SettingsForm extends ConfigFormBase {
// Get all available fetcher, parser and processor definitions.
foreach (['fetcher', 'parser', 'processor'] as $type) {
foreach ($this->managers[$type]->getDefinitions() as $id => $definition) {
$this->definitions[$type][$id] = SafeMarkup::format('@title <span class="description">@description</span>', ['@title' => $definition['title'], '@description' => $definition['description']]);
$this->definitions[$type][$id] = new FormattableMarkup('@title <span class="description">@description</span>', ['@title' => $definition['title'], '@description' => $definition['description']]);
}
}
}

View file

@ -17,7 +17,7 @@ class ItemStorageSchema extends SqlContentEntityStorageSchema {
$schema = parent::getSharedTableFieldSchema($storage_definition, $table_name, $column_mapping);
$field_name = $storage_definition->getName();
if ($table_name == 'aggregator_item') {
if ($table_name == $this->storage->getBaseTable()) {
switch ($field_name) {
case 'timestamp':
$this->addSharedTableFieldIndex($storage_definition, $schema, TRUE);

View file

@ -94,7 +94,7 @@ class ItemsImporter implements ItemsImporterInterface {
watchdog_exception('aggregator', $e);
}
// Store instances in an array so we dont have to instantiate new objects.
// Store instances in an array so we don't have to instantiate new objects.
$processor_instances = [];
foreach ($this->config->get('processors') as $processor) {
try {

View file

@ -57,7 +57,6 @@ class AggregatorFeedBlock extends BlockBase implements ContainerFactoryPluginInt
$this->itemStorage = $item_storage;
}
/**
* {@inheritdoc}
*/
@ -71,7 +70,6 @@ class AggregatorFeedBlock extends BlockBase implements ContainerFactoryPluginInt
);
}
/**
* {@inheritdoc}
*/
@ -167,8 +165,10 @@ class AggregatorFeedBlock extends BlockBase implements ContainerFactoryPluginInt
*/
public function getCacheTags() {
$cache_tags = parent::getCacheTags();
$feed = $this->feedStorage->load($this->configuration['feed']);
return Cache::mergeTags($cache_tags, $feed->getCacheTags());
if ($feed = $this->feedStorage->load($this->configuration['feed'])) {
$cache_tags = Cache::mergeTags($cache_tags, $feed->getCacheTags());
}
return $cache_tags;
}
}

View file

@ -21,6 +21,7 @@ use Drupal\Core\Url;
* )
*/
class AggregatorTitleFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/

View file

@ -6,6 +6,7 @@ use Drupal\aggregator\Plugin\FetcherInterface;
use Drupal\aggregator\FeedInterface;
use Drupal\Component\Datetime\DateTimePlus;
use Drupal\Core\Http\ClientFactory;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Request;
@ -42,6 +43,13 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
*/
protected $logger;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* Constructs a DefaultFetcher object.
*
@ -49,10 +57,13 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
* A Guzzle client object.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
*/
public function __construct(ClientFactory $http_client_factory, LoggerInterface $logger) {
public function __construct(ClientFactory $http_client_factory, LoggerInterface $logger, MessengerInterface $messenger) {
$this->httpClientFactory = $http_client_factory;
$this->logger = $logger;
$this->messenger = $messenger;
}
/**
@ -61,7 +72,8 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$container->get('http_client_factory'),
$container->get('logger.factory')->get('aggregator')
$container->get('logger.factory')->get('aggregator'),
$container->get('messenger')
);
}
@ -84,11 +96,13 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
/** @var \Psr\Http\Message\UriInterface $actual_uri */
$actual_uri = NULL;
$response = $this->httpClientFactory->fromOptions(['allow_redirects' => [
'on_redirect' => function(RequestInterface $request, ResponseInterface $response, UriInterface $uri) use (&$actual_uri) {
$actual_uri = (string) $uri;
}
]])->send($request);
$response = $this->httpClientFactory->fromOptions([
'allow_redirects' => [
'on_redirect' => function (RequestInterface $request, ResponseInterface $response, UriInterface $uri) use (&$actual_uri) {
$actual_uri = (string) $uri;
},
],
])->send($request);
// In case of a 304 Not Modified, there is no new content, so return
// FALSE.
@ -113,7 +127,7 @@ class DefaultFetcher implements FetcherInterface, ContainerFactoryPluginInterfac
}
catch (RequestException $e) {
$this->logger->warning('The feed from %site seems to be broken because of error "%error".', ['%site' => $feed->label(), '%error' => $e->getMessage()]);
drupal_set_message(t('The feed from %site seems to be broken because of error "%error".', ['%site' => $feed->label(), '%error' => $e->getMessage()]), 'warning');
$this->messenger->addWarning(t('The feed from %site seems to be broken because of error "%error".', ['%site' => $feed->label(), '%error' => $e->getMessage()]));
return FALSE;
}
}

View file

@ -4,6 +4,7 @@ namespace Drupal\aggregator\Plugin\aggregator\parser;
use Drupal\aggregator\Plugin\ParserInterface;
use Drupal\aggregator\FeedInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Zend\Feed\Reader\Reader;
use Zend\Feed\Reader\Exception\ExceptionInterface;
@ -20,6 +21,8 @@ use Zend\Feed\Reader\Exception\ExceptionInterface;
*/
class DefaultParser implements ParserInterface {
use MessengerTrait;
/**
* {@inheritdoc}
*/
@ -31,7 +34,7 @@ class DefaultParser implements ParserInterface {
}
catch (ExceptionInterface $e) {
watchdog_exception('aggregator', $e);
drupal_set_message(t('The feed from %site seems to be broken because of error "%error".', ['%site' => $feed->label(), '%error' => $e->getMessage()]), 'error');
$this->messenger()->addError(t('The feed from %site seems to be broken because of error "%error".', ['%site' => $feed->label(), '%error' => $e->getMessage()]));
return FALSE;
}

View file

@ -3,15 +3,16 @@
namespace Drupal\aggregator\Plugin\aggregator\processor;
use Drupal\aggregator\Entity\Item;
use Drupal\aggregator\FeedInterface;
use Drupal\aggregator\ItemStorageInterface;
use Drupal\aggregator\Plugin\AggregatorPluginSettingsBase;
use Drupal\aggregator\Plugin\ProcessorInterface;
use Drupal\aggregator\FeedInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Form\ConfigFormBaseTrait;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\UrlGeneratorTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -28,6 +29,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* )
*/
class DefaultProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface, ContainerFactoryPluginInterface {
use ConfigFormBaseTrait;
use UrlGeneratorTrait;
@ -52,6 +54,13 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor
*/
protected $dateFormatter;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* Constructs a DefaultProcessor object.
*
@ -67,11 +76,14 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor
* The entity storage for feed items.
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The date formatter service.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, ItemStorageInterface $item_storage, DateFormatterInterface $date_formatter) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, ItemStorageInterface $item_storage, DateFormatterInterface $date_formatter, MessengerInterface $messenger) {
$this->configFactory = $config;
$this->itemStorage = $item_storage;
$this->dateFormatter = $date_formatter;
$this->messenger = $messenger;
// @todo Refactor aggregator plugins to ConfigEntity so merging
// the configuration here is not needed.
parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition);
@ -87,7 +99,8 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor
$plugin_definition,
$container->get('config.factory'),
$container->get('entity_type.manager')->getStorage('aggregator_item'),
$container->get('date.formatter')
$container->get('date.formatter'),
$container->get('messenger')
);
}
@ -141,7 +154,7 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor
];
$lengths = [0, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000];
$options = array_map(function($length) {
$options = array_map(function ($length) {
return ($length == 0) ? t('Unlimited') : $this->formatPlural($length, '1 character', '@count characters');
}, array_combine($lengths, $lengths));
@ -231,7 +244,7 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor
$this->itemStorage->delete($items);
}
// @todo This should be moved out to caller with a different message maybe.
drupal_set_message(t('The news items from %site have been deleted.', ['%site' => $feed->label()]));
$this->messenger->addStatus(t('The news items from %site have been deleted.', ['%site' => $feed->label()]));
}
/**

View file

@ -9,7 +9,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "aggregator_feed",
* source_provider = "aggregator"
* source_module = "aggregator"
* )
*/
class AggregatorFeed extends DrupalSqlBase {

View file

@ -9,7 +9,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "aggregator_item",
* source_provider = "aggregator"
* source_module = "aggregator"
* )
*/
class AggregatorItem extends DrupalSqlBase {

View file

@ -23,7 +23,7 @@ class Fid extends NumericArgument {
protected $entityManager;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
* Constructs a \Drupal\aggregator\Plugin\views\argument\Fid object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.

View file

@ -23,7 +23,7 @@ class Iid extends NumericArgument {
protected $entityManager;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
* Constructs a \Drupal\aggregator\Plugin\views\argument\Iid object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.

View file

@ -5,5 +5,5 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- aggregator
- views
- drupal:aggregator
- drupal:views

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\aggregator\Tests;
namespace Drupal\Tests\aggregator\Functional;
/**
* Add feed test.
@ -60,7 +60,7 @@ class AddFeedTest extends AggregatorTestBase {
$this->assertNoRaw('Test feed title <script>alert(123);</script>');
// Ensure the feed icon title is escaped.
$this->assertTrue(strpos(str_replace(["\n", "\r"], '', $this->getRawContent()), 'class="feed-icon"> Subscribe to Test feed title &lt;script&gt;alert(123);&lt;/script&gt; feed</a>') !== FALSE);
$this->assertTrue(strpos(str_replace(["\n", "\r"], '', $this->getSession()->getPage()->getContent()), 'class="feed-icon"> Subscribe to Test feed title &lt;script&gt;alert(123);&lt;/script&gt; feed</a>') !== FALSE);
}
/**

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\aggregator\Tests;
namespace Drupal\Tests\aggregator\Functional;
/**
* Tests aggregator admin pages.
@ -67,18 +67,22 @@ class AggregatorAdminTest extends AggregatorTestBase {
// Check if the amount of feeds in the overview matches the amount created.
$this->assertEqual(1, count($result), 'Created feed is found in the overview');
// Check if the fields in the table match with what's expected.
$this->assertEqual($feed->label(), (string) $result[0]->td[0]->a);
$link = $this->xpath('//table/tbody/tr//td[1]/a');
$this->assertEquals($feed->label(), $link[0]->getText());
$count = $this->container->get('entity.manager')->getStorage('aggregator_item')->getItemCount($feed);
$this->assertEqual(\Drupal::translation()->formatPlural($count, '1 item', '@count items'), (string) $result[0]->td[1]);
$td = $this->xpath('//table/tbody/tr//td[2]');
$this->assertEquals(\Drupal::translation()->formatPlural($count, '1 item', '@count items'), $td[0]->getText());
// Update the items of the first feed.
$feed->refreshItems();
$this->drupalGet('admin/config/services/aggregator');
$result = $this->xpath('//table/tbody/tr');
// Check if the fields in the table match with what's expected.
$this->assertEqual($feed->label(), (string) $result[0]->td[0]->a);
$link = $this->xpath('//table/tbody/tr//td[1]/a');
$this->assertEquals($feed->label(), $link[0]->getText());
$count = $this->container->get('entity.manager')->getStorage('aggregator_item')->getItemCount($feed);
$this->assertEqual(\Drupal::translation()->formatPlural($count, '1 item', '@count items'), (string) $result[0]->td[1]);
$td = $this->xpath('//table/tbody/tr//td[2]');
$this->assertEquals(\Drupal::translation()->formatPlural($count, '1 item', '@count items'), $td[0]->getText());
}
}

View file

@ -1,6 +1,8 @@
<?php
namespace Drupal\aggregator\Tests;
namespace Drupal\Tests\aggregator\Functional;
use Drupal\Tests\Traits\Core\CronRunTrait;
/**
* Update feeds on cron.
@ -8,6 +10,9 @@ namespace Drupal\aggregator\Tests;
* @group aggregator
*/
class AggregatorCronTest extends AggregatorTestBase {
use CronRunTrait;
/**
* Adds feeds and updates them via cron process.
*/

View file

@ -1,8 +1,8 @@
<?php
namespace Drupal\aggregator\Tests;
namespace Drupal\Tests\aggregator\Functional;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\views\Entity\View;
/**
@ -114,7 +114,7 @@ class AggregatorRenderingTest extends AggregatorTestBase {
// Find the expected read_more link on the sources page.
$href = $feed->url();
$links = $this->xpath('//a[@href = :href]', [':href' => $href]);
$this->assertTrue(isset($links[0]), SafeMarkup::format('Link to href %href found.', ['%href' => $href]));
$this->assertTrue(isset($links[0]), new FormattableMarkup('Link to href %href found.', ['%href' => $href]));
$cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
$cache_tags = explode(' ', $cache_tags_header);
$this->assertTrue(in_array('aggregator_feed:' . $feed->id(), $cache_tags));
@ -132,10 +132,14 @@ class AggregatorRenderingTest extends AggregatorTestBase {
// Check the opml aggregator page.
$this->drupalGet('aggregator/opml');
$outline = $this->xpath('//outline[1]');
$this->assertEqual($outline[0]['type'], 'rss', 'The correct type attribute is used for rss OPML.');
$this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for rss OPML.');
$this->assertEqual($outline[0]['xmlurl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.');
$content = $this->getSession()->getPage()->getContent();
// We can't use Mink xpath queries here because it only supports HTML pages,
// but we are dealing with XML here.
$xml = simplexml_load_string($content);
$attributes = $xml->xpath('//outline[1]')[0]->attributes();
$this->assertEquals('rss', $attributes->type);
$this->assertEquals($feed->label(), $attributes->text);
$this->assertEquals($feed->getUrl(), $attributes->xmlUrl);
// Check for the presence of a pager.
$this->drupalGet('aggregator/sources/' . $feed->id());

View file

@ -8,6 +8,7 @@ namespace Drupal\Tests\aggregator\Functional;
* @group aggregator
*/
class DeleteFeedItemTest extends AggregatorTestBase {
/**
* Tests running "delete items" from 'admin/config/services/aggregator' page.
*/

View file

@ -40,7 +40,7 @@ class DeleteFeedTest extends AggregatorTestBase {
// Check feed source.
$this->drupalGet('aggregator/sources/' . $feed1->id());
$this->assertResponse(404, 'Deleted feed source does not exists.');
$this->assertResponse(404, 'Deleted feed source does not exist.');
// Check database for feed.
$result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", [':title' => $feed1->label(), ':url' => $feed1->getUrl()])->fetchField();

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\aggregator\Tests;
namespace Drupal\Tests\aggregator\Functional;
/**
* Tests the display of a feed on the Aggregator list page.

View file

@ -3,7 +3,7 @@
namespace Drupal\Tests\aggregator\Functional;
use Drupal\aggregator\Entity\Feed;
use Drupal\system\Tests\Entity\EntityWithUriCacheTagsTestBase;
use Drupal\Tests\system\Functional\Entity\EntityWithUriCacheTagsTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;

View file

@ -1,8 +1,9 @@
<?php
namespace Drupal\aggregator\Tests;
namespace Drupal\Tests\aggregator\Functional;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Tests\Traits\Core\CronRunTrait;
/**
* Tests aggregator feeds in multiple languages.
@ -11,6 +12,8 @@ use Drupal\language\Entity\ConfigurableLanguage;
*/
class FeedLanguageTest extends AggregatorTestBase {
use CronRunTrait;
/**
* Modules to install.
*

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\hal\Functional\EntityResource\Feed;
namespace Drupal\Tests\aggregator\Functional\Hal;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\hal\Functional\EntityResource\Feed;
namespace Drupal\Tests\aggregator\Functional\Hal;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\hal\Functional\EntityResource\Feed;
namespace Drupal\Tests\aggregator\Functional\Hal;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;

View file

@ -1,18 +1,13 @@
<?php
namespace Drupal\Tests\hal\Functional\EntityResource\Term;
namespace Drupal\Tests\aggregator\Functional\Hal;
use Drupal\Tests\aggregator\Functional\Rest\FeedResourceTestBase;
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\Term\TermResourceTestBase;
/**
* @group hal
*/
class TermHalJsonAnonTest extends TermResourceTestBase {
abstract class FeedHalJsonTestBase extends FeedResourceTestBase {
use HalEntityNormalizationTrait;
use AnonResourceTestTrait;
/**
* {@inheritdoc}
@ -40,10 +35,10 @@ class TermHalJsonAnonTest extends TermResourceTestBase {
return $normalization + [
'_links' => [
'self' => [
'href' => $this->baseUrl . '/taxonomy/term/1?_format=hal_json',
'href' => $this->baseUrl . '/aggregator/sources/1?_format=hal_json',
],
'type' => [
'href' => $this->baseUrl . '/rest/type/taxonomy_term/camelids',
'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed',
],
],
];
@ -56,7 +51,7 @@ class TermHalJsonAnonTest extends TermResourceTestBase {
return parent::getNormalizedPostEntity() + [
'_links' => [
'type' => [
'href' => $this->baseUrl . '/rest/type/taxonomy_term/camelids',
'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed',
],
],
];

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\hal\Functional\EntityResource\Item;
namespace Drupal\Tests\aggregator\Functional\Hal;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\hal\Functional\EntityResource\Item;
namespace Drupal\Tests\aggregator\Functional\Hal;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\hal\Functional\EntityResource\Item;
namespace Drupal\Tests\aggregator\Functional\Hal;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;

View file

@ -0,0 +1,100 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Hal;
use Drupal\aggregator\Entity\Feed;
use Drupal\Tests\aggregator\Functional\Rest\ItemResourceTestBase;
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
/**
* ResourceTestBase for Item entity.
*/
abstract class ItemHalJsonTestBase extends ItemResourceTestBase {
use HalEntityNormalizationTrait;
use AnonResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
/**
* {@inheritdoc}
*/
protected function getExpectedNormalizedEntity() {
$default_normalization = parent::getExpectedNormalizedEntity();
$normalization = $this->applyHalFieldNormalization($default_normalization);
$feed = Feed::load($this->entity->getFeedId());
return $normalization + [
'_embedded' => [
$this->baseUrl . '/rest/relation/aggregator_item/aggregator_item/fid' => [
[
'_links' => [
'self' => [
'href' => $this->baseUrl . '/aggregator/sources/1?_format=hal_json',
],
'type' => [
'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed',
],
],
'uuid' => [
[
'value' => $feed->uuid(),
],
],
],
],
],
'_links' => [
'self' => [
'href' => '',
],
'type' => [
'href' => $this->baseUrl . '/rest/type/aggregator_item/aggregator_item',
],
$this->baseUrl . '/rest/relation/aggregator_item/aggregator_item/fid' => [
[
'href' => $this->baseUrl . '/aggregator/sources/' . $feed->id() . '?_format=hal_json',
],
],
],
];
}
/**
* {@inheritdoc}
*/
protected function getNormalizedPostEntity() {
return parent::getNormalizedPostEntity() + [
'_links' => [
'type' => [
'href' => $this->baseUrl . '/rest/type/aggregator_item/aggregator_item',
],
],
];
}
/**
* {@inheritdoc}
*/
protected function getExpectedCacheContexts() {
return [
'url.site',
'user.permissions',
];
}
}

View file

@ -5,7 +5,7 @@ namespace Drupal\Tests\aggregator\Functional;
use Drupal\aggregator\Entity\Feed;
use Drupal\aggregator\Entity\Item;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\system\Tests\Entity\EntityCacheTagsTestBase;
use Drupal\Tests\system\Functional\Entity\EntityCacheTagsTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\rest\Functional\EntityResource\Feed;
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\rest\Functional\EntityResource\Feed;
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\rest\Functional\EntityResource\Feed;
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;

View file

@ -0,0 +1,192 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
use Drupal\aggregator\Entity\Feed;
abstract class FeedResourceTestBase extends EntityResourceTestBase {
use BcTimestampNormalizerUnixTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['aggregator'];
/**
* {@inheritdoc}
*/
public static $entityTypeId = 'aggregator_feed';
/**
* {@inheritdoc}
*/
protected static $patchProtectedFieldNames = [];
/**
* {@inheritdoc}
*/
protected static $uniqueFieldNames = ['url'];
/**
* {@inheritdoc}
*/
protected function setUpAuthorization($method) {
switch ($method) {
case 'GET':
$this->grantPermissionsToTestedRole(['access news feeds']);
break;
case 'POST':
case 'PATCH':
case 'DELETE':
$this->grantPermissionsToTestedRole(['administer news feeds']);
break;
}
}
/**
* {@inheritdoc}
*/
public function createEntity() {
$feed = Feed::create();
$feed->set('fid', 1)
->set('uuid', 'abcdefg')
->setTitle('Feed')
->setUrl('http://example.com/rss.xml')
->setDescription('Feed Resource Test 1')
->setRefreshRate(900)
->setLastCheckedTime(123456789)
->setQueuedTime(123456789)
->setWebsiteUrl('http://example.com')
->setImage('http://example.com/feed_logo')
->setHash('abcdefg')
->setEtag('hijklmn')
->setLastModified(123456789)
->save();
return $feed;
}
/**
* {@inheritdoc}
*/
protected function getExpectedNormalizedEntity() {
return [
'uuid' => [
[
'value' => 'abcdefg',
],
],
'fid' => [
[
'value' => 1,
],
],
'langcode' => [
[
'value' => 'en',
],
],
'url' => [
[
'value' => 'http://example.com/rss.xml',
],
],
'title' => [
[
'value' => 'Feed',
],
],
'refresh' => [
[
'value' => 900,
],
],
'checked' => [
$this->formatExpectedTimestampItemValues(123456789),
],
'queued' => [
$this->formatExpectedTimestampItemValues(123456789),
],
'link' => [
[
'value' => 'http://example.com',
],
],
'description' => [
[
'value' => 'Feed Resource Test 1',
],
],
'image' => [
[
'value' => 'http://example.com/feed_logo',
],
],
'hash' => [
[
'value' => 'abcdefg',
],
],
'etag' => [
[
'value' => 'hijklmn',
],
],
'modified' => [
$this->formatExpectedTimestampItemValues(123456789),
],
];
}
/**
* {@inheritdoc}
*/
protected function getNormalizedPostEntity() {
return [
'title' => [
[
'value' => 'Feed Resource Post Test',
],
],
'url' => [
[
'value' => 'http://example.com/feed',
],
],
'refresh' => [
[
'value' => 900,
],
],
'description' => [
[
'value' => 'Feed Resource Post Test Description',
],
],
];
}
/**
* {@inheritdoc}
*/
protected function getExpectedUnauthorizedAccessMessage($method) {
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
return parent::getExpectedUnauthorizedAccessMessage($method);
}
switch ($method) {
case 'GET':
return "The 'access news feeds' permission is required.";
case 'POST':
case 'PATCH':
case 'DELETE':
return "The 'administer news feeds' permission is required.";
default:
return parent::getExpectedUnauthorizedAccessMessage($method);
}
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class FeedXmlAnonTest extends FeedResourceTestBase {
use AnonResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
}

View file

@ -0,0 +1,36 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class FeedXmlBasicAuthTest extends FeedResourceTestBase {
use BasicAuthResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,31 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class FeedXmlCookieTest extends FeedResourceTestBase {
use CookieResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\rest\Functional\EntityResource\Item;
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\rest\Functional\EntityResource\Item;
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\Tests\rest\Functional\EntityResource\Item;
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;

View file

@ -0,0 +1,192 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\aggregator\Entity\Feed;
use Drupal\aggregator\Entity\Item;
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
/**
* ResourceTestBase for Item entity.
*/
abstract class ItemResourceTestBase extends EntityResourceTestBase {
use BcTimestampNormalizerUnixTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['aggregator'];
/**
* {@inheritdoc}
*/
protected static $entityTypeId = 'aggregator_item';
/**
* {@inheritdoc}
*/
protected static $patchProtectedFieldNames = [];
/**
* The Item entity.
*
* @var \Drupal\aggregator\ItemInterface
*/
protected $entity;
/**
* {@inheritdoc}
*/
protected function setUpAuthorization($method) {
switch ($method) {
case 'GET':
$this->grantPermissionsToTestedRole(['access news feeds']);
break;
case 'POST':
case 'PATCH':
case 'DELETE':
$this->grantPermissionsToTestedRole(['administer news feeds']);
break;
}
}
/**
* {@inheritdoc}
*/
protected function createEntity() {
// Create a "Camelids" feed.
$feed = Feed::create([
'title' => 'Camelids',
'url' => 'https://groups.drupal.org/not_used/167169',
'refresh' => 900,
'checked' => 1389919932,
'description' => 'Drupal Core Group feed',
]);
$feed->save();
// Create a "Llama" item.
$item = Item::create();
$item->setTitle('Llama')
->setFeedId($feed->id())
->setLink('https://www.drupal.org/')
->setPostedTime(123456789)
->save();
return $item;
}
/**
* {@inheritdoc}
*/
protected function createAnotherEntity() {
$entity = $this->entity->createDuplicate();
$entity->setLink('https://www.example.org/');
$label_key = $entity->getEntityType()->getKey('label');
if ($label_key) {
$entity->set($label_key, $entity->label() . '_dupe');
}
$entity->save();
return $entity;
}
/**
* {@inheritdoc}
*/
protected function getExpectedNormalizedEntity() {
$feed = Feed::load($this->entity->getFeedId());
return [
'iid' => [
[
'value' => 1,
],
],
'langcode' => [
[
'value' => 'en',
],
],
'fid' => [
[
'target_id' => 1,
'target_type' => 'aggregator_feed',
'target_uuid' => $feed->uuid(),
'url' => base_path() . 'aggregator/sources/1',
],
],
'title' => [
[
'value' => 'Llama',
],
],
'link' => [
[
'value' => 'https://www.drupal.org/',
],
],
'author' => [],
'description' => [],
'timestamp' => [
$this->formatExpectedTimestampItemValues(123456789),
],
'guid' => [],
];
}
/**
* {@inheritdoc}
*/
protected function getNormalizedPostEntity() {
return [
'fid' => [
[
'target_id' => 1,
],
],
'title' => [
[
'value' => 'Llama',
],
],
'link' => [
[
'value' => 'https://www.drupal.org/',
],
],
];
}
/**
* {@inheritdoc}
*/
protected function getExpectedCacheContexts() {
// @see ::createEntity()
return ['user.permissions'];
}
/**
* {@inheritdoc}
*/
protected function getExpectedUnauthorizedAccessMessage($method) {
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
return parent::getExpectedUnauthorizedAccessMessage($method);
}
switch ($method) {
case 'GET':
return "The 'access news feeds' permission is required.";
case 'POST':
case 'PATCH':
case 'DELETE':
return "The 'administer news feeds' permission is required.";
default:
return parent::getExpectedUnauthorizedAccessMessage($method);
}
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class ItemXmlAnonTest extends ItemResourceTestBase {
use AnonResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
}

View file

@ -0,0 +1,36 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class ItemXmlBasicAuthTest extends ItemResourceTestBase {
use BasicAuthResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,31 @@
<?php
namespace Drupal\Tests\aggregator\Functional\Rest;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class ItemXmlCookieTest extends ItemResourceTestBase {
use CookieResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -1,13 +1,14 @@
<?php
namespace Drupal\aggregator\Tests\Update;
namespace Drupal\Tests\aggregator\Functional\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests that node settings are properly updated during database updates.
*
* @group aggregator
* @group legacy
*/
class AggregatorUpdateTest extends UpdatePathTestBase {
@ -16,7 +17,7 @@ class AggregatorUpdateTest extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.filled.standard.php.gz',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.filled.standard.php.gz',
];
}
@ -38,4 +39,21 @@ class AggregatorUpdateTest extends UpdatePathTestBase {
$this->assertTrue($field_definition->isRequired());
}
/**
* Tests that the 'Update interval' field has a default value.
*/
public function testUpdateIntervalDefaultValue() {
// Check that the 'refresh' field does not have a default value prior to the
// update.
$field_definition = \Drupal::entityDefinitionUpdateManager()->getFieldStorageDefinition('refresh', 'aggregator_feed');
$this->assertSame([], $field_definition->getDefaultValueLiteral());
// Run updates.
$this->runUpdates();
// Check that the 'refresh' has a default value now.
$field_definition = \Drupal::entityDefinitionUpdateManager()->getFieldStorageDefinition('refresh', 'aggregator_feed');
$this->assertSame([['value' => 3600]], $field_definition->getDefaultValueLiteral());
}
}

View file

@ -1,6 +1,7 @@
<?php
namespace Drupal\aggregator\Tests;
namespace Drupal\Tests\aggregator\Functional;
use Drupal\aggregator\Entity\Feed;
/**
@ -9,6 +10,7 @@ use Drupal\aggregator\Entity\Feed;
* @group aggregator
*/
class UpdateFeedItemTest extends AggregatorTestBase {
/**
* Tests running "update items" from 'admin/config/services/aggregator' page.
*/

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\aggregator\Tests;
namespace Drupal\Tests\aggregator\Functional;
/**
* Update feed test.
@ -8,6 +8,7 @@ namespace Drupal\aggregator\Tests;
* @group aggregator
*/
class UpdateFeedTest extends AggregatorTestBase {
/**
* Creates a feed and attempts to update it.
*/

View file

@ -6,7 +6,6 @@ use Drupal\aggregator\Entity\Feed;
use Drupal\aggregator\Entity\Item;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests the aggregator_title formatter.
*

View file

@ -2,7 +2,6 @@
namespace Drupal\Tests\aggregator\Kernel\Migrate;
use Drupal\migrate\MigrateException;
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
use Drupal\migrate_drupal\Tests\StubTestTrait;
@ -40,18 +39,6 @@ class MigrateAggregatorStubTest extends MigrateDrupalTestBase {
* Tests creation of aggregator feed items.
*/
public function testItemStub() {
try {
// We expect an exception, because there's no feed to reference.
$this->performStubTest('aggregator_item');
$this->fail('Expected exception has not been thrown.');
}
catch (MigrateException $e) {
$this->assertIdentical($e->getMessage(),
'Stubbing failed, unable to generate value for field fid');
}
// The stub should pass when there's a feed to point to.
$this->createStub('aggregator_feed');
$this->performStubTest('aggregator_item');
}

View file

@ -4,6 +4,7 @@ namespace Drupal\Tests\aggregator\Unit\Plugin;
use Drupal\aggregator\Form\SettingsForm;
use Drupal\Core\Form\FormState;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Tests\UnitTestCase;
/**
@ -55,6 +56,10 @@ class AggregatorPluginSettingsBaseTest extends UnitTestCase {
->will($this->returnValue(['aggregator_test' => ['title' => '', 'description' => '']]));
}
/** @var \Drupal\Core\Messenger\MessengerInterface|\PHPUnit_Framework_MockObject_MockBuilder $messenger */
$messenger = $this->createMock(MessengerInterface::class);
$messenger->expects($this->any())->method('addMessage');
$this->settingsForm = new SettingsForm(
$this->configFactory,
$this->managers['fetcher'],
@ -62,6 +67,7 @@ class AggregatorPluginSettingsBaseTest extends UnitTestCase {
$this->managers['processor'],
$this->getStringTranslationStub()
);
$this->settingsForm->setMessenger($messenger);
}
/**
@ -104,10 +110,3 @@ class AggregatorPluginSettingsBaseTest extends UnitTestCase {
}
}
// @todo Delete after https://www.drupal.org/node/2278383 is in.
namespace Drupal\Core\Form;
if (!function_exists('drupal_set_message')) {
function drupal_set_message() {}
}

View file

@ -31,7 +31,7 @@ class AutomatedCron implements EventSubscriberInterface {
/**
* The state key value store.
*
* @var \Drupal\Core\State\StateInterface;
* @var \Drupal\Core\State\StateInterface
*/
protected $state;

View file

@ -2,6 +2,7 @@ id: d7_blocked_ips
label: Blocked IPs
migration_tags:
- Drupal 7
- Content
source:
plugin: d7_blocked_ips
process:

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