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
|
@ -15,6 +15,7 @@ use Drupal\Core\Render\BareHtmlPageRendererInterface;
|
|||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\Core\Update\UpdateRegistry;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
@ -74,6 +75,13 @@ class DbUpdateController extends ControllerBase {
|
|||
*/
|
||||
protected $root;
|
||||
|
||||
/**
|
||||
* The post update registry.
|
||||
*
|
||||
* @var \Drupal\Core\Update\UpdateRegistry
|
||||
*/
|
||||
protected $postUpdateRegistry;
|
||||
|
||||
/**
|
||||
* Constructs a new UpdateController.
|
||||
*
|
||||
|
@ -91,8 +99,10 @@ class DbUpdateController extends ControllerBase {
|
|||
* The current user.
|
||||
* @param \Drupal\Core\Render\BareHtmlPageRendererInterface $bare_html_page_renderer
|
||||
* The bare HTML page renderer.
|
||||
* @param \Drupal\Core\Update\UpdateRegistry $post_update_registry
|
||||
* The post update registry.
|
||||
*/
|
||||
public function __construct($root, KeyValueExpirableFactoryInterface $key_value_expirable_factory, CacheBackendInterface $cache, StateInterface $state, ModuleHandlerInterface $module_handler, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer) {
|
||||
public function __construct($root, KeyValueExpirableFactoryInterface $key_value_expirable_factory, CacheBackendInterface $cache, StateInterface $state, ModuleHandlerInterface $module_handler, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer, UpdateRegistry $post_update_registry) {
|
||||
$this->root = $root;
|
||||
$this->keyValueExpirableFactory = $key_value_expirable_factory;
|
||||
$this->cache = $cache;
|
||||
|
@ -100,6 +110,7 @@ class DbUpdateController extends ControllerBase {
|
|||
$this->moduleHandler = $module_handler;
|
||||
$this->account = $account;
|
||||
$this->bareHtmlPageRenderer = $bare_html_page_renderer;
|
||||
$this->postUpdateRegistry = $post_update_registry;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,7 +124,8 @@ class DbUpdateController extends ControllerBase {
|
|||
$container->get('state'),
|
||||
$container->get('module_handler'),
|
||||
$container->get('current_user'),
|
||||
$container->get('bare_html_page_renderer')
|
||||
$container->get('bare_html_page_renderer'),
|
||||
$container->get('update.post_update_registry')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -210,8 +222,8 @@ class DbUpdateController extends ControllerBase {
|
|||
);
|
||||
|
||||
$info[] = $this->t("<strong>Back up your code</strong>. Hint: when backing up module code, do not leave that backup in the 'modules' or 'sites/*/modules' directories as this may confuse Drupal's auto-discovery mechanism.");
|
||||
$info[] = $this->t('Put your site into <a href="@url">maintenance mode</a>.', array(
|
||||
'@url' => Url::fromRoute('system.site_maintenance_mode')->toString(TRUE)->getGeneratedUrl(),
|
||||
$info[] = $this->t('Put your site into <a href=":url">maintenance mode</a>.', array(
|
||||
':url' => Url::fromRoute('system.site_maintenance_mode')->toString(TRUE)->getGeneratedUrl(),
|
||||
));
|
||||
$info[] = $this->t('<strong>Back up your database</strong>. This process will change your database values and in case of emergency you may need to revert to a backup.');
|
||||
$info[] = $this->t('Install your new files in the appropriate location, as described in the handbook.');
|
||||
|
@ -257,35 +269,52 @@ class DbUpdateController extends ControllerBase {
|
|||
// Ensure system.module's updates appear first.
|
||||
$build['start']['system'] = array();
|
||||
|
||||
$updates = update_get_update_list();
|
||||
$starting_updates = array();
|
||||
$incompatible_updates_exist = FALSE;
|
||||
foreach ($updates as $module => $update) {
|
||||
if (!isset($update['start'])) {
|
||||
$build['start'][$module] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => $module . ' module',
|
||||
'#markup' => $update['warning'],
|
||||
'#prefix' => '<div class="messages messages--warning">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
$incompatible_updates_exist = TRUE;
|
||||
continue;
|
||||
$updates_per_module = [];
|
||||
foreach (['update', 'post_update'] as $update_type) {
|
||||
switch ($update_type) {
|
||||
case 'update':
|
||||
$updates = update_get_update_list();
|
||||
break;
|
||||
case 'post_update':
|
||||
$updates = $this->postUpdateRegistry->getPendingUpdateInformation();
|
||||
break;
|
||||
}
|
||||
if (!empty($update['pending'])) {
|
||||
$starting_updates[$module] = $update['start'];
|
||||
$build['start'][$module] = array(
|
||||
'#type' => 'hidden',
|
||||
'#value' => $update['start'],
|
||||
);
|
||||
$build['start'][$module . '_updates'] = array(
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $update['pending'],
|
||||
'#title' => $module . ' module',
|
||||
);
|
||||
}
|
||||
if (isset($update['pending'])) {
|
||||
$count = $count + count($update['pending']);
|
||||
foreach ($updates as $module => $update) {
|
||||
if (!isset($update['start'])) {
|
||||
$build['start'][$module] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => $module . ' module',
|
||||
'#markup' => $update['warning'],
|
||||
'#prefix' => '<div class="messages messages--warning">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
$incompatible_updates_exist = TRUE;
|
||||
continue;
|
||||
}
|
||||
if (!empty($update['pending'])) {
|
||||
$updates_per_module += [$module => []];
|
||||
$updates_per_module[$module] = array_merge($updates_per_module[$module], $update['pending']);
|
||||
$build['start'][$module] = array(
|
||||
'#type' => 'hidden',
|
||||
'#value' => $update['start'],
|
||||
);
|
||||
// Store the previous items in order to merge normal updates and
|
||||
// post_update functions together.
|
||||
$build['start'][$module] = array(
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $updates_per_module[$module],
|
||||
'#title' => $module . ' module',
|
||||
);
|
||||
|
||||
if ($update_type === 'update') {
|
||||
$starting_updates[$module] = $update['start'];
|
||||
}
|
||||
}
|
||||
if (isset($update['pending'])) {
|
||||
$count = $count + count($update['pending']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,8 +401,8 @@ class DbUpdateController extends ControllerBase {
|
|||
// Report end result.
|
||||
$dblog_exists = $this->moduleHandler->moduleExists('dblog');
|
||||
if ($dblog_exists && $this->account->hasPermission('access site reports')) {
|
||||
$log_message = $this->t('All errors have been <a href="@url">logged</a>.', array(
|
||||
'@url' => Url::fromRoute('dblog.overview')->setOption('base_url', $base_url)->toString(TRUE)->getGeneratedUrl(),
|
||||
$log_message = $this->t('All errors have been <a href=":url">logged</a>.', array(
|
||||
':url' => Url::fromRoute('dblog.overview')->setOption('base_url', $base_url)->toString(TRUE)->getGeneratedUrl(),
|
||||
));
|
||||
}
|
||||
else {
|
||||
|
@ -381,7 +410,7 @@ class DbUpdateController extends ControllerBase {
|
|||
}
|
||||
|
||||
if (!empty($_SESSION['update_success'])) {
|
||||
$message = '<p>' . $this->t('Updates were attempted. If you see no failures below, you may proceed happily back to your <a href="@url">site</a>. Otherwise, you may need to update your database manually.', array('@url' => Url::fromRoute('<front>')->setOption('base_url', $base_url)->toString(TRUE)->getGeneratedUrl())) . ' ' . $log_message . '</p>';
|
||||
$message = '<p>' . $this->t('Updates were attempted. If you see no failures below, you may proceed happily back to your <a href=":url">site</a>. Otherwise, you may need to update your database manually.', array(':url' => Url::fromRoute('<front>')->setOption('base_url', $base_url)->toString(TRUE)->getGeneratedUrl())) . ' ' . $log_message . '</p>';
|
||||
}
|
||||
else {
|
||||
$last = reset($_SESSION['updates_remaining']);
|
||||
|
@ -415,7 +444,7 @@ class DbUpdateController extends ControllerBase {
|
|||
if ($module != '#abort') {
|
||||
$module_has_message = FALSE;
|
||||
$info_messages = array();
|
||||
foreach ($updates as $number => $queries) {
|
||||
foreach ($updates as $name => $queries) {
|
||||
$messages = array();
|
||||
foreach ($queries as $query) {
|
||||
// If there is no message for this update, don't show anything.
|
||||
|
@ -439,10 +468,16 @@ class DbUpdateController extends ControllerBase {
|
|||
|
||||
if ($messages) {
|
||||
$module_has_message = TRUE;
|
||||
if (is_numeric($name)) {
|
||||
$title = $this->t('Update #@count', ['@count' => $name]);
|
||||
}
|
||||
else {
|
||||
$title = $this->t('Update @name', ['@name' => trim($name, '_')]);
|
||||
}
|
||||
$info_messages[] = array(
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $messages,
|
||||
'#title' => $this->t('Update #@count', array('@count' => $number)),
|
||||
'#title' => $title,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -493,7 +528,7 @@ class DbUpdateController extends ControllerBase {
|
|||
$build['status_report'] = array(
|
||||
'#theme' => 'status_report',
|
||||
'#requirements' => $requirements,
|
||||
'#suffix' => $this->t('Check the messages and <a href="@url">try again</a>.', array('@url' => $try_again_url))
|
||||
'#suffix' => $this->t('Check the messages and <a href=":url">try again</a>.', array(':url' => $try_again_url))
|
||||
);
|
||||
|
||||
$build['#title'] = $this->t('Requirements problem');
|
||||
|
@ -575,6 +610,17 @@ class DbUpdateController extends ControllerBase {
|
|||
}
|
||||
}
|
||||
|
||||
$post_updates = $this->postUpdateRegistry->getPendingUpdateFunctions();
|
||||
|
||||
if ($post_updates) {
|
||||
// Now we rebuild all caches and after that execute the hook_post_update()
|
||||
// functions.
|
||||
$operations[] = ['drupal_flush_all_caches', []];
|
||||
foreach ($post_updates as $function) {
|
||||
$operations[] = ['update_invoke_post_update', [$function]];
|
||||
}
|
||||
}
|
||||
|
||||
$batch['operations'] = $operations;
|
||||
$batch += array(
|
||||
'title' => $this->t('Updating'),
|
||||
|
|
|
@ -118,7 +118,7 @@ class SystemController extends ControllerBase {
|
|||
public function overview($link_id) {
|
||||
// Check for status report errors.
|
||||
if ($this->systemManager->checkRequirements() && $this->currentUser()->hasPermission('administer site configuration')) {
|
||||
drupal_set_message($this->t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => $this->url('system.status'))), 'error');
|
||||
drupal_set_message($this->t('One or more problems were detected with your Drupal installation. Check the <a href=":status">status report</a> for more information.', array(':status' => $this->url('system.status'))), 'error');
|
||||
}
|
||||
// Load all menu links below it.
|
||||
$parameters = new MenuTreeParameters();
|
||||
|
@ -231,8 +231,8 @@ class SystemController extends ControllerBase {
|
|||
if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) {
|
||||
$theme->screenshot = array(
|
||||
'uri' => $themes[$theme_key]->info['screenshot'],
|
||||
'alt' => $this->t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])),
|
||||
'title' => $this->t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])),
|
||||
'alt' => $this->t('Screenshot for @theme theme', array('@theme' => $theme->info['name'])),
|
||||
'title' => $this->t('Screenshot for @theme theme', array('@theme' => $theme->info['name'])),
|
||||
'attributes' => array('class' => array('screenshot')),
|
||||
);
|
||||
break;
|
||||
|
@ -259,7 +259,7 @@ class SystemController extends ControllerBase {
|
|||
$theme->operations[] = array(
|
||||
'title' => $this->t('Settings'),
|
||||
'url' => Url::fromRoute('system.theme_settings_theme', ['theme' => $theme->getName()]),
|
||||
'attributes' => array('title' => $this->t('Settings for !theme theme', array('!theme' => $theme->info['name']))),
|
||||
'attributes' => array('title' => $this->t('Settings for @theme theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
}
|
||||
if (!empty($theme->status)) {
|
||||
|
@ -279,14 +279,14 @@ class SystemController extends ControllerBase {
|
|||
'title' => $this->t('Uninstall'),
|
||||
'url' => Url::fromRoute('system.theme_uninstall'),
|
||||
'query' => $query,
|
||||
'attributes' => array('title' => $this->t('Uninstall !theme theme', array('!theme' => $theme->info['name']))),
|
||||
'attributes' => array('title' => $this->t('Uninstall @theme theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
}
|
||||
$theme->operations[] = array(
|
||||
'title' => $this->t('Set as default'),
|
||||
'url' => Url::fromRoute('system.theme_set_default'),
|
||||
'query' => $query,
|
||||
'attributes' => array('title' => $this->t('Set !theme as default theme', array('!theme' => $theme->info['name']))),
|
||||
'attributes' => array('title' => $this->t('Set @theme as default theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
}
|
||||
$admin_theme_options[$theme->getName()] = $theme->info['name'];
|
||||
|
@ -296,13 +296,13 @@ class SystemController extends ControllerBase {
|
|||
'title' => $this->t('Install'),
|
||||
'url' => Url::fromRoute('system.theme_install'),
|
||||
'query' => $query,
|
||||
'attributes' => array('title' => $this->t('Install !theme theme', array('!theme' => $theme->info['name']))),
|
||||
'attributes' => array('title' => $this->t('Install @theme theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
$theme->operations[] = array(
|
||||
'title' => $this->t('Install and set as default'),
|
||||
'url' => Url::fromRoute('system.theme_set_default'),
|
||||
'query' => $query,
|
||||
'attributes' => array('title' => $this->t('Install !theme as default theme', array('!theme' => $theme->info['name']))),
|
||||
'attributes' => array('title' => $this->t('Install @theme as default theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ class SystemInfoController implements ContainerInjectionInterface {
|
|||
$output = ob_get_clean();
|
||||
}
|
||||
else {
|
||||
$output = t('The phpinfo() function has been disabled for security reasons. For more information, visit <a href="@phpinfo">Enabling and disabling phpinfo()</a> handbook page.', array('@phpinfo' => 'https://www.drupal.org/node/243993'));
|
||||
$output = t('The phpinfo() function has been disabled for security reasons. For more information, visit <a href=":phpinfo">Enabling and disabling phpinfo()</a> handbook page.', array(':phpinfo' => 'https://www.drupal.org/node/243993'));
|
||||
}
|
||||
return new Response($output);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ class DateFormatAccessControlHandler extends EntityAccessControlHandler {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
// There are no restrictions on viewing a date format.
|
||||
if ($operation == 'view') {
|
||||
return AccessResult::allowed();
|
||||
|
@ -33,11 +33,11 @@ class DateFormatAccessControlHandler extends EntityAccessControlHandler {
|
|||
return AccessResult::forbidden()->cacheUntilEntityChanges($entity);
|
||||
}
|
||||
else {
|
||||
return parent::checkAccess($entity, $operation, $langcode, $account)->cacheUntilEntityChanges($entity);
|
||||
return parent::checkAccess($entity, $operation, $account)->cacheUntilEntityChanges($entity);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::checkAccess($entity, $operation, $langcode, $account);
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Drupal\system;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
@ -24,7 +24,7 @@ class DateFormatListBuilder extends ConfigEntityListBuilder {
|
|||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
|
@ -35,10 +35,10 @@ class DateFormatListBuilder extends ConfigEntityListBuilder {
|
|||
* The entity type definition.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The entity storage class.
|
||||
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatter $date_formatter) {
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter) {
|
||||
parent::__construct($entity_type, $storage);
|
||||
|
||||
$this->dateFormatter = $date_formatter;
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\EventSubscriber\AutomaticCron.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\CronInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* A subscriber running cron when a request terminates.
|
||||
*/
|
||||
class AutomaticCron implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The cron service.
|
||||
*
|
||||
* @var \Drupal\Core\CronInterface
|
||||
*/
|
||||
protected $cron;
|
||||
|
||||
/**
|
||||
* The cron configuration.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The state key value store.
|
||||
*
|
||||
* Drupal\Core\State\StateInterface;
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Construct a new automatic 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.
|
||||
*/
|
||||
public function __construct(CronInterface $cron, ConfigFactoryInterface $config_factory, StateInterface $state) {
|
||||
$this->cron = $cron;
|
||||
$this->config = $config_factory->get('system.cron');
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the automated cron if enabled.
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the methods in this class that should be listeners.
|
||||
*
|
||||
* @return array
|
||||
* An array of event listener definitions.
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -60,8 +60,8 @@ class ConfigCacheTag implements EventSubscriberInterface {
|
|||
$this->cacheTagsInvalidator->invalidateTags(['route_match', 'rendered']);
|
||||
}
|
||||
|
||||
// Global theme settings.
|
||||
if ($event->getConfig()->getName() === 'system.theme.global') {
|
||||
// Theme configuration and global theme settings.
|
||||
if (in_array($event->getConfig()->getName(), ['system.theme', 'system.theme.global'], TRUE)) {
|
||||
$this->cacheTagsInvalidator->invalidateTags(['rendered']);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,11 @@ class FileDownloadController extends ControllerBase {
|
|||
}
|
||||
|
||||
if (count($headers)) {
|
||||
return new BinaryFileResponse($uri, 200, $headers);
|
||||
// \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
|
||||
// sets response as not cacheable if the Cache-Control header is not
|
||||
// already modified. We pass in FALSE for non-private schemes for the
|
||||
// $public parameter to make sure we don't change the headers.
|
||||
return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
|
||||
}
|
||||
|
||||
throw new AccessDeniedHttpException();
|
||||
|
|
|
@ -9,17 +9,18 @@ namespace Drupal\system\Form;
|
|||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\CronInterface;
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\Core\Form\ConfigFormBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
||||
/**
|
||||
* Configure cron settings for this site.
|
||||
*/
|
||||
class CronForm extends ConfigFormBase {
|
||||
class CronForm extends FormBase {
|
||||
|
||||
/**
|
||||
* Stores the state storage service.
|
||||
|
@ -38,10 +39,17 @@ class CronForm extends ConfigFormBase {
|
|||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
/**
|
||||
* The module handler service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Constructs a CronForm object.
|
||||
*
|
||||
|
@ -51,14 +59,16 @@ class CronForm extends ConfigFormBase {
|
|||
* The state key value store.
|
||||
* @param \Drupal\Core\CronInterface $cron
|
||||
* The cron service.
|
||||
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler service.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory, StateInterface $state, CronInterface $cron, DateFormatter $date_formatter) {
|
||||
parent::__construct($config_factory);
|
||||
public function __construct(ConfigFactoryInterface $config_factory, StateInterface $state, CronInterface $cron, DateFormatterInterface $date_formatter, ModuleHandlerInterface $module_handler) {
|
||||
$this->state = $state;
|
||||
$this->cron = $cron;
|
||||
$this->dateFormatter = $date_formatter;
|
||||
$this->moduleHandler = $module_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,7 +79,8 @@ class CronForm extends ConfigFormBase {
|
|||
$container->get('config.factory'),
|
||||
$container->get('state'),
|
||||
$container->get('cron'),
|
||||
$container->get('date.formatter')
|
||||
$container->get('date.formatter'),
|
||||
$container->get('module_handler')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -80,68 +91,40 @@ class CronForm extends ConfigFormBase {
|
|||
return 'system_cron_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEditableConfigNames() {
|
||||
return ['system.cron'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$config = $this->config('system.cron');
|
||||
|
||||
$form['description'] = array(
|
||||
'#markup' => '<p>' . t('Cron takes care of running periodic tasks like checking for updates and indexing content for search.') . '</p>',
|
||||
);
|
||||
$form['run'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Run cron'),
|
||||
'#submit' => array('::submitCron'),
|
||||
);
|
||||
$status = '<p>' . $this->t('Last run: %time ago.', array('%time' => $this->dateFormatter->formatTimeDiffSince($this->state->get('system.cron_last')))) . '</p>';
|
||||
$form['status'] = array(
|
||||
'#markup' => $status,
|
||||
);
|
||||
|
||||
$cron_url = $this->url('system.cron', array('key' => $this->state->get('system.cron_key')), array('absolute' => TRUE));
|
||||
$form['cron_url'] = array(
|
||||
'#markup' => '<p>' . t('To run cron from outside the site, go to <a href="!cron">!cron</a>', array('!cron' => $this->url('system.cron', array('key' => $this->state->get('system.cron_key')), array('absolute' => TRUE)))) . '</p>',
|
||||
'#markup' => '<p>' . t('To run cron from outside the site, go to <a href=":cron">@cron</a>', array(':cron' => $cron_url, '@cron' => $cron_url)) . '</p>',
|
||||
);
|
||||
|
||||
$form['cron'] = array(
|
||||
'#title' => t('Cron settings'),
|
||||
'#type' => 'details',
|
||||
'#open' => TRUE,
|
||||
);
|
||||
$options = array(3600, 10800, 21600, 43200, 86400, 604800);
|
||||
$form['cron']['cron_safe_threshold'] = array(
|
||||
'#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>.', array('@url' => 'https://www.drupal.org/cron')),
|
||||
'#default_value' => $config->get('threshold.autorun'),
|
||||
'#options' => array(0 => t('Never')) + array_map(array($this->dateFormatter, 'formatInterval'), array_combine($options, $options)),
|
||||
);
|
||||
if (!$this->moduleHandler->moduleExists('automated_cron')) {
|
||||
$form['cron'] = array(
|
||||
'#markup' => $this->t('Enable the <em>Automated Cron</em> module to allow cron execution at the end of a server response.'),
|
||||
);
|
||||
}
|
||||
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->config('system.cron')
|
||||
->set('threshold.autorun', $form_state->getValue('cron_safe_threshold'))
|
||||
->save();
|
||||
|
||||
parent::submitForm($form, $form_state);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs cron and reloads the page.
|
||||
*/
|
||||
public function submitCron(array &$form, FormStateInterface $form_state) {
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
// Run cron manually from Cron form.
|
||||
if ($this->cron->run()) {
|
||||
drupal_set_message(t('Cron run successfully.'));
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\system\Form;
|
||||
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Entity\EntityDeleteForm;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
|
@ -19,17 +19,17 @@ class DateFormatDeleteForm extends EntityDeleteForm {
|
|||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
/**
|
||||
* Constructs an DateFormatDeleteForm 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Drupal\system\Form;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -23,7 +23,7 @@ abstract class DateFormatFormBase extends EntityForm {
|
|||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
|
@ -37,12 +37,12 @@ abstract class DateFormatFormBase extends EntityForm {
|
|||
/**
|
||||
* Constructs a new date format form.
|
||||
*
|
||||
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date service.
|
||||
* @param \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $date_format_storage
|
||||
* The date format storage.
|
||||
*/
|
||||
public function __construct(DateFormatter $date_formatter, ConfigEntityStorageInterface $date_format_storage) {
|
||||
public function __construct(DateFormatterInterface $date_formatter, ConfigEntityStorageInterface $date_format_storage) {
|
||||
$date = new DrupalDateTime();
|
||||
|
||||
$this->dateFormatter = $date_formatter;
|
||||
|
@ -104,7 +104,7 @@ abstract class DateFormatFormBase extends EntityForm {
|
|||
'#type' => 'textfield',
|
||||
'#title' => t('Format string'),
|
||||
'#maxlength' => 100,
|
||||
'#description' => $this->t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php')),
|
||||
'#description' => $this->t('A user-defined date format. See the <a href=":url">PHP manual</a> for available options.', array(':url' => 'http://php.net/manual/function.date.php')),
|
||||
'#required' => TRUE,
|
||||
'#attributes' => [
|
||||
'data-drupal-date-formatter' => 'source',
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Drupal\system\Form;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\StreamWrapper\PrivateStream;
|
||||
use Drupal\Core\StreamWrapper\PublicStream;
|
||||
|
@ -25,7 +25,7 @@ class FileSystemForm extends ConfigFormBase {
|
|||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
|
@ -41,12 +41,12 @@ class FileSystemForm extends ConfigFormBase {
|
|||
*
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The factory for configuration objects.
|
||||
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
* @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager
|
||||
* The stream wrapper manager.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory, DateFormatter $date_formatter, StreamWrapperManagerInterface $stream_wrapper_manager) {
|
||||
public function __construct(ConfigFactoryInterface $config_factory, DateFormatterInterface $date_formatter, StreamWrapperManagerInterface $stream_wrapper_manager) {
|
||||
parent::__construct($config_factory);
|
||||
$this->dateFormatter = $date_formatter;
|
||||
$this->streamWrapperManager = $stream_wrapper_manager;
|
||||
|
@ -89,6 +89,13 @@ class FileSystemForm extends ConfigFormBase {
|
|||
'#description' => t('A local file system path where public files will be stored. This directory must exist and be writable by Drupal. This directory must be relative to the Drupal installation directory and be accessible over the web. This must be changed in settings.php'),
|
||||
);
|
||||
|
||||
$form['file_public_base_url'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Public file base URL'),
|
||||
'#markup' => PublicStream::baseUrl(),
|
||||
'#description' => t('The base URL that will be used for public file URLs. This can be changed in settings.php'),
|
||||
);
|
||||
|
||||
$form['file_private_path'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Private file system path'),
|
||||
|
|
|
@ -59,34 +59,6 @@ class ModulesListForm extends FormBase {
|
|||
*/
|
||||
protected $keyValueExpirable;
|
||||
|
||||
/**
|
||||
* The title resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Controller\TitleResolverInterface
|
||||
*/
|
||||
protected $titleResolver;
|
||||
|
||||
/**
|
||||
* The route provider.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteProviderInterface
|
||||
*/
|
||||
protected $routeProvider;
|
||||
|
||||
/**
|
||||
* The current route match.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteMatchInterface
|
||||
*/
|
||||
protected $routeMatch;
|
||||
|
||||
/**
|
||||
* The menu link manager.
|
||||
*
|
||||
* @var \Drupal\Core\Menu\MenuLinkManagerInterface
|
||||
*/
|
||||
protected $menuLinkManager;
|
||||
|
||||
/**
|
||||
* The module installer.
|
||||
*
|
||||
|
@ -111,10 +83,6 @@ class ModulesListForm extends FormBase {
|
|||
$container->get('keyvalue.expirable')->get('module_list'),
|
||||
$container->get('access_manager'),
|
||||
$container->get('current_user'),
|
||||
$container->get('current_route_match'),
|
||||
$container->get('title_resolver'),
|
||||
$container->get('router.route_provider'),
|
||||
$container->get('plugin.manager.menu.link'),
|
||||
$container->get('user.permissions')
|
||||
);
|
||||
}
|
||||
|
@ -132,27 +100,15 @@ class ModulesListForm extends FormBase {
|
|||
* Access manager.
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The current user.
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The current route match.
|
||||
* @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
|
||||
* The title resolver.
|
||||
* @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
|
||||
* The route provider.
|
||||
* @param \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager
|
||||
* The menu link manager.
|
||||
* @param \Drupal\user\PermissionHandlerInterface $permission_handler
|
||||
* The permission handler.
|
||||
*/
|
||||
public function __construct(ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable, AccessManagerInterface $access_manager, AccountInterface $current_user, RouteMatchInterface $route_match, TitleResolverInterface $title_resolver, RouteProviderInterface $route_provider, MenuLinkManagerInterface $menu_link_manager, PermissionHandlerInterface $permission_handler) {
|
||||
public function __construct(ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable, AccessManagerInterface $access_manager, AccountInterface $current_user, PermissionHandlerInterface $permission_handler) {
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->moduleInstaller = $module_installer;
|
||||
$this->keyValueExpirable = $key_value_expirable;
|
||||
$this->accessManager = $access_manager;
|
||||
$this->currentUser = $current_user;
|
||||
$this->routeMatch = $route_match;
|
||||
$this->titleResolver = $title_resolver;
|
||||
$this->routeProvider = $route_provider;
|
||||
$this->menuLinkManager = $menu_link_manager;
|
||||
$this->permissionHandler = $permission_handler;
|
||||
}
|
||||
|
||||
|
@ -214,11 +170,6 @@ class ModulesListForm extends FormBase {
|
|||
'#title' => $this->t($package),
|
||||
'#open' => TRUE,
|
||||
'#theme' => 'system_modules_details',
|
||||
'#header' => array(
|
||||
array('data' => $this->t('Installed'), 'class' => array('checkbox', 'visually-hidden')),
|
||||
array('data' => $this->t('Name'), 'class' => array('name', 'visually-hidden')),
|
||||
array('data' => $this->t('Description'), 'class' => array('description', 'visually-hidden', RESPONSIVE_PRIORITY_LOW)),
|
||||
),
|
||||
'#attributes' => array('class' => array('package-listing')),
|
||||
// Ensure that the "Core" package comes first.
|
||||
'#weight' => $package == 'Core' ? -10 : NULL,
|
||||
|
@ -270,7 +221,6 @@ class ModulesListForm extends FormBase {
|
|||
// Generate link for module's help page. Assume that if a hook_help()
|
||||
// implementation exists then the module provides an overview page, rather
|
||||
// than checking to see if the page exists, which is costly.
|
||||
$row['links']['help'] = array();
|
||||
if ($this->moduleHandler->moduleExists('help') && $module->status && in_array($module->getName(), $this->moduleHandler->getImplementations('help'))) {
|
||||
$row['links']['help'] = array(
|
||||
'#type' => 'link',
|
||||
|
@ -281,7 +231,6 @@ class ModulesListForm extends FormBase {
|
|||
}
|
||||
|
||||
// Generate link for module's permission, if the user has access to it.
|
||||
$row['links']['permissions'] = array();
|
||||
if ($module->status && $this->currentUser->hasPermission('administer permissions') && $this->permissionHandler->moduleProvidesPermissions($module->getName())) {
|
||||
$row['links']['permissions'] = array(
|
||||
'#type' => 'link',
|
||||
|
@ -292,36 +241,16 @@ class ModulesListForm extends FormBase {
|
|||
}
|
||||
|
||||
// Generate link for module's configuration page, if it has one.
|
||||
$row['links']['configure'] = array();
|
||||
if ($module->status && isset($module->info['configure'])) {
|
||||
$route_parameters = isset($module->info['configure_parameters']) ? $module->info['configure_parameters'] : array();
|
||||
if ($this->accessManager->checkNamedRoute($module->info['configure'], $route_parameters, $this->currentUser)) {
|
||||
|
||||
$links = $this->menuLinkManager->loadLinksByRoute($module->info['configure']);
|
||||
/** @var \Drupal\Core\Menu\MenuLinkInterface $link */
|
||||
$link = reset($links);
|
||||
// Most configure links have a corresponding menu link, though some just
|
||||
// have a route.
|
||||
if ($link) {
|
||||
$description = $link->getDescription();
|
||||
}
|
||||
else {
|
||||
$request = new Request();
|
||||
$request->attributes->set('_route_name', $module->info['configure']);
|
||||
$route_object = $this->routeProvider->getRouteByName($module->info['configure']);
|
||||
$request->attributes->set('_route', $route_object);
|
||||
$request->attributes->add($route_parameters);
|
||||
$description = $this->titleResolver->getTitle($request, $route_object);
|
||||
}
|
||||
|
||||
$row['links']['configure'] = array(
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Configure'),
|
||||
'#title' => $this->t('Configure <span class="visually-hidden">the @module module</span>', ['@module' => $module->info['name']]),
|
||||
'#url' => Url::fromRoute($module->info['configure'], $route_parameters),
|
||||
'#options' => array(
|
||||
'attributes' => array(
|
||||
'class' => array('module-link', 'module-link-configure'),
|
||||
'title' => $description,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -353,8 +282,8 @@ class ModulesListForm extends FormBase {
|
|||
// Check the core compatibility.
|
||||
if ($module->info['core'] != \Drupal::CORE_COMPATIBILITY) {
|
||||
$compatible = FALSE;
|
||||
$reasons[] = $this->t('This version is not compatible with Drupal !core_version and should be replaced.', array(
|
||||
'!core_version' => \Drupal::CORE_COMPATIBILITY,
|
||||
$reasons[] = $this->t('This version is not compatible with Drupal @core_version and should be replaced.', array(
|
||||
'@core_version' => \Drupal::CORE_COMPATIBILITY,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -362,9 +291,9 @@ class ModulesListForm extends FormBase {
|
|||
if (version_compare(phpversion(), $module->info['php']) < 0) {
|
||||
$compatible = FALSE;
|
||||
$required = $module->info['php'] . (substr_count($module->info['php'], '.') < 2 ? '.*' : '');
|
||||
$reasons[] = $this->t('This module requires PHP version @php_required and is incompatible with PHP version !php_version.', array(
|
||||
$reasons[] = $this->t('This module requires PHP version @php_required and is incompatible with PHP version @php_version.', array(
|
||||
'@php_required' => $required,
|
||||
'!php_version' => phpversion(),
|
||||
'@php_version' => phpversion(),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use Drupal\Core\Asset\AssetCollectionOptimizerInterface;
|
|||
use Drupal\Core\Form\ConfigFormBase;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Datetime\DateFormatter;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
|
@ -30,7 +30,7 @@ class PerformanceForm extends ConfigFormBase {
|
|||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatter
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
|
@ -54,14 +54,14 @@ class PerformanceForm extends ConfigFormBase {
|
|||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The factory for configuration objects.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $render_cache
|
||||
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
* @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface $css_collection_optimizer
|
||||
* The CSS asset collection optimizer service.
|
||||
* @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface $js_collection_optimizer
|
||||
* The JavaScript asset collection optimizer service.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory, CacheBackendInterface $render_cache, DateFormatter $date_formatter, AssetCollectionOptimizerInterface $css_collection_optimizer, AssetCollectionOptimizerInterface $js_collection_optimizer) {
|
||||
public function __construct(ConfigFactoryInterface $config_factory, CacheBackendInterface $render_cache, DateFormatterInterface $date_formatter, AssetCollectionOptimizerInterface $css_collection_optimizer, AssetCollectionOptimizerInterface $js_collection_optimizer) {
|
||||
parent::__construct($config_factory);
|
||||
|
||||
$this->renderCache = $render_cache;
|
||||
|
@ -141,7 +141,7 @@ class PerformanceForm extends ConfigFormBase {
|
|||
$disabled = !$is_writable;
|
||||
$disabled_message = '';
|
||||
if (!$is_writable) {
|
||||
$disabled_message = ' ' . t('<strong class="error">Set up the <a href="!file-system">public files directory</a> to make these optimizations available.</strong>', array('!file-system' => $this->url('system.file_system_settings')));
|
||||
$disabled_message = ' ' . t('<strong class="error">Set up the <a href=":file-system">public files directory</a> to make these optimizations available.</strong>', array(':file-system' => $this->url('system.file_system_settings')));
|
||||
}
|
||||
|
||||
$form['bandwidth_optimization'] = array(
|
||||
|
|
|
@ -70,7 +70,7 @@ class SiteMaintenanceModeForm extends ConfigFormBase {
|
|||
'#type' => 'checkbox',
|
||||
'#title' => t('Put site into maintenance mode'),
|
||||
'#default_value' => $this->state->get('system.maintenance_mode'),
|
||||
'#description' => t('Visitors will only see the maintenance mode message. Only users with the "Access site in maintenance mode" <a href="@permissions-url">permission</a> will be able to access the site. Authorized users can log in directly via the <a href="@user-login">user login</a> page.', array('@permissions-url' => $this->url('user.admin_permissions'), '@user-login' => $this->url('user.login'))),
|
||||
'#description' => t('Visitors will only see the maintenance mode message. Only users with the "Access site in maintenance mode" <a href=":permissions-url">permission</a> will be able to access the site. Authorized users can log in directly via the <a href=":user-login">user login</a> page.', array(':permissions-url' => $this->url('user.admin_permissions'), ':user-login' => $this->url('user.login'))),
|
||||
);
|
||||
$form['maintenance_mode_message'] = array(
|
||||
'#type' => 'textarea',
|
||||
|
|
|
@ -141,9 +141,6 @@ class ThemeSettingsForm extends ConfigFormBase {
|
|||
|
||||
// Toggle settings
|
||||
$toggles = array(
|
||||
'logo' => t('Logo'),
|
||||
'name' => t('Site name'),
|
||||
'slogan' => t('Site slogan'),
|
||||
'node_user_picture' => t('User pictures in posts'),
|
||||
'comment_user_picture' => t('User pictures in comments'),
|
||||
'comment_user_verification' => t('User verification status in comments'),
|
||||
|
|
|
@ -22,7 +22,7 @@ class MenuAccessControlHandler extends EntityAccessControlHandler {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
if ($operation === 'view') {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
|
@ -32,11 +32,11 @@ class MenuAccessControlHandler extends EntityAccessControlHandler {
|
|||
return AccessResult::forbidden()->cacheUntilEntityChanges($entity);
|
||||
}
|
||||
else {
|
||||
return parent::checkAccess($entity, $operation, $langcode, $account)->cacheUntilEntityChanges($entity);
|
||||
return parent::checkAccess($entity, $operation, $account)->cacheUntilEntityChanges($entity);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::checkAccess($entity, $operation, $langcode, $account);
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface {
|
|||
$exclude['/user'] = TRUE;
|
||||
// Because this breadcrumb builder is entirely path-based, vary by the
|
||||
// 'url.path' cache context.
|
||||
$breadcrumb->setCacheContexts(['url.path']);
|
||||
$breadcrumb->addCacheContexts(['url.path']);
|
||||
while (count($path_elements) > 1) {
|
||||
array_pop($path_elements);
|
||||
// Copy the path elements for up-casting.
|
||||
|
|
|
@ -89,9 +89,9 @@ class SystemBrandingBlock extends BlockBase implements ContainerFactoryPluginInt
|
|||
if ($url_system_theme_settings->access() && $url_system_theme_settings_theme->access()) {
|
||||
// Provide links to the Appearance Settings and Theme Settings pages
|
||||
// if the user has access to administer themes.
|
||||
$site_logo_description = $this->t('Defined on the <a href="@appearance">Appearance Settings</a> or <a href="@theme">Theme Settings</a> page.', array(
|
||||
'@appearance' => $url_system_theme_settings->toString(),
|
||||
'@theme' => $url_system_theme_settings_theme->toString(),
|
||||
$site_logo_description = $this->t('Defined on the <a href=":appearance">Appearance Settings</a> or <a href=":theme">Theme Settings</a> page.', array(
|
||||
':appearance' => $url_system_theme_settings->toString(),
|
||||
':theme' => $url_system_theme_settings_theme->toString(),
|
||||
));
|
||||
}
|
||||
else {
|
||||
|
@ -106,8 +106,8 @@ class SystemBrandingBlock extends BlockBase implements ContainerFactoryPluginInt
|
|||
|
||||
// Provide link to Site Information page if the user has access to
|
||||
// administer site configuration.
|
||||
$site_name_description = $this->t('Defined on the <a href="@information">Site Information</a> page.', array('@information' => $site_information_url));
|
||||
$site_slogan_description = $this->t('Defined on the <a href="@information">Site Information</a> page.', array('@information' => $site_information_url));
|
||||
$site_name_description = $this->t('Defined on the <a href=":information">Site Information</a> page.', array(':information' => $site_information_url));
|
||||
$site_slogan_description = $this->t('Defined on the <a href=":information">Site Information</a> page.', array(':information' => $site_information_url));
|
||||
}
|
||||
else {
|
||||
// Explain that the user does not have access to the Site Information
|
||||
|
@ -160,10 +160,9 @@ class SystemBrandingBlock extends BlockBase implements ContainerFactoryPluginInt
|
|||
$build = array();
|
||||
$site_config = $this->configFactory->get('system.site');
|
||||
|
||||
$logo = theme_get_setting('logo');
|
||||
$build['site_logo'] = array(
|
||||
'#theme' => 'image',
|
||||
'#uri' => $logo['url'],
|
||||
'#uri' => theme_get_setting('logo.url'),
|
||||
'#alt' => $this->t('Home'),
|
||||
'#access' => $this->configuration['use_site_logo'],
|
||||
);
|
||||
|
|
|
@ -74,16 +74,7 @@ class SystemBreadcrumbBlock extends BlockBase implements ContainerFactoryPluginI
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
$breadcrumb = $this->breadcrumbManager->build($this->routeMatch);
|
||||
if (!empty($breadcrumb)) {
|
||||
// $breadcrumb is expected to be an array of rendered breadcrumb links.
|
||||
$build = [
|
||||
'#theme' => 'breadcrumb',
|
||||
'#links' => $breadcrumb->getLinks(),
|
||||
];
|
||||
$breadcrumb->applyTo($build);
|
||||
return $build;
|
||||
}
|
||||
return $this->breadcrumbManager->build($this->routeMatch)->toRenderable();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,17 +43,4 @@ class SystemMainBlock extends BlockBase implements MainContentBlockPluginInterfa
|
|||
return $this->mainContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::buildConfigurationForm($form, $form_state);
|
||||
|
||||
$form['cache']['#disabled'] = TRUE;
|
||||
$form['cache']['#description'] = $this->t("This block's maximum age cannot be configured, because it depends on the contents.");
|
||||
$form['cache']['max_age']['#value'] = Cache::PERMANENT;
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,20 +40,6 @@ class SystemMessagesBlock extends BlockBase implements MessagesBlockPluginInterf
|
|||
return ['#type' => 'status_messages'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::buildConfigurationForm($form, $form_state);
|
||||
|
||||
// @see ::getCacheMaxAge()
|
||||
$form['cache']['#description'] = $this->t('This block is cacheable forever, it is not configurable.');
|
||||
$form['cache']['max_age']['#value'] = Cache::PERMANENT;
|
||||
$form['cache']['max_age']['#disabled'] = TRUE;
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -25,30 +25,7 @@ class SystemPoweredByBlock extends BlockBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return array('#markup' => '<span>' . $this->t('Powered by <a href="@poweredby">Drupal</a>', array('@poweredby' => 'https://www.drupal.org')) . '</span>');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::buildConfigurationForm($form, $form_state);
|
||||
|
||||
// @see ::getCacheMaxAge()
|
||||
$form['cache']['#disabled'] = TRUE;
|
||||
$form['cache']['max_age']['#value'] = Cache::PERMANENT;
|
||||
$form['cache']['#description'] = $this->t('This block is always cached forever, it is not configurable.');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheMaxAge() {
|
||||
// The 'Powered by Drupal' block is permanently cacheable, because its
|
||||
// contents can never change.
|
||||
return Cache::PERMANENT;
|
||||
return array('#markup' => '<span>' . $this->t('Powered by <a href=":poweredby">Drupal</a>', array(':poweredby' => 'https://www.drupal.org')) . '</span>');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ use Drupal\Core\Config\ConfigFactoryInterface;
|
|||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\ImageToolkit\ImageToolkitBase;
|
||||
use Drupal\Core\ImageToolkit\ImageToolkitOperationManagerInterface;
|
||||
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
|
||||
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
|
||||
|
||||
/**
|
||||
* Defines the GD2 toolkit for image manipulation within Drupal.
|
||||
|
@ -65,7 +65,7 @@ class GDToolkit extends ImageToolkitBase {
|
|||
protected $streamWrapperManager;
|
||||
|
||||
/**
|
||||
* Constructs a TestToolkit object.
|
||||
* Constructs a GDToolkit object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
|
@ -87,6 +87,17 @@ class GDToolkit extends ImageToolkitBase {
|
|||
$this->streamWrapperManager = $stream_wrapper_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructs a GDToolkit object.
|
||||
*
|
||||
* Frees memory associated with a GD image resource.
|
||||
*/
|
||||
public function __destruct() {
|
||||
if (is_resource($this->resource)) {
|
||||
imagedestroy($this->resource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -108,9 +119,13 @@ class GDToolkit extends ImageToolkitBase {
|
|||
* @param resource $resource
|
||||
* The GD image resource.
|
||||
*
|
||||
* @return $this
|
||||
* @return \Drupal\system\Plugin\ImageToolkit\GDToolkit
|
||||
* An instance of the current toolkit object.
|
||||
*/
|
||||
public function setResource($resource) {
|
||||
if (!is_resource($resource) || get_resource_type($resource) != 'gd') {
|
||||
throw new \InvalidArgumentException('Invalid resource argument');
|
||||
}
|
||||
$this->preLoadInfo = NULL;
|
||||
$this->resource = $resource;
|
||||
return $this;
|
||||
|
@ -123,7 +138,7 @@ class GDToolkit extends ImageToolkitBase {
|
|||
* The GD image resource, or NULL if not available.
|
||||
*/
|
||||
public function getResource() {
|
||||
if (!$this->resource) {
|
||||
if (!is_resource($this->resource)) {
|
||||
$this->load();
|
||||
}
|
||||
return $this->resource;
|
||||
|
@ -167,7 +182,7 @@ class GDToolkit extends ImageToolkitBase {
|
|||
}
|
||||
|
||||
$function = 'imagecreatefrom' . image_type_to_extension($this->getType(), FALSE);
|
||||
if (function_exists($function) && $resource = $function($this->getImage()->getSource())) {
|
||||
if (function_exists($function) && $resource = $function($this->getSource())) {
|
||||
$this->setResource($resource);
|
||||
if (imageistruecolor($resource)) {
|
||||
return TRUE;
|
||||
|
@ -181,6 +196,7 @@ class GDToolkit extends ImageToolkitBase {
|
|||
'height' => imagesy($resource),
|
||||
'extension' => image_type_to_extension($this->getType(), FALSE),
|
||||
'transparent_color' => $this->getTransparentColor(),
|
||||
'is_temp' => TRUE,
|
||||
);
|
||||
if ($this->apply('create_new', $data)) {
|
||||
imagecopy($this->getResource(), $resource, 0, 0, 0, 0, imagesx($resource), imagesy($resource));
|
||||
|
@ -242,7 +258,7 @@ class GDToolkit extends ImageToolkitBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseFile() {
|
||||
$data = @getimagesize($this->getImage()->getSource());
|
||||
$data = @getimagesize($this->getSource());
|
||||
if ($data && in_array($data[2], static::supportedTypes())) {
|
||||
$this->setType($data[2]);
|
||||
$this->preLoadInfo = $data;
|
||||
|
@ -362,7 +378,7 @@ class GDToolkit extends ImageToolkitBase {
|
|||
// Check for filter and rotate support.
|
||||
if (!function_exists('imagefilter') || !function_exists('imagerotate')) {
|
||||
$requirements['version']['severity'] = REQUIREMENT_WARNING;
|
||||
$requirements['version']['description'] = t('The GD Library for PHP is enabled, but was compiled without support for functions used by the rotate and desaturate effects. It was probably compiled using the official GD libraries from http://www.libgd.org instead of the GD library bundled with PHP. You should recompile PHP --with-gd using the bundled GD library. See <a href="@url">the PHP manual</a>.', array('@url' => 'http://www.php.net/manual/book.image.php'));
|
||||
$requirements['version']['description'] = t('The GD Library for PHP is enabled, but was compiled without support for functions used by the rotate and desaturate effects. It was probably compiled using the official GD libraries from http://www.libgd.org instead of the GD library bundled with PHP. You should recompile PHP --with-gd using the bundled GD library. See <a href=":url">the PHP manual</a>.', array(':url' => 'http://www.php.net/manual/book.image.php'));
|
||||
}
|
||||
|
||||
return $requirements;
|
||||
|
|
|
@ -56,7 +56,8 @@ class Convert extends GDImageToolkitOperationBase {
|
|||
'width' => $width,
|
||||
'height' => $height,
|
||||
'extension' => $arguments['extension'],
|
||||
'transparent_color' => $this->getToolkit()->getTransparentColor()
|
||||
'transparent_color' => $this->getToolkit()->getTransparentColor(),
|
||||
'is_temp' => TRUE,
|
||||
);
|
||||
if ($this->getToolkit()->apply('create_new', $data)) {
|
||||
if (imagecopyresampled($this->getToolkit()->getResource(), $original_resource, 0, 0, 0, 0, $width, $height, $width, $height)) {
|
||||
|
|
|
@ -43,6 +43,11 @@ class CreateNew extends GDImageToolkitOperationBase {
|
|||
'required' => FALSE,
|
||||
'default' => '#ffffff',
|
||||
),
|
||||
'is_temp' => array(
|
||||
'description' => 'If TRUE, this operation is being used to create a temporary image by another GD operation. After performing its function, the caller is responsible for destroying the original GD resource.',
|
||||
'required' => FALSE,
|
||||
'default' => FALSE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -82,6 +87,9 @@ class CreateNew extends GDImageToolkitOperationBase {
|
|||
// Get the image type.
|
||||
$type = $this->getToolkit()->extensionToImageType($arguments['extension']);
|
||||
|
||||
// Store the original GD resource.
|
||||
$original_res = $this->getToolkit()->getResource();
|
||||
|
||||
// Create the resource.
|
||||
if (!$res = imagecreatetruecolor($arguments['width'], $arguments['height'])) {
|
||||
return FALSE;
|
||||
|
@ -119,6 +127,12 @@ class CreateNew extends GDImageToolkitOperationBase {
|
|||
// Update the toolkit properties.
|
||||
$this->getToolkit()->setType($type);
|
||||
$this->getToolkit()->setResource($res);
|
||||
|
||||
// Destroy the original resource if it is not needed by other operations.
|
||||
if (!$arguments['is_temp'] && is_resource($original_res)) {
|
||||
imagedestroy($original_res);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,13 +86,20 @@ class Crop extends GDImageToolkitOperationBase {
|
|||
'width' => $arguments['width'],
|
||||
'height' => $arguments['height'],
|
||||
'extension' => image_type_to_extension($this->getToolkit()->getType(), FALSE),
|
||||
'transparent_color' => $this->getToolkit()->getTransparentColor()
|
||||
'transparent_color' => $this->getToolkit()->getTransparentColor(),
|
||||
'is_temp' => TRUE,
|
||||
);
|
||||
if ($this->getToolkit()->apply('create_new', $data)) {
|
||||
if (imagecopyresampled($this->getToolkit()->getResource(), $original_resource, 0, 0, $arguments['x'], $arguments['y'], $arguments['width'], $arguments['height'], $arguments['width'], $arguments['height'])) {
|
||||
imagedestroy($original_resource);
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
// In case of failure, destroy the temporary resource and restore
|
||||
// the original one.
|
||||
imagedestroy($this->getToolkit()->getResource());
|
||||
$this->getToolkit()->setResource($original_resource);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class Desaturate extends GDImageToolkitOperationBase {
|
|||
protected function execute(array $arguments) {
|
||||
// PHP installations using non-bundled GD do not have imagefilter.
|
||||
if (!function_exists('imagefilter')) {
|
||||
$this->logger->notice("The image '@file' could not be desaturated because the imagefilter() function is not available in this PHP installation.", array('@file' => $this->getToolkit()->getImage()->getSource()));
|
||||
$this->logger->notice("The image '@file' could not be desaturated because the imagefilter() function is not available in this PHP installation.", array('@file' => $this->getToolkit()->getSource()));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,13 +65,20 @@ class Resize extends GDImageToolkitOperationBase {
|
|||
'width' => $arguments['width'],
|
||||
'height' => $arguments['height'],
|
||||
'extension' => image_type_to_extension($this->getToolkit()->getType(), FALSE),
|
||||
'transparent_color' => $this->getToolkit()->getTransparentColor()
|
||||
'transparent_color' => $this->getToolkit()->getTransparentColor(),
|
||||
'is_temp' => TRUE,
|
||||
);
|
||||
if ($this->getToolkit()->apply('create_new', $data)) {
|
||||
if (imagecopyresampled($this->getToolkit()->getResource(), $original_resource, 0, 0, 0, 0, $arguments['width'], $arguments['height'], imagesx($original_resource), imagesy($original_resource))) {
|
||||
imagedestroy($original_resource);
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
// In case of failure, destroy the temporary resource and restore
|
||||
// the original one.
|
||||
imagedestroy($this->getToolkit()->getResource());
|
||||
$this->getToolkit()->setResource($original_resource);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -94,21 +94,29 @@ class Rotate extends GDImageToolkitOperationBase {
|
|||
protected function execute(array $arguments) {
|
||||
// PHP installations using non-bundled GD do not have imagerotate.
|
||||
if (!function_exists('imagerotate')) {
|
||||
$this->logger->notice('The image %file could not be rotated because the imagerotate() function is not available in this PHP installation.', array('%file' => $this->getToolkit()->getImage()->getSource()));
|
||||
$this->logger->notice('The image %file could not be rotated because the imagerotate() function is not available in this PHP installation.', array('%file' => $this->getToolkit()->getSource()));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$this->getToolkit()->setResource(imagerotate($this->getToolkit()->getResource(), 360 - $arguments['degrees'], $arguments['background_idx']));
|
||||
// Stores the original GD resource.
|
||||
$original_res = $this->getToolkit()->getResource();
|
||||
|
||||
// GIFs need to reassign the transparent color after performing the rotate,
|
||||
// but only do so, if the image already had transparency of its own, or the
|
||||
// rotate added a transparent background.
|
||||
if (!empty($arguments['gif_transparent_color'])) {
|
||||
$transparent_idx = imagecolorexactalpha($this->getToolkit()->getResource(), $arguments['gif_transparent_color']['red'], $arguments['gif_transparent_color']['green'], $arguments['gif_transparent_color']['blue'], $arguments['gif_transparent_color']['alpha']);
|
||||
imagecolortransparent($this->getToolkit()->getResource(), $transparent_idx);
|
||||
if ($new_res = imagerotate($this->getToolkit()->getResource(), 360 - $arguments['degrees'], $arguments['background_idx'])) {
|
||||
$this->getToolkit()->setResource($new_res);
|
||||
imagedestroy($original_res);
|
||||
|
||||
// GIFs need to reassign the transparent color after performing the
|
||||
// rotate, but only do so, if the image already had transparency of its
|
||||
// own, or the rotate added a transparent background.
|
||||
if (!empty($arguments['gif_transparent_color'])) {
|
||||
$transparent_idx = imagecolorexactalpha($this->getToolkit()->getResource(), $arguments['gif_transparent_color']['red'], $arguments['gif_transparent_color']['green'], $arguments['gif_transparent_color']['blue'], $arguments['gif_transparent_color']['alpha']);
|
||||
imagecolortransparent($this->getToolkit()->getResource(), $transparent_idx);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\system\Plugin\views\field;
|
||||
|
||||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\RevisionableInterface;
|
||||
|
@ -15,7 +16,6 @@ use Drupal\Core\Language\LanguageManagerInterface;
|
|||
use Drupal\Core\Routing\RedirectDestinationTrait;
|
||||
use Drupal\Core\TypedData\TranslatableInterface;
|
||||
use Drupal\views\Entity\Render\EntityTranslationRenderTrait;
|
||||
use Drupal\views\Plugin\CacheablePluginInterface;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\Plugin\views\field\FieldPluginBase;
|
||||
use Drupal\views\Plugin\views\field\UncacheableFieldHandlerTrait;
|
||||
|
@ -29,7 +29,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
*
|
||||
* @ViewsField("bulk_form")
|
||||
*/
|
||||
class BulkForm extends FieldPluginBase implements CacheablePluginInterface {
|
||||
class BulkForm extends FieldPluginBase implements CacheableDependencyInterface {
|
||||
|
||||
use RedirectDestinationTrait;
|
||||
use UncacheableFieldHandlerTrait;
|
||||
|
@ -114,10 +114,10 @@ class BulkForm extends FieldPluginBase implements CacheablePluginInterface {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCacheable() {
|
||||
public function getCacheMaxAge() {
|
||||
// @todo Consider making the bulk operation form cacheable. See
|
||||
// https://www.drupal.org/node/2503009.
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,6 +127,13 @@ class BulkForm extends FieldPluginBase implements CacheablePluginInterface {
|
|||
return $this->languageManager->isMultilingual() ? $this->getEntityTranslationRenderer()->getCacheContexts() : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTags() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -99,7 +99,7 @@ class ActionUnitTest extends KernelTestBase {
|
|||
'user',
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($expected, $action->calculateDependencies());
|
||||
$this->assertIdentical($expected, $action->calculateDependencies()->getDependencies());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ class AjaxFormCacheTest extends AjaxTestBase {
|
|||
$this->drupalLogin($this->rootUser);
|
||||
|
||||
$this->drupalPlaceBlock('search_form_block', ['weight' => -5]);
|
||||
$this->drupalPlaceBlock('ajax_forms_test_block', ['cache' => ['max_age' => 0]]);
|
||||
$this->drupalPlaceBlock('ajax_forms_test_block');
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->drupalPostAjaxForm(NULL, ['test1' => 'option1'], 'test1');
|
||||
|
@ -66,7 +66,7 @@ class AjaxFormCacheTest extends AjaxTestBase {
|
|||
$this->container->get('module_installer')->install(['block']);
|
||||
$this->drupalLogin($this->rootUser);
|
||||
|
||||
$this->drupalPlaceBlock('ajax_forms_test_block', ['cache' => ['max_age' => 0]]);
|
||||
$this->drupalPlaceBlock('ajax_forms_test_block');
|
||||
|
||||
$url = Url::fromRoute('entity.user.canonical', ['user' => $this->rootUser->id()], ['query' => ['foo' => 'bar']]);
|
||||
$this->drupalGet($url);
|
||||
|
|
|
@ -7,39 +7,289 @@
|
|||
|
||||
namespace Drupal\system\Tests\Asset;
|
||||
|
||||
use Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException;
|
||||
use Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the element info.
|
||||
* Tests the library discovery and library discovery parser.
|
||||
*
|
||||
* @group Render
|
||||
*/
|
||||
class LibraryDiscoveryIntegrationTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* The library discovery service.
|
||||
*
|
||||
* @var \Drupal\Core\Asset\LibraryDiscoveryInterface
|
||||
*/
|
||||
protected $libraryDiscovery;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->container->get('theme_handler')->install(['test_theme', 'classy']);
|
||||
$this->container->get('theme_installer')->install(['test_theme', 'classy']);
|
||||
$this->libraryDiscovery = $this->container->get('library.discovery');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the element info can be altered by themes.
|
||||
*/
|
||||
public function testElementInfoByTheme() {
|
||||
$this->activateTheme('test_theme');
|
||||
$this->assertTrue($this->libraryDiscovery->getLibraryByName('test_theme', 'kitten'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that libraries-override are applied to library definitions.
|
||||
*/
|
||||
public function testLibrariesOverride() {
|
||||
// Assert some classy libraries that will be overridden or removed.
|
||||
$this->activateTheme('classy');
|
||||
$this->assertAssetInLibrary('core/themes/classy/css/components/button.css', 'classy', 'base', 'css');
|
||||
$this->assertAssetInLibrary('core/themes/classy/css/components/collapse-processed.css', 'classy', 'base', 'css');
|
||||
$this->assertAssetInLibrary('core/themes/classy/css/components/container-inline.css', 'classy', 'base', 'css');
|
||||
$this->assertAssetInLibrary('core/themes/classy/css/components/details.css', 'classy', 'base', 'css');
|
||||
$this->assertAssetInLibrary('core/themes/classy/css/components/dialog.css', 'classy', 'dialog', 'css');
|
||||
|
||||
// Confirmatory assert on core library to be removed.
|
||||
$this->assertTrue($this->libraryDiscovery->getLibraryByName('core', 'drupal.progress'), 'Confirmatory test on "core/drupal.progress"');
|
||||
|
||||
// Activate test theme that defines libraries overrides.
|
||||
$this->activateTheme('test_theme');
|
||||
|
||||
// Assert that entire library was correctly overridden.
|
||||
$this->assertEqual($this->libraryDiscovery->getLibraryByName('core', 'drupal.collapse'), $this->libraryDiscovery->getLibraryByName('test_theme', 'collapse'), 'Entire library correctly overridden.');
|
||||
|
||||
// Assert that classy library assets were correctly overridden or removed.
|
||||
$this->assertNoAssetInLibrary('core/themes/classy/css/components/button.css', 'classy', 'base', 'css');
|
||||
$this->assertNoAssetInLibrary('core/themes/classy/css/components/collapse-processed.css', 'classy', 'base', 'css');
|
||||
$this->assertNoAssetInLibrary('core/themes/classy/css/components/container-inline.css', 'classy', 'base', 'css');
|
||||
$this->assertNoAssetInLibrary('core/themes/classy/css/components/details.css', 'classy', 'base', 'css');
|
||||
$this->assertNoAssetInLibrary('core/themes/classy/css/components/dialog.css', 'classy', 'dialog', 'css');
|
||||
|
||||
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme/css/my-button.css', 'classy', 'base', 'css');
|
||||
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme/css/my-collapse-processed.css', 'classy', 'base', 'css');
|
||||
$this->assertAssetInLibrary('themes/my_theme/css/my-container-inline.css', 'classy', 'base', 'css');
|
||||
$this->assertAssetInLibrary('themes/my_theme/css/my-details.css', 'classy', 'base', 'css');
|
||||
|
||||
// Assert that entire library was correctly removed.
|
||||
$this->assertFalse($this->libraryDiscovery->getLibraryByName('core', 'drupal.progress'), 'Entire library correctly removed.');
|
||||
|
||||
// Assert that overridden library asset still retains attributes.
|
||||
$library = $this->libraryDiscovery->getLibraryByName('core', 'jquery');
|
||||
foreach ($library['js'] as $definition) {
|
||||
if ($definition['data'] == 'core/modules/system/tests/themes/test_theme/js/collapse.js') {
|
||||
$this->assertTrue($definition['minified'] && $definition['weight'] == -20, 'Previous attributes retained');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests libraries-override on drupalSettings.
|
||||
*/
|
||||
public function testLibrariesOverrideDrupalSettings() {
|
||||
// Activate test theme that attempts to override drupalSettings.
|
||||
$this->activateTheme('test_theme_libraries_override_with_drupal_settings');
|
||||
|
||||
// Assert that drupalSettings cannot be overridden and throws an exception.
|
||||
try {
|
||||
$this->libraryDiscovery->getLibraryByName('core', 'drupal.ajax');
|
||||
$this->fail('Throw Exception when trying to override drupalSettings');
|
||||
}
|
||||
catch (InvalidLibrariesOverrideSpecificationException $e) {
|
||||
$expected_message = 'drupalSettings may not be overridden in libraries-override. Trying to override core/drupal.ajax/drupalSettings. Use hook_library_info_alter() instead.';
|
||||
$this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when trying to override drupalSettings');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests libraries-override on malformed assets.
|
||||
*/
|
||||
public function testLibrariesOverrideMalformedAsset() {
|
||||
// Activate test theme that overrides with a malformed asset.
|
||||
$this->activateTheme('test_theme_libraries_override_with_invalid_asset');
|
||||
|
||||
// Assert that improperly formed asset "specs" throw an exception.
|
||||
try {
|
||||
$this->libraryDiscovery->getLibraryByName('core', 'drupal.dialog');
|
||||
$this->fail('Throw Exception when specifying invalid override');
|
||||
}
|
||||
catch (InvalidLibrariesOverrideSpecificationException $e) {
|
||||
$expected_message = 'Library asset core/drupal.dialog/css is not correctly specified. It should be in the form "extension/library_name/sub_key/path/to/asset.js".';
|
||||
$this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when specifying invalid override');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests library assets with other ways for specifying paths.
|
||||
*/
|
||||
public function testLibrariesOverrideOtherAssetLibraryNames() {
|
||||
// Activate a test theme that defines libraries overrides on other types of
|
||||
// assets.
|
||||
$this->activateTheme('test_theme');
|
||||
|
||||
// Assert Drupal-relative paths.
|
||||
$this->assertAssetInLibrary('themes/my_theme/css/dropbutton.css', 'core', 'drupal.dropbutton', 'css');
|
||||
|
||||
// Assert stream wrapper paths.
|
||||
$this->assertAssetInLibrary('public://my_css/vertical-tabs.css', 'core', 'drupal.vertical-tabs', 'css');
|
||||
|
||||
// Assert a protocol-relative URI.
|
||||
$this->assertAssetInLibrary('//my-server/my_theme/css/jquery_ui.css', 'core', 'jquery.ui', 'css');
|
||||
|
||||
// Assert an absolute URI.
|
||||
$this->assertAssetInLibrary('http://example.com/my_theme/css/farbtastic.css', 'core', 'jquery.farbtastic', 'css');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that base theme libraries-override still apply in sub themes.
|
||||
*/
|
||||
public function testBaseThemeLibrariesOverrideInSubTheme() {
|
||||
// Activate a test theme that has subthemes.
|
||||
$this->activateTheme('test_subtheme');
|
||||
|
||||
// Assert that libraries-override specified in the base theme still applies
|
||||
// in the sub theme.
|
||||
$this->assertNoAssetInLibrary('core/misc/dialog/dialog.js', 'core', 'drupal.dialog', 'js');
|
||||
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_basetheme/css/farbtastic.css', 'core', 'jquery.farbtastic', 'css');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests libraries-extend.
|
||||
*/
|
||||
public function testLibrariesExtend() {
|
||||
// Activate classy themes and verify the libraries are not extended.
|
||||
$this->activateTheme('classy');
|
||||
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_1.css', 'classy', 'book-navigation', 'css');
|
||||
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/js/extend_1.js', 'classy', 'book-navigation', 'js');
|
||||
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_2.css', 'classy', 'book-navigation', 'css');
|
||||
|
||||
// Activate the theme that extends the book-navigation library in classy.
|
||||
$this->activateTheme('test_theme_libraries_extend');
|
||||
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_1.css', 'classy', 'book-navigation', 'css');
|
||||
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/js/extend_1.js', 'classy', 'book-navigation', 'js');
|
||||
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_2.css', 'classy', 'book-navigation', 'css');
|
||||
|
||||
// Activate a sub theme and confirm that it inherits the library assets
|
||||
// extended in the base theme as well as its own.
|
||||
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_basetheme/css/base-libraries-extend.css', 'classy', 'base', 'css');
|
||||
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_subtheme/css/sub-libraries-extend.css', 'classy', 'base', 'css');
|
||||
$this->activateTheme('test_subtheme');
|
||||
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_basetheme/css/base-libraries-extend.css', 'classy', 'base', 'css');
|
||||
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_subtheme/css/sub-libraries-extend.css', 'classy', 'base', 'css');
|
||||
|
||||
// Activate test theme that extends with a non-existent library. An
|
||||
// exception should be thrown.
|
||||
$this->activateTheme('test_theme_libraries_extend');
|
||||
try {
|
||||
$this->libraryDiscovery->getLibraryByName('core', 'drupal.dialog');
|
||||
$this->fail('Throw Exception when specifying non-existent libraries-extend.');
|
||||
}
|
||||
catch (InvalidLibrariesExtendSpecificationException $e) {
|
||||
$expected_message = 'The specified library "test_theme_libraries_extend/non_existent_library" does not exist.';
|
||||
$this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when specifying non-existent libraries-extend.');
|
||||
}
|
||||
|
||||
// Also, test non-string libraries-extend. An exception should be thrown.
|
||||
$this->container->get('theme_installer')->install(['test_theme']);
|
||||
try {
|
||||
$this->libraryDiscovery->getLibraryByName('test_theme', 'collapse');
|
||||
$this->fail('Throw Exception when specifying non-string libraries-extend.');
|
||||
}
|
||||
catch (InvalidLibrariesExtendSpecificationException $e) {
|
||||
$expected_message = 'The libraries-extend specification for each library must be a list of strings.';
|
||||
$this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when specifying non-string libraries-extend.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates a specified theme.
|
||||
*
|
||||
* Installs the theme if not already installed and makes it the active theme.
|
||||
*
|
||||
* @param string $theme_name
|
||||
* The name of the theme to be activated.
|
||||
*/
|
||||
protected function activateTheme($theme_name) {
|
||||
$this->container->get('theme_installer')->install([$theme_name]);
|
||||
|
||||
/** @var \Drupal\Core\Theme\ThemeInitializationInterface $theme_initializer */
|
||||
$theme_initializer = $this->container->get('theme.initialization');
|
||||
|
||||
/** @var \Drupal\Core\Theme\ThemeManagerInterface $theme_manager */
|
||||
$theme_manager = $this->container->get('theme.manager');
|
||||
|
||||
/** @var \Drupal\Core\Render\ElementInfoManagerInterface $element_info */
|
||||
$library_discovery = $this->container->get('library.discovery');
|
||||
$theme_manager->setActiveTheme($theme_initializer->getActiveThemeByName($theme_name));
|
||||
|
||||
$theme_manager->setActiveTheme($theme_initializer->getActiveThemeByName('test_theme'));
|
||||
$this->assertTrue($library_discovery->getLibraryByName('test_theme', 'kitten'));
|
||||
$this->libraryDiscovery->clearCachedDefinitions();
|
||||
|
||||
// Assert message.
|
||||
$this->pass(sprintf('Activated theme "%s"', $theme_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the specified asset is in the given library.
|
||||
*
|
||||
* @param string $asset
|
||||
* The asset file with the path for the file.
|
||||
* @param string $extension
|
||||
* The extension in which the $library is defined.
|
||||
* @param string $library_name
|
||||
* Name of the library.
|
||||
* @param mixed $sub_key
|
||||
* The library sub key where the given asset is defined.
|
||||
* @param string $message
|
||||
* (optional) A message to display with the assertion.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the specified asset is found in the library.
|
||||
*/
|
||||
protected function assertAssetInLibrary($asset, $extension, $library_name, $sub_key, $message = NULL) {
|
||||
if (!isset($message)) {
|
||||
$message = sprintf('Asset %s found in library "%s/%s"', $asset, $extension, $library_name);
|
||||
}
|
||||
$library = $this->libraryDiscovery->getLibraryByName($extension, $library_name);
|
||||
foreach ($library[$sub_key] as $definition) {
|
||||
if ($asset == $definition['data']) {
|
||||
return $this->pass($message);
|
||||
}
|
||||
}
|
||||
return $this->fail($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the specified asset is not in the given library.
|
||||
*
|
||||
* @param string $asset
|
||||
* The asset file with the path for the file.
|
||||
* @param string $extension
|
||||
* The extension in which the $library_name is defined.
|
||||
* @param string $library_name
|
||||
* Name of the library.
|
||||
* @param mixed $sub_key
|
||||
* The library sub key where the given asset is defined.
|
||||
* @param string $message
|
||||
* (optional) A message to display with the assertion.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the specified asset is not found in the library.
|
||||
*/
|
||||
protected function assertNoAssetInLibrary($asset, $extension, $library_name, $sub_key, $message = NULL) {
|
||||
if (!isset($message)) {
|
||||
$message = sprintf('Asset %s not found in library "%s/%s"', $asset, $extension, $library_name);
|
||||
}
|
||||
$library = $this->libraryDiscovery->getLibraryByName($extension, $library_name);
|
||||
foreach ($library[$sub_key] as $definition) {
|
||||
if ($asset == $definition['data']) {
|
||||
return $this->fail($message);
|
||||
}
|
||||
}
|
||||
return $this->pass($message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,12 +54,14 @@ class ProcessingTest extends WebTestBase {
|
|||
// Batch 0: no operation.
|
||||
$edit = array('batch' => 'batch_0');
|
||||
$this->drupalPostForm('batch-test', $edit, 'Submit');
|
||||
$this->assertNoEscaped('<', 'No escaped markup is present.');
|
||||
$this->assertBatchMessages($this->_resultMessages('batch_0'), 'Batch with no operation performed successfully.');
|
||||
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
|
||||
|
||||
// Batch 1: several simple operations.
|
||||
$edit = array('batch' => 'batch_1');
|
||||
$this->drupalPostForm('batch-test', $edit, 'Submit');
|
||||
$this->assertNoEscaped('<', 'No escaped markup is present.');
|
||||
$this->assertBatchMessages($this->_resultMessages('batch_1'), 'Batch with simple operations performed successfully.');
|
||||
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), 'Execution order was correct.');
|
||||
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
|
||||
|
@ -67,6 +69,7 @@ class ProcessingTest extends WebTestBase {
|
|||
// Batch 2: one multistep operation.
|
||||
$edit = array('batch' => 'batch_2');
|
||||
$this->drupalPostForm('batch-test', $edit, 'Submit');
|
||||
$this->assertNoEscaped('<', 'No escaped markup is present.');
|
||||
$this->assertBatchMessages($this->_resultMessages('batch_2'), 'Batch with multistep operation performed successfully.');
|
||||
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_2'), 'Execution order was correct.');
|
||||
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
|
||||
|
@ -74,6 +77,7 @@ class ProcessingTest extends WebTestBase {
|
|||
// Batch 3: simple + multistep combined.
|
||||
$edit = array('batch' => 'batch_3');
|
||||
$this->drupalPostForm('batch-test', $edit, 'Submit');
|
||||
$this->assertNoEscaped('<', 'No escaped markup is present.');
|
||||
$this->assertBatchMessages($this->_resultMessages('batch_3'), 'Batch with simple and multistep operations performed successfully.');
|
||||
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_3'), 'Execution order was correct.');
|
||||
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
|
||||
|
@ -81,6 +85,7 @@ class ProcessingTest extends WebTestBase {
|
|||
// Batch 4: nested batch.
|
||||
$edit = array('batch' => 'batch_4');
|
||||
$this->drupalPostForm('batch-test', $edit, 'Submit');
|
||||
$this->assertNoEscaped('<', 'No escaped markup is present.');
|
||||
$this->assertBatchMessages($this->_resultMessages('batch_4'), 'Nested batch performed successfully.');
|
||||
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_4'), 'Execution order was correct.');
|
||||
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
|
||||
|
@ -91,6 +96,7 @@ class ProcessingTest extends WebTestBase {
|
|||
*/
|
||||
function testBatchFormMultistep() {
|
||||
$this->drupalGet('batch-test/multistep');
|
||||
$this->assertNoEscaped('<', 'No escaped markup is present.');
|
||||
$this->assertText('step 1', 'Form is displayed in step 1.');
|
||||
|
||||
// First step triggers batch 1.
|
||||
|
@ -98,12 +104,14 @@ class ProcessingTest extends WebTestBase {
|
|||
$this->assertBatchMessages($this->_resultMessages('batch_1'), 'Batch for step 1 performed successfully.');
|
||||
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), 'Execution order was correct.');
|
||||
$this->assertText('step 2', 'Form is displayed in step 2.');
|
||||
$this->assertNoEscaped('<', 'No escaped markup is present.');
|
||||
|
||||
// Second step triggers batch 2.
|
||||
$this->drupalPostForm(NULL, array(), 'Submit');
|
||||
$this->assertBatchMessages($this->_resultMessages('batch_2'), 'Batch for step 2 performed successfully.');
|
||||
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_2'), 'Execution order was correct.');
|
||||
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
|
||||
$this->assertNoEscaped('<', 'No escaped markup is present.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -162,7 +162,7 @@ class SystemMenuBlockTest extends KernelTestBase {
|
|||
'theme' => 'stark',
|
||||
));
|
||||
|
||||
$dependencies = $block->calculateDependencies();
|
||||
$dependencies = $block->calculateDependencies()->getDependencies();
|
||||
$expected = array(
|
||||
'config' => array(
|
||||
'system.menu.' . $this->menu->id()
|
||||
|
|
|
@ -37,14 +37,14 @@ class DrupalSetMessageTest extends WebTestBase {
|
|||
$this->assertUniqueText('Non Duplicated message');
|
||||
$this->assertNoUniqueText('Duplicated message');
|
||||
|
||||
// Ensure SafeString objects are rendered as expected.
|
||||
$this->assertRaw('SafeString with <em>markup!</em>');
|
||||
$this->assertUniqueText('SafeString with markup!');
|
||||
$this->assertRaw('SafeString2 with <em>markup!</em>');
|
||||
// Ensure Markup objects are rendered as expected.
|
||||
$this->assertRaw('Markup with <em>markup!</em>');
|
||||
$this->assertUniqueText('Markup with markup!');
|
||||
$this->assertRaw('Markup2 with <em>markup!</em>');
|
||||
|
||||
// Ensure when the same message is of different types it is not duplicated.
|
||||
$this->assertUniqueText('Non duplicate SafeString / string.');
|
||||
$this->assertNoUniqueText('Duplicate SafeString / string.');
|
||||
$this->assertUniqueText('Non duplicate Markup / string.');
|
||||
$this->assertNoUniqueText('Duplicate Markup / string.');
|
||||
|
||||
// Ensure that strings that are not marked as safe are escaped.
|
||||
$this->assertEscaped('<em>This<span>markup will be</span> escaped</em>.');
|
||||
|
|
|
@ -17,8 +17,18 @@ use Drupal\Core\Cache\ApcuBackend;
|
|||
*/
|
||||
class ApcuBackendUnitTest extends GenericCacheBackendUnitTestBase {
|
||||
|
||||
protected function checkRequirements() {
|
||||
$requirements = parent::checkRequirements();
|
||||
/**
|
||||
* Get a list of failed requirements.
|
||||
*
|
||||
* This specifically bypasses checkRequirements because it fails tests. PHP 7
|
||||
* does not have APC and simpletest does not have a explicit "skip"
|
||||
* functionality so to emulate it we override all test methods and explicitly
|
||||
* pass when requirements are not met.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getRequirements() {
|
||||
$requirements = [];
|
||||
if (!extension_loaded('apc')) {
|
||||
$requirements[] = 'APC extension not found.';
|
||||
}
|
||||
|
@ -33,10 +43,35 @@ class ApcuBackendUnitTest extends GenericCacheBackendUnitTestBase {
|
|||
return $requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if requirements fail.
|
||||
*
|
||||
* If the requirements fail the test method should return immediately instead
|
||||
* of running any tests. Messages will be output to display why the test was
|
||||
* skipped.
|
||||
*/
|
||||
protected function requirementsFail() {
|
||||
$requirements = $this->getRequirements();
|
||||
if (!empty($requirements)) {
|
||||
foreach ($requirements as $message) {
|
||||
$this->pass($message);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createCacheBackend($bin) {
|
||||
return new ApcuBackend($bin, $this->databasePrefix, \Drupal::service('cache_tags.invalidator.checksum'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function tearDown() {
|
||||
foreach ($this->cachebackends as $bin => $cachebackend) {
|
||||
$this->cachebackends[$bin]->removeBin();
|
||||
|
@ -44,4 +79,114 @@ class ApcuBackendUnitTest extends GenericCacheBackendUnitTestBase {
|
|||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testSetGet() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testSetGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testDelete() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testValueTypeIsKept() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testValueTypeIsKept();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testGetMultiple() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testGetMultiple();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testSetMultiple() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testSetMultiple();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testDeleteMultiple() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testDeleteMultiple();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testDeleteAll() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testDeleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testInvalidate() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testInvalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testInvalidateTags() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testInvalidateTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testInvalidateAll() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testInvalidateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testRemoveBin() {
|
||||
if ($this->requirementsFail()) {
|
||||
return;
|
||||
}
|
||||
parent::testRemoveBin();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -218,13 +218,13 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
$this->assertEqual('value', $backend->get('TEST8')->data);
|
||||
$this->assertFalse($backend->get('test8'));
|
||||
|
||||
// Calling ::set() with invalid cache tags.
|
||||
// Calling ::set() with invalid cache tags. This should fail an assertion.
|
||||
try {
|
||||
$backend->set('exception_test', 'value', Cache::PERMANENT, ['node' => [3, 5, 7]]);
|
||||
$this->fail('::set() was called with invalid cache tags, no exception was thrown.');
|
||||
$backend->set('assertion_test', 'value', Cache::PERMANENT, ['node' => [3, 5, 7]]);
|
||||
$this->fail('::set() was called with invalid cache tags, runtime assertion did not fail.');
|
||||
}
|
||||
catch (\LogicException $e) {
|
||||
$this->pass('::set() was called with invalid cache tags, an exception was thrown.');
|
||||
catch (\AssertionError $e) {
|
||||
$this->pass('::set() was called with invalid cache tags, runtime assertion failed.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +412,8 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
|
||||
$this->assertEqual($cached['cid_5']->data, $items['cid_5']['data'], 'New cache item set correctly.');
|
||||
|
||||
// Calling ::setMultiple() with invalid cache tags.
|
||||
// Calling ::setMultiple() with invalid cache tags. This should fail an
|
||||
// assertion.
|
||||
try {
|
||||
$items = [
|
||||
'exception_test_1' => array('data' => 1, 'tags' => []),
|
||||
|
@ -420,10 +421,10 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
'exception_test_3' => array('data' => 3, 'tags' => ['node' => [3, 5, 7]]),
|
||||
];
|
||||
$backend->setMultiple($items);
|
||||
$this->fail('::setMultiple() was called with invalid cache tags, no exception was thrown.');
|
||||
$this->fail('::setMultiple() was called with invalid cache tags, runtime assertion did not fail.');
|
||||
}
|
||||
catch (\LogicException $e) {
|
||||
$this->pass('::setMultiple() was called with invalid cache tags, an exception was thrown.');
|
||||
catch (\AssertionError $e) {
|
||||
$this->pass('::setMultiple() was called with invalid cache tags, runtime assertion failed.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,9 +61,14 @@ class AddFeedTest extends WebTestBase {
|
|||
$build['#attached']['feed'][] = [$feed_info['url'], $feed_info['title']];
|
||||
}
|
||||
|
||||
drupal_process_attached($build);
|
||||
|
||||
$this->setRawContent(drupal_get_html_head());
|
||||
// Use the bare HTML page renderer to render our links.
|
||||
$renderer = $this->container->get('bare_html_page_renderer');
|
||||
$response = $renderer->renderBarePage(
|
||||
$build, '', $this->container->get('theme.manager')->getActiveTheme()->getName()
|
||||
);
|
||||
// Glean the content from the response object.
|
||||
$this->setRawContent($response->getContent());
|
||||
// Assert that the content contains the RSS links we specified.
|
||||
foreach ($urls as $description => $feed_info) {
|
||||
$this->assertPattern($this->urlToRSSLinkPattern($feed_info['url'], $feed_info['title']), format_string('Found correct feed header for %description', array('%description' => $description)));
|
||||
}
|
||||
|
|
|
@ -288,7 +288,7 @@ class AttachedAssetsTest extends KernelTestBase {
|
|||
$js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js);
|
||||
|
||||
$rendered_js = $this->renderer->renderPlain($js_render_array);
|
||||
$this->assertTrue(strpos($rendered_js, 'core/assets/vendor/backbone/backbone-min.js?v=1.2.1') > 0 && strpos($rendered_js, 'core/assets/vendor/domready/ready.min.js?v=1.0.8') > 0 , 'JavaScript version identifiers correctly appended to URLs');
|
||||
$this->assertTrue(strpos($rendered_js, 'core/assets/vendor/backbone/backbone-min.js?v=1.2.3') > 0 && strpos($rendered_js, 'core/assets/vendor/domready/ready.min.js?v=1.0.8') > 0 , 'JavaScript version identifiers correctly appended to URLs');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -117,5 +117,10 @@ class FormatDateTest extends WebTestBase {
|
|||
$this->assertIdentical(format_date($timestamp, 'html_week'), '2007-W12', 'Test html_week date format.');
|
||||
$this->assertIdentical(format_date($timestamp, 'html_month'), '2007-03', 'Test html_month date format.');
|
||||
$this->assertIdentical(format_date($timestamp, 'html_year'), '2007', 'Test html_year date format.');
|
||||
|
||||
// HTML is not escaped by the date formatter, it must be escaped later.
|
||||
$formatter = \Drupal::service('date.formatter');
|
||||
$this->assertIdentical($formatter->format($timestamp, 'custom', '\<\s\c\r\i\p\t\>\a\l\e\r\t\(\'Y\'\)\;\<\/\s\c\r\i\p\t\>'), "<script>alert('2007');</script>", 'Script tags not removed from dates.');
|
||||
$this->assertIdentical($formatter->format($timestamp, 'custom', '\<\e\m\>Y\<\/\e\m\>'), '<em>2007</em>', 'Em tags are not removed from dates.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,17 +53,18 @@ class RenderTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests drupal_process_attached().
|
||||
* Tests that we get an exception when we try to attach an illegal type.
|
||||
*/
|
||||
public function testDrupalProcessAttached() {
|
||||
public function testProcessAttached() {
|
||||
// Specify invalid attachments in a render array.
|
||||
$build['#attached']['library'][] = 'core/drupal.states';
|
||||
$build['#attached']['drupal_process_states'][] = [];
|
||||
$renderer = $this->container->get('bare_html_page_renderer');
|
||||
try {
|
||||
drupal_process_attached($build);
|
||||
$renderer->renderBarePage($build, '', $this->container->get('theme.manager')->getActiveTheme()->getName());
|
||||
$this->fail("Invalid #attachment 'drupal_process_states' allowed");
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
catch (\LogicException $e) {
|
||||
$this->pass("Invalid #attachment 'drupal_process_states' not allowed");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ class RenderWebTest extends WebTestBase {
|
|||
),
|
||||
);
|
||||
$this->assertRenderedElement($element, '//a[@href=:href and contains(., :title)]', array(
|
||||
':href' => \Drupal::urlGenerator()->generateFromPath('common-test/destination', ['absolute' => TRUE]),
|
||||
':href' => URL::fromRoute('common_test.destination')->setAbsolute()->toString(),
|
||||
':title' => $element['#title'],
|
||||
));
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@ use Drupal\simpletest\WebTestBase;
|
|||
/**
|
||||
* Confirm that \Drupal\Core\Url,
|
||||
* \Drupal\Component\Utility\UrlHelper::filterQueryParameters(),
|
||||
* \Drupal\Component\Utility\UrlHelper::buildQuery(), and _l() work correctly
|
||||
* with various input.
|
||||
* \Drupal\Component\Utility\UrlHelper::buildQuery(), and
|
||||
* \Drupal\Core\Utility\LinkGeneratorInterface::generate()
|
||||
* work correctly with various input.
|
||||
*
|
||||
* @group Common
|
||||
*/
|
||||
|
@ -36,7 +37,7 @@ class UrlTest extends WebTestBase {
|
|||
$encoded_path = "3CSCRIPT%3Ealert%28%27XSS%27%29%3C/SCRIPT%3E";
|
||||
|
||||
$link = \Drupal::l($text, Url::fromUserInput('/' . $path));
|
||||
$this->assertTrue(strpos($link, $encoded_path) !== FALSE && strpos($link, $path) === FALSE, format_string('XSS attack @path was filtered by _l().', array('@path' => $path)));
|
||||
$this->assertTrue(strpos($link, $encoded_path) !== FALSE && strpos($link, $path) === FALSE, format_string('XSS attack @path was filtered by \Drupal\Core\Utility\LinkGeneratorInterface::generate().', array('@path' => $path)));
|
||||
|
||||
// Test \Drupal\Core\Url.
|
||||
$link = Url::fromUri('base:' . $path)->toString();
|
||||
|
@ -102,7 +103,8 @@ class UrlTest extends WebTestBase {
|
|||
$rendered = $renderer->renderRoot($hreflang_override_link);
|
||||
$this->assertTrue($this->hasAttribute('hreflang', $rendered, 'foo'), format_string('hreflang attribute with value @hreflang is present on a rendered link when @hreflang is provided in the render array.', array('@hreflang' => 'foo')));
|
||||
|
||||
// Test the active class in links produced by _l() and #type 'link'.
|
||||
// Test the active class in links produced by
|
||||
// \Drupal\Core\Utility\LinkGeneratorInterface::generate() and #type 'link'.
|
||||
$options_no_query = array();
|
||||
$options_query = array(
|
||||
'query' => array(
|
||||
|
@ -122,23 +124,24 @@ class UrlTest extends WebTestBase {
|
|||
|
||||
$this->drupalGet($path, $options_no_query);
|
||||
$links = $this->xpath('//a[@href = :href and contains(@class, :class)]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_no_query)->toString(), ':class' => 'is-active'));
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page is marked active.');
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page is marked active.');
|
||||
|
||||
$links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_query)->toString(), ':class' => 'is-active'));
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page with a query string when the current page has no query string is not marked active.');
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string when the current page has no query string is not marked active.');
|
||||
|
||||
$this->drupalGet($path, $options_query);
|
||||
$links = $this->xpath('//a[@href = :href and contains(@class, :class)]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_query)->toString(), ':class' => 'is-active'));
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page with a query string that matches the current query string is marked active.');
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string that matches the current query string is marked active.');
|
||||
|
||||
$links = $this->xpath('//a[@href = :href and contains(@class, :class)]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_query_reverse)->toString(), ':class' => 'is-active'));
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page with a query string that has matching parameters to the current query string but in a different order is marked active.');
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string that has matching parameters to the current query string but in a different order is marked active.');
|
||||
|
||||
$links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_no_query)->toString(), ':class' => 'is-active'));
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page without a query string when the current page has a query string is not marked active.');
|
||||
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page without a query string when the current page has a query string is not marked active.');
|
||||
|
||||
// Test adding a custom class in links produced by _l() and #type 'link'.
|
||||
// Test _l().
|
||||
// Test adding a custom class in links produced by
|
||||
// \Drupal\Core\Utility\LinkGeneratorInterface::generate() and #type 'link'.
|
||||
// Test the link generator.
|
||||
$class_l = $this->randomMachineName();
|
||||
$link_l = \Drupal::l($this->randomMachineName(), new Url('<current>', [], ['attributes' => ['class' => [$class_l]]]));
|
||||
$this->assertTrue($this->hasAttribute('class', $link_l, $class_l), format_string('Custom class @class is present on link when requested by l()', array('@class' => $class_l)));
|
||||
|
@ -166,10 +169,10 @@ class UrlTest extends WebTestBase {
|
|||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = $this->container->get('renderer');
|
||||
|
||||
// Build a link with _l() for reference.
|
||||
// Build a link with the link generator for reference.
|
||||
$l = \Drupal::l('foo', Url::fromUri('https://www.drupal.org'));
|
||||
|
||||
// Test a renderable array passed to _l().
|
||||
// Test a renderable array passed to the link generator.
|
||||
$renderer->executeInRenderContext(new RenderContext(), function() use ($renderer, $l) {
|
||||
$renderable_text = array('#markup' => 'foo');
|
||||
$l_renderable_text = \Drupal::l($renderable_text, Url::fromUri('https://www.drupal.org'));
|
||||
|
|
|
@ -40,8 +40,6 @@ class XssUnitTest extends KernelTestBase {
|
|||
$this->assertEqual($text, 'Escaped text: <script>', 't replaces and escapes string.');
|
||||
$text = t('Placeholder text: %value', array('%value' => '<script>'));
|
||||
$this->assertEqual($text, 'Placeholder text: <em class="placeholder"><script></em>', 't replaces, escapes and themes string.');
|
||||
$text = t('Verbatim text: !value', array('!value' => '<script>'));
|
||||
$this->assertEqual($text, 'Verbatim text: <script>', 't replaces verbatim string as-is.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\system\Tests\Database;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Database\DatabaseExceptionWrapper;
|
||||
|
||||
/**
|
||||
* Tests of the core database system.
|
||||
|
@ -122,22 +123,41 @@ class ConnectionTest extends DatabaseTestBase {
|
|||
* Ensure that you cannot execute multiple statements on phpversion() > 5.5.21 or > 5.6.5.
|
||||
*/
|
||||
public function testMultipleStatementsForNewPhp() {
|
||||
// This just tests mysql, as other PDO integrations don't allow to disable
|
||||
// This just tests mysql, as other PDO integrations don't allow disabling
|
||||
// multiple statements.
|
||||
if (Database::getConnection()->databaseType() !== 'mysql' || !defined('\PDO::MYSQL_ATTR_MULTI_STATEMENTS')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$db = Database::getConnection('default', 'default');
|
||||
// Disable the protection at the PHP level.
|
||||
try {
|
||||
$db->query('SELECT * FROM {test}; SELECT * FROM {test_people}')->execute();
|
||||
$this->fail('NO PDO exception thrown for multiple statements.');
|
||||
$db->query('SELECT * FROM {test}; SELECT * FROM {test_people}',
|
||||
[],
|
||||
[ 'allow_delimiter_in_query' => TRUE ]
|
||||
);
|
||||
$this->fail('No PDO exception thrown for multiple statements.');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
catch (DatabaseExceptionWrapper $e) {
|
||||
$this->pass('PDO exception thrown for multiple statements.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that you cannot execute multiple statements.
|
||||
*/
|
||||
public function testMultipleStatements() {
|
||||
|
||||
$db = Database::getConnection('default', 'default');
|
||||
try {
|
||||
$db->query('SELECT * FROM {test}; SELECT * FROM {test_people}');
|
||||
$this->fail('No exception thrown for multiple statements.');
|
||||
}
|
||||
catch (\InvalidArgumentException $e) {
|
||||
$this->pass('Exception thrown for multiple statements.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the escapeTable(), escapeField() and escapeAlias() methods with all possible reserved words in PostgreSQL.
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,7 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
'test_null',
|
||||
'test_serialized',
|
||||
'test_special_columns',
|
||||
'TEST_UPPERCASE',
|
||||
));
|
||||
self::addSampleData();
|
||||
}
|
||||
|
|
|
@ -66,6 +66,74 @@ class QueryTest extends DatabaseTestBase {
|
|||
$this->assertFalse($result, 'SQL injection attempt did not result in a row being inserted in the database table.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SQL injection via condition operator.
|
||||
*/
|
||||
public function testConditionOperatorArgumentsSQLInjection() {
|
||||
$injection = "IS NOT NULL) ;INSERT INTO {test} (name) VALUES ('test12345678'); -- ";
|
||||
|
||||
// Convert errors to exceptions for testing purposes below.
|
||||
set_error_handler(function ($severity, $message, $filename, $lineno) {
|
||||
throw new \ErrorException($message, 0, $severity, $filename, $lineno);
|
||||
});
|
||||
try {
|
||||
$result = db_select('test', 't')
|
||||
->fields('t')
|
||||
->condition('name', 1, $injection)
|
||||
->execute();
|
||||
$this->fail('Should not be able to attempt SQL injection via condition operator.');
|
||||
}
|
||||
catch (\ErrorException $e) {
|
||||
$this->pass('SQL injection attempt via condition arguments should result in a database exception.');
|
||||
}
|
||||
|
||||
// Test that the insert query that was used in the SQL injection attempt did
|
||||
// not result in a row being inserted in the database.
|
||||
$result = db_select('test')
|
||||
->condition('name', 'test12345678')
|
||||
->countQuery()
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertFalse($result, 'SQL injection attempt did not result in a row being inserted in the database table.');
|
||||
|
||||
// Attempt SQLi via union query with no unsafe characters.
|
||||
$this->enableModules(['user']);
|
||||
$this->installEntitySchema('user');
|
||||
db_insert('test')
|
||||
->fields(['name' => '123456'])
|
||||
->execute();
|
||||
$injection = "= 1 UNION ALL SELECT password FROM user WHERE uid =";
|
||||
|
||||
try {
|
||||
$result = db_select('test', 't')
|
||||
->fields('t', array('name', 'name'))
|
||||
->condition('name', 1, $injection)
|
||||
->execute();
|
||||
$this->fail('Should not be able to attempt SQL injection via operator.');
|
||||
}
|
||||
catch (\ErrorException $e) {
|
||||
$this->pass('SQL injection attempt via condition arguments should result in a database exception.');
|
||||
}
|
||||
|
||||
// Attempt SQLi via union query - uppercase tablename.
|
||||
db_insert('TEST_UPPERCASE')
|
||||
->fields(['name' => 'secrets'])
|
||||
->execute();
|
||||
$injection = "IS NOT NULL) UNION ALL SELECT name FROM {TEST_UPPERCASE} -- ";
|
||||
|
||||
try {
|
||||
$result = db_select('test', 't')
|
||||
->fields('t', array('name'))
|
||||
->condition('name', 1, $injection)
|
||||
->execute();
|
||||
$this->fail('Should not be able to attempt SQL injection via operator.');
|
||||
}
|
||||
catch (\ErrorException $e) {
|
||||
$this->pass('SQL injection attempt via condition arguments should result in a database exception.');
|
||||
}
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests numeric query parameter expansion in expressions.
|
||||
*
|
||||
|
|
|
@ -640,7 +640,7 @@ class SchemaTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests changing columns between numeric types.
|
||||
* Tests changing columns between types.
|
||||
*/
|
||||
function testSchemaChangeField() {
|
||||
$field_specs = array(
|
||||
|
@ -661,6 +661,27 @@ class SchemaTest extends KernelTestBase {
|
|||
$this->assertFieldChange($old_spec, $new_spec);
|
||||
}
|
||||
}
|
||||
|
||||
$field_specs = array(
|
||||
array('type' => 'varchar_ascii', 'length' => '255'),
|
||||
array('type' => 'varchar', 'length' => '255'),
|
||||
array('type' => 'text'),
|
||||
array('type' => 'blob', 'size' => 'big'),
|
||||
);
|
||||
|
||||
foreach ($field_specs as $i => $old_spec) {
|
||||
foreach ($field_specs as $j => $new_spec) {
|
||||
if ($i === $j) {
|
||||
// Do not change a field into itself.
|
||||
continue;
|
||||
}
|
||||
// Note if the serialized data contained an object this would fail on
|
||||
// Postgres.
|
||||
// @see https://www.drupal.org/node/1031122
|
||||
$this->assertFieldChange($old_spec, $new_spec, serialize(['string' => "This \n has \\\\ some backslash \"*string action.\\n"]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -671,7 +692,7 @@ class SchemaTest extends KernelTestBase {
|
|||
* @param $new_spec
|
||||
* The ending field specification.
|
||||
*/
|
||||
protected function assertFieldChange($old_spec, $new_spec) {
|
||||
protected function assertFieldChange($old_spec, $new_spec, $test_data = NULL) {
|
||||
$table_name = 'test_table_' . ($this->counter++);
|
||||
$table_spec = array(
|
||||
'fields' => array(
|
||||
|
@ -689,9 +710,24 @@ class SchemaTest extends KernelTestBase {
|
|||
// Remove inserted rows.
|
||||
db_truncate($table_name)->execute();
|
||||
|
||||
if ($test_data) {
|
||||
$id = db_insert($table_name)
|
||||
->fields(['test_field'], [$test_data])
|
||||
->execute();
|
||||
}
|
||||
|
||||
// Change the field.
|
||||
db_change_field($table_name, 'test_field', 'test_field', $new_spec);
|
||||
|
||||
if ($test_data) {
|
||||
$field_value = db_select($table_name)
|
||||
->fields($table_name, ['test_field'])
|
||||
->condition('serial_column', $id)
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertIdentical($field_value, $test_data);
|
||||
}
|
||||
|
||||
// Check the field was changed.
|
||||
$this->assertFieldCharacteristics($table_name, 'test_field', $new_spec);
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class SelectTest extends DatabaseTestBase {
|
|||
$records = $result->fetchAll();
|
||||
|
||||
$query = (string) $query;
|
||||
$expected = "/* Testing query comments * / SELECT nid FROM {node}; -- */ SELECT test.name AS name, test.age AS age\nFROM \n{test} test";
|
||||
$expected = "/* Testing query comments * / SELECT nid FROM {node}. -- */ SELECT test.name AS name, test.age AS age\nFROM \n{test} test";
|
||||
|
||||
$this->assertEqual(count($records), 4, 'Returned the correct number of rows.');
|
||||
$this->assertNotIdentical(FALSE, strpos($query, $expected), 'The flattened query contains the sanitised comment string.');
|
||||
|
@ -81,21 +81,21 @@ class SelectTest extends DatabaseTestBase {
|
|||
],
|
||||
// Try and close the comment early.
|
||||
[
|
||||
'/* Exploit * / DROP TABLE node; -- */ ',
|
||||
'/* Exploit * / DROP TABLE node. -- */ ',
|
||||
['Exploit */ DROP TABLE node; --'],
|
||||
],
|
||||
// Variations on comment closing.
|
||||
[
|
||||
'/* Exploit * / * / DROP TABLE node; -- */ ',
|
||||
'/* Exploit * / * / DROP TABLE node. -- */ ',
|
||||
['Exploit */*/ DROP TABLE node; --'],
|
||||
],
|
||||
[
|
||||
'/* Exploit * * // DROP TABLE node; -- */ ',
|
||||
'/* Exploit * * // DROP TABLE node. -- */ ',
|
||||
['Exploit **// DROP TABLE node; --'],
|
||||
],
|
||||
// Try closing the comment in the second string which is appended.
|
||||
[
|
||||
'/* Exploit * / DROP TABLE node; --; Another try * / DROP TABLE node; -- */ ',
|
||||
'/* Exploit * / DROP TABLE node. --. Another try * / DROP TABLE node. -- */ ',
|
||||
['Exploit */ DROP TABLE node; --', 'Another try */ DROP TABLE node; --'],
|
||||
],
|
||||
];
|
||||
|
|
|
@ -184,7 +184,7 @@ class PathElementFormTest extends KernelTestBase implements FormInterface {
|
|||
$errors = $form_state->getErrors();
|
||||
// Should be missing 'required_validate' field.
|
||||
$this->assertEqual(count($errors), 1);
|
||||
$this->assertEqual($errors, array('required_validate' => t('!name field is required.', array('!name' => 'required_validate'))));
|
||||
$this->assertEqual($errors, array('required_validate' => t('@name field is required.', array('@name' => 'required_validate'))));
|
||||
|
||||
// Test invalid parameters.
|
||||
$form_state = (new FormState())
|
||||
|
|
|
@ -31,7 +31,7 @@ class ConfigEntityImportTest extends WebTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
|
||||
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,7 +58,7 @@ class ConfigEntityImportTest extends WebTestBase {
|
|||
|
||||
$this->checkSinglePluginConfigSync($entity, 'configuration', 'message', '');
|
||||
|
||||
// Read the existing data, and prepare an altered version in staging.
|
||||
// Read the existing data, and prepare an altered version in sync.
|
||||
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
|
||||
$custom_data['configuration']['message'] = 'Granny Smith';
|
||||
$this->assertConfigUpdateImport($name, $original_data, $custom_data);
|
||||
|
@ -78,7 +78,7 @@ class ConfigEntityImportTest extends WebTestBase {
|
|||
|
||||
$this->checkSinglePluginConfigSync($block, 'settings', 'label', 'Red Delicious');
|
||||
|
||||
// Read the existing data, and prepare an altered version in staging.
|
||||
// Read the existing data, and prepare an altered version in sync.
|
||||
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
|
||||
$custom_data['settings']['label'] = 'Granny Smith';
|
||||
$this->assertConfigUpdateImport($name, $original_data, $custom_data);
|
||||
|
@ -110,7 +110,7 @@ class ConfigEntityImportTest extends WebTestBase {
|
|||
$this->assertIdentical($filters, $entity->get('filters'));
|
||||
$this->assertIdentical($filters, $plugin_collection->getConfiguration());
|
||||
|
||||
// Read the existing data, and prepare an altered version in staging.
|
||||
// Read the existing data, and prepare an altered version in sync.
|
||||
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
|
||||
$custom_data['filters']['filter_url']['settings']['filter_url_length'] = 100;
|
||||
$this->assertConfigUpdateImport($name, $original_data, $custom_data);
|
||||
|
@ -145,7 +145,7 @@ class ConfigEntityImportTest extends WebTestBase {
|
|||
$this->assertIdentical($effects, $entity->get('effects'));
|
||||
$this->assertIdentical($effects, $plugin_collection->getConfiguration());
|
||||
|
||||
// Read the existing data, and prepare an altered version in staging.
|
||||
// Read the existing data, and prepare an altered version in sync.
|
||||
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
|
||||
$effect_name = key($original_data['effects']);
|
||||
|
||||
|
@ -167,7 +167,7 @@ class ConfigEntityImportTest extends WebTestBase {
|
|||
|
||||
$this->checkSinglePluginConfigSync($entity, 'configuration', 'boost', 'bi');
|
||||
|
||||
// Read the existing data, and prepare an altered version in staging.
|
||||
// Read the existing data, and prepare an altered version in sync.
|
||||
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
|
||||
$custom_data['configuration']['boost'] = 'asdf';
|
||||
$this->assertConfigUpdateImport($name, $original_data, $custom_data);
|
||||
|
@ -218,7 +218,7 @@ class ConfigEntityImportTest extends WebTestBase {
|
|||
* The new data to store in the config object.
|
||||
*/
|
||||
public function assertConfigUpdateImport($name, $original_data, $custom_data) {
|
||||
$this->container->get('config.storage.staging')->write($name, $custom_data);
|
||||
$this->container->get('config.storage.sync')->write($name, $custom_data);
|
||||
|
||||
// Verify the active configuration still returns the default values.
|
||||
$config = $this->config($name);
|
||||
|
|
|
@ -481,6 +481,74 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$this->assertIdentical(array_values($this->queryResults), array('1', '2', '3', '4'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests sorting with tableSort on config entity queries.
|
||||
*/
|
||||
public function testTableSort() {
|
||||
$header = array(
|
||||
array('data' => t('ID'), 'specifier' => 'id'),
|
||||
array('data' => t('Number'), 'specifier' => 'number'),
|
||||
);
|
||||
|
||||
// Sort key: id
|
||||
// Sorting with 'DESC' upper case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
->tableSort($header)
|
||||
->sort('id', 'DESC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), array('5', '4', '3', '2', '1'));
|
||||
|
||||
// Sorting with 'ASC' upper case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
->tableSort($header)
|
||||
->sort('id', 'ASC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), array('1', '2', '3', '4', '5'));
|
||||
|
||||
// Sorting with 'desc' lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
->tableSort($header)
|
||||
->sort('id', 'desc')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), array('5', '4', '3', '2', '1'));
|
||||
|
||||
// Sorting with 'asc' lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
->tableSort($header)
|
||||
->sort('id', 'asc')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), array('1', '2', '3', '4', '5'));
|
||||
|
||||
// Sort key: number
|
||||
// Sorting with 'DeSc' mixed upper and lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
->tableSort($header)
|
||||
->sort('number', 'DeSc')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), array('3', '5', '2', '1', '4'));
|
||||
|
||||
// Sorting with 'AsC' mixed upper and lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
->tableSort($header)
|
||||
->sort('number', 'AsC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), array('4', '1', '2', '5', '3'));
|
||||
|
||||
// Sorting with 'dEsC' mixed upper and lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
->tableSort($header)
|
||||
->sort('number', 'dEsC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), array('3', '5', '2', '1', '4'));
|
||||
|
||||
// Sorting with 'aSc' mixed upper and lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
->tableSort($header)
|
||||
->sort('number', 'aSc')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), array('4', '1', '2', '5', '3'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests dotted path matching.
|
||||
*/
|
||||
|
|
|
@ -422,7 +422,7 @@ class ContentEntityChangedTest extends EntityUnitTestBase {
|
|||
'Changed flag of German translation is set when changing the German translation.'
|
||||
);
|
||||
|
||||
$french = $entity->getTranslation('fr');
|
||||
$french = $entity->addTranslation('fr');
|
||||
|
||||
$entity->setNewRevision();
|
||||
$entity->save();
|
||||
|
|
|
@ -51,11 +51,11 @@ class ContentEntityNullStorageTest extends KernelTestBase {
|
|||
$contact_form = ContactForm::create(['id' => 'test']);
|
||||
$contact_form->save();
|
||||
|
||||
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
|
||||
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
|
||||
|
||||
// Set up the ConfigImporter object for testing.
|
||||
$storage_comparer = new StorageComparer(
|
||||
$this->container->get('config.storage.staging'),
|
||||
$this->container->get('config.storage.sync'),
|
||||
$this->container->get('config.storage'),
|
||||
$this->container->get('config.manager')
|
||||
);
|
||||
|
@ -71,9 +71,9 @@ class ContentEntityNullStorageTest extends KernelTestBase {
|
|||
$this->container->get('string_translation')
|
||||
);
|
||||
|
||||
// Delete the contact message in staging.
|
||||
$staging = $this->container->get('config.storage.staging');
|
||||
$staging->delete($contact_form->getConfigDependencyName());
|
||||
// Delete the contact message in sync.
|
||||
$sync = $this->container->get('config.storage.sync');
|
||||
$sync->delete($contact_form->getConfigDependencyName());
|
||||
|
||||
// Import.
|
||||
$config_importer->reset()->import();
|
||||
|
|
|
@ -137,7 +137,7 @@ class EntityAccessControlHandlerTest extends EntityLanguageTestBase {
|
|||
));
|
||||
$entity->save();
|
||||
|
||||
$translation = $entity->getTranslation('bar');
|
||||
$translation = $entity->addTranslation('bar');
|
||||
$this->assertEntityAccess(array(
|
||||
'view' => TRUE,
|
||||
), $translation);
|
||||
|
|
|
@ -95,6 +95,31 @@ class EntityApiTest extends EntityUnitTestBase {
|
|||
if ($revision_table = $definition->getRevisionTable()) {
|
||||
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {' . $revision_table . '}')->fetchField(), 'Data table was emptied');
|
||||
}
|
||||
|
||||
// Test deleting a list of entities not indexed by entity id.
|
||||
$entities = array();
|
||||
$entity = entity_create($entity_type, array('name' => 'test', 'user_id' => $user1->id()));
|
||||
$entity->save();
|
||||
$entities['test'] = $entity;
|
||||
$entity = entity_create($entity_type, array('name' => 'test2', 'user_id' => $user1->id()));
|
||||
$entity->save();
|
||||
$entities['test2'] = $entity;
|
||||
$controller = \Drupal::entityManager()->getStorage($entity_type);
|
||||
$controller->delete($entities);
|
||||
|
||||
// Verify that entities got deleted.
|
||||
$all = entity_load_multiple($entity_type);
|
||||
$this->assertTrue(empty($all), format_string('%entity_type: Deleted all entities.', array('%entity_type' => $entity_type)));
|
||||
|
||||
// Verify that all data got deleted from the tables.
|
||||
$definition = \Drupal::entityManager()->getDefinition($entity_type);
|
||||
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {' . $definition->getBaseTable() . '}')->fetchField(), 'Base table was emptied');
|
||||
if ($data_table = $definition->getDataTable()) {
|
||||
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {' . $data_table . '}')->fetchField(), 'Data table was emptied');
|
||||
}
|
||||
if ($revision_table = $definition->getRevisionTable()) {
|
||||
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {' . $revision_table . '}')->fetchField(), 'Data table was emptied');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,8 +57,8 @@ class EntityAutocompleteTest extends EntityUnitTestBase {
|
|||
$entity_2 = entity_create($this->entityType, array('name' => '10/17/2011'));
|
||||
$entity_2->save();
|
||||
|
||||
// Add another entity that has both a comma and a slash character.
|
||||
$entity_3 = entity_create($this->entityType, array('name' => 'label with, and / test'));
|
||||
// Add another entity that has both a comma, a slash and markup.
|
||||
$entity_3 = entity_create($this->entityType, array('name' => 'label with, and / <em>test</em>'));
|
||||
$entity_3->save();
|
||||
|
||||
// Try to autocomplete a entity label that matches both entities.
|
||||
|
@ -84,8 +84,8 @@ class EntityAutocompleteTest extends EntityUnitTestBase {
|
|||
$data = $this->getAutocompleteResult($input);
|
||||
$this->assertIdentical($data[0]['label'], Html::escape($entity_2->name->value), 'Autocomplete returned the second matching entity');
|
||||
|
||||
// Try to autocomplete a entity label with both a comma and a slash.
|
||||
$input = '"label with, and / t';
|
||||
// Try to autocomplete a entity label with both a comma, a slash and markup.
|
||||
$input = '"label with, and / <em>';
|
||||
$data = $this->getAutocompleteResult($input);
|
||||
$n = $entity_3->name->value . ' (3)';
|
||||
// Entity labels containing commas or quotes must be wrapped in quotes.
|
||||
|
|
|
@ -29,7 +29,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('entity_reference', 'entity_test', 'field_test');
|
||||
public static $modules = ['entity_test', 'field_test'];
|
||||
|
||||
/**
|
||||
* The main entity used for testing.
|
||||
|
|
|
@ -107,7 +107,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Update the %entity_type entity type.', array('%entity_type' => $this->entityManager->getDefinition('entity_test_update')->getLabel())),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected); //, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected); //, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
|
||||
// Run the update and ensure the revision table is created.
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
@ -146,7 +146,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Create the %field_name field.', array('%field_name' => t('A new base field'))),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertTrue($this->database->schema()->fieldExists('entity_test_update', 'new_base_field'), 'Column created in shared table for new_base_field.');
|
||||
|
||||
|
@ -159,7 +159,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Update the %field_name field.', array('%field_name' => t('A new base field'))),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertTrue($this->database->schema()->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), 'Index created.');
|
||||
|
||||
|
@ -172,7 +172,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Update the %field_name field.', array('%field_name' => t('A new base field'))),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertFalse($this->database->schema()->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), 'Index deleted.');
|
||||
|
||||
|
@ -186,7 +186,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Update the %field_name field.', array('%field_name' => t('A new base field'))),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertFalse($this->database->schema()->fieldExists('entity_test_update', 'new_base_field'), 'Original column deleted in shared table for new_base_field.');
|
||||
$this->assertTrue($this->database->schema()->fieldExists('entity_test_update', 'new_base_field__value'), 'Value column created in shared table for new_base_field.');
|
||||
|
@ -201,7 +201,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Delete the %field_name field.', array('%field_name' => t('A new base field'))),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertFalse($this->database->schema()->fieldExists('entity_test_update', 'new_base_field_value'), 'Value column deleted from shared table for new_base_field.');
|
||||
$this->assertFalse($this->database->schema()->fieldExists('entity_test_update', 'new_base_field_format'), 'Format column deleted from shared table for new_base_field.');
|
||||
|
@ -220,7 +220,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Create the %field_name field.', array('%field_name' => t('A new bundle field'))),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertTrue($this->database->schema()->tableExists('entity_test_update__new_bundle_field'), 'Dedicated table created for new_bundle_field.');
|
||||
|
||||
|
@ -234,7 +234,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Update the %field_name field.', array('%field_name' => t('A new bundle field'))),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertTrue($this->database->schema()->fieldExists('entity_test_update__new_bundle_field', 'new_bundle_field_format'), 'Format column created in dedicated table for new_base_field.');
|
||||
|
||||
|
@ -247,7 +247,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Delete the %field_name field.', array('%field_name' => t('A new bundle field'))),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertFalse($this->database->schema()->tableExists('entity_test_update__new_bundle_field'), 'Dedicated table deleted for new_bundle_field.');
|
||||
}
|
||||
|
@ -489,7 +489,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Update the %entity_type entity type.', array('%entity_type' => $this->entityManager->getDefinition('entity_test_update')->getLabel())),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
|
||||
// Run the update and ensure the new index is created.
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
@ -504,7 +504,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
t('Update the %entity_type entity type.', array('%entity_type' => $this->entityManager->getDefinition('entity_test_update')->getLabel())),
|
||||
),
|
||||
);
|
||||
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
|
||||
// Run the update and ensure the index is deleted.
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
@ -619,7 +619,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests ::applyEntityUpdate() and ::applyFieldUpdate().
|
||||
* Tests applying single updates.
|
||||
*/
|
||||
public function testSingleActionCalls() {
|
||||
$db_schema = $this->database->schema();
|
||||
|
@ -668,9 +668,9 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
|
|||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
|
||||
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table.");
|
||||
|
||||
// Ensure that installing an existing entity type is a no-op.
|
||||
// Ensure that installing an existing field is a no-op.
|
||||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
|
||||
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), 'Installing an existing entity type is a no-op');
|
||||
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), 'Installing an existing field is a no-op');
|
||||
|
||||
// Update an existing field schema.
|
||||
$this->modifyBaseField();
|
||||
|
|
|
@ -30,7 +30,7 @@ class EntityFieldTest extends EntityUnitTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('filter', 'text', 'node', 'user');
|
||||
public static $modules = array('filter', 'text', 'node', 'user', 'field_test');
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -688,12 +688,10 @@ class EntityFieldTest extends EntityUnitTestBase {
|
|||
->save();
|
||||
$definition = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel('Test entity')
|
||||
->setSettings(array(
|
||||
'target_type' => 'node',
|
||||
'target_bundle' => 'article',
|
||||
));
|
||||
->setSetting('target_type', 'node')
|
||||
->setSetting('handler_settings', ['target_bundles' => ['article' => 'article']]);
|
||||
$reference_field = \Drupal::TypedDataManager()->create($definition);
|
||||
$reference = $reference_field->appendItem(array('entity' => $node))->get('entity');
|
||||
$reference = $reference_field->appendItem(array('entity' => $node));
|
||||
$violations = $reference->validate();
|
||||
$this->assertEqual($violations->count(), 1);
|
||||
|
||||
|
|
|
@ -70,4 +70,12 @@ class EntityListBuilderTest extends WebTestBase {
|
|||
$this->assertEqual(['entity_test_view_grants', 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.permissions'], $build['#cache']['contexts']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the list cache tags are set.
|
||||
*/
|
||||
public function testCacheTags() {
|
||||
$this->drupalGet('entity_test/list');
|
||||
$this->assertCacheTag('entity_test_list');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\system\Tests\Entity;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Tests the Entity Query relationship API.
|
||||
|
|
|
@ -130,7 +130,7 @@ class EntityQueryTest extends EntityUnitTestBase {
|
|||
));
|
||||
// Make sure the name is set for every language that we might create.
|
||||
foreach (array('tr', 'pl') as $langcode) {
|
||||
$entity->getTranslation($langcode)->name = $this->randomMachineName();
|
||||
$entity->addTranslation($langcode)->name = $this->randomMachineName();
|
||||
}
|
||||
foreach (array_reverse(str_split(decbin($i))) as $key => $bit) {
|
||||
if ($bit) {
|
||||
|
|
|
@ -12,8 +12,9 @@ use Drupal\Core\Entity\EntityInterface;
|
|||
use Drupal\Core\Entity\EntityStorageException;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
@ -105,8 +106,14 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
|
|||
$this->assertEqual($violations->count(), 1, 'Validation throws a violation.');
|
||||
$this->assertEqual($violations[0]->getMessage(), t('The referenced entity (%type: %id) does not exist.', array('%type' => $this->referencedEntityType, '%id' => 9999)));
|
||||
|
||||
// @todo Implement a test case for invalid bundle references after
|
||||
// https://www.drupal.org/node/2064191 is fixed.
|
||||
// Test a non-referenceable bundle.
|
||||
entity_test_create_bundle('non_referenceable', NULL, $this->referencedEntityType);
|
||||
$referenced_entity = entity_create($this->referencedEntityType, array('type' => 'non_referenceable'));
|
||||
$referenced_entity->save();
|
||||
$entity->{$this->fieldName}->target_id = $referenced_entity->id();
|
||||
$violations = $entity->{$this->fieldName}->validate();
|
||||
$this->assertEqual($violations->count(), 1, 'Validation throws a violation.');
|
||||
$this->assertEqual($violations[0]->getMessage(), t('The entity must be of bundle %bundle.', array('%bundle' => $this->bundle)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -170,7 +177,7 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
|
|||
else {
|
||||
// A non-existent or NULL entity target id must not return any item in
|
||||
// the target entities set.
|
||||
$this->assertFalse(isset($loaded_entities[$delta]));
|
||||
$this->assertFalse(isset($entities[$delta]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,16 +245,15 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
|
|||
});
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$entity->user_id[0]->get('entity')->setValue($user);
|
||||
$entity->user_id[0]->get('target_id')->setValue(-1);
|
||||
});
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$entity->user_id->setValue(array('entity' => $user, 'target_id' => -1));
|
||||
$entity->user_id->setValue(array('entity' => $user, 'target_id' => NULL));
|
||||
});
|
||||
try {
|
||||
$message = 'Setting both the entity and an invalid target_id property fails.';
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$user->save();
|
||||
$entity->user_id->setValue(array('entity' => $user, 'target_id' => -1));
|
||||
$entity->user_id->setValue(array('entity' => $user, 'target_id' => $this->generateRandomEntityId()));
|
||||
});
|
||||
$this->fail($message);
|
||||
}
|
||||
|
@ -273,16 +279,15 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
|
|||
});
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->user_role[0]->get('entity')->setValue($role);
|
||||
$entity->user_role[0]->get('target_id')->setValue(-1);
|
||||
});
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->user_role->setValue(array('entity' => $role, 'target_id' => -1));
|
||||
$entity->user_role->setValue(array('entity' => $role, 'target_id' => NULL));
|
||||
});
|
||||
try {
|
||||
$message = 'Setting both the entity and an invalid target_id property fails.';
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$role->save();
|
||||
$entity->user_role->setValue(array('entity' => $role, 'target_id' => -1));
|
||||
$entity->user_role->setValue(array('entity' => $role, 'target_id' => $this->generateRandomEntityId(TRUE)));
|
||||
});
|
||||
$this->fail($message);
|
||||
}
|
||||
|
@ -402,4 +407,35 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the dependencies entity reference fields are created with.
|
||||
*/
|
||||
public function testEntityReferenceFieldDependencies() {
|
||||
$field_name = 'user_reference_field';
|
||||
$entity_type = 'entity_test';
|
||||
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'type' => 'entity_reference',
|
||||
'entity_type' => $entity_type,
|
||||
'settings' => [
|
||||
'target_type' => 'user',
|
||||
],
|
||||
]);
|
||||
$field_storage->save();
|
||||
$this->assertEqual(['module' => ['entity_test', 'user']], $field_storage->getDependencies());
|
||||
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => 'entity_test',
|
||||
'label' => $field_name,
|
||||
'settings' => [
|
||||
'handler' => 'default',
|
||||
],
|
||||
]);
|
||||
$field->save();
|
||||
$this->assertEqual(['config' => ['field.storage.entity_test.user_reference_field'], 'module' => ['entity_test']], $field->getDependencies());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ class EntityReferenceSelectionAccessTest extends WebTestBase {
|
|||
'target_type' => 'node',
|
||||
'handler' => 'default',
|
||||
'handler_settings' => array(
|
||||
'target_bundles' => array(),
|
||||
'target_bundles' => NULL,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -203,7 +203,7 @@ class EntityReferenceSelectionAccessTest extends WebTestBase {
|
|||
'target_type' => 'user',
|
||||
'handler' => 'default',
|
||||
'handler_settings' => array(
|
||||
'target_bundles' => array(),
|
||||
'target_bundles' => NULL,
|
||||
'include_anonymous' => TRUE,
|
||||
),
|
||||
);
|
||||
|
@ -345,7 +345,7 @@ class EntityReferenceSelectionAccessTest extends WebTestBase {
|
|||
'target_type' => 'comment',
|
||||
'handler' => 'default',
|
||||
'handler_settings' => array(
|
||||
'target_bundles' => array(),
|
||||
'target_bundles' => NULL,
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ class EntityReferenceSelectionSortTest extends EntityUnitTestBase {
|
|||
'target_type' => 'node',
|
||||
'handler' => 'default',
|
||||
'handler_settings' => array(
|
||||
'target_bundles' => array(),
|
||||
'target_bundles' => NULL,
|
||||
// Add sorting.
|
||||
'sort' => array(
|
||||
'field' => 'field_text.value',
|
||||
|
|
|
@ -57,4 +57,39 @@ class EntityRevisionTranslationTest extends EntityUnitTestBase {
|
|||
$this->assertTrue($this->reloadEntity($entity)->getRevisionId() > $old_rev_id, 'The entity from the storage has a newer revision id.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the translation object has the right revision id after new revision.
|
||||
*/
|
||||
public function testRevertRevisionAfterTranslation() {
|
||||
$user = $this->createUser();
|
||||
$storage = $this->entityManager->getStorage('entity_test_mulrev');
|
||||
|
||||
// Create a test entity.
|
||||
$entity = EntityTestMulRev::create([
|
||||
'name' => $this->randomString(),
|
||||
'user_id' => $user->id(),
|
||||
'language' => 'en',
|
||||
]);
|
||||
$entity->save();
|
||||
$old_rev_id = $entity->getRevisionId();
|
||||
|
||||
$translation = $entity->addTranslation('de');
|
||||
$translation->setNewRevision();
|
||||
$translation->save();
|
||||
|
||||
$entity = $this->reloadEntity($entity);
|
||||
|
||||
$this->assertTrue($entity->hasTranslation('de'));
|
||||
|
||||
$entity = $storage->loadRevision($old_rev_id);
|
||||
|
||||
$entity->setNewRevision();
|
||||
$entity->isDefaultRevision(TRUE);
|
||||
$entity->save();
|
||||
|
||||
$entity = $this->reloadEntity($entity);
|
||||
|
||||
$this->assertFalse($entity->hasTranslation('de'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -139,4 +139,59 @@ class EntitySchemaTest extends EntityUnitTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests fields from an uninstalled module are removed from the schema.
|
||||
*/
|
||||
public function testCleanUpStorageDefinition() {
|
||||
// Find all the entity types provided by the entity_test module and install
|
||||
// the schema for them.
|
||||
$entity_type_ids = [];
|
||||
$entities = \Drupal::entityManager()->getDefinitions();
|
||||
foreach ($entities as $entity_type_id => $definition) {
|
||||
if ($definition->getProvider() == 'entity_test') {
|
||||
$this->installEntitySchema($entity_type_id);
|
||||
$entity_type_ids[] = $entity_type_id;
|
||||
};
|
||||
}
|
||||
|
||||
// Get a list of all the entities in the schema.
|
||||
$key_value_store = \Drupal::keyValue('entity.storage_schema.sql');
|
||||
$schema = $key_value_store->getAll();
|
||||
|
||||
// Count the storage definitions provided by the entity_test module, so that
|
||||
// after uninstall we can be sure there were some to be deleted.
|
||||
$entity_type_id_count = 0;
|
||||
|
||||
foreach (array_keys($schema) as $storage_definition_name) {
|
||||
list($entity_type_id, ,) = explode('.', $storage_definition_name);
|
||||
if (in_array($entity_type_id, $entity_type_ids)) {
|
||||
$entity_type_id_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that there are storage definitions from the entity_test module.
|
||||
$this->assertNotEqual($entity_type_id_count, 0, 'There are storage definitions provided by the entity_test module in the schema.');
|
||||
|
||||
// Uninstall the entity_test module.
|
||||
$this->container->get('module_installer')->uninstall(array('entity_test'));
|
||||
|
||||
// Get a list of all the entities in the schema.
|
||||
$key_value_store = \Drupal::keyValue('entity.storage_schema.sql');
|
||||
$schema = $key_value_store->getAll();
|
||||
|
||||
// Count the storage definitions that come from entity types provided by
|
||||
// the entity_test module.
|
||||
$entity_type_id_count = 0;
|
||||
|
||||
foreach (array_keys($schema) as $storage_definition_name) {
|
||||
list($entity_type_id, ,) = explode('.', $storage_definition_name);
|
||||
if (in_array($entity_type_id, $entity_type_ids)) {
|
||||
$entity_type_id_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that all storage definitions have been removed from the schema.
|
||||
$this->assertEqual($entity_type_id_count, 0, 'After uninstalling entity_test module the schema should not contains fields from entities provided by the module.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -106,9 +106,10 @@ class EntityTranslationFormTest extends WebTestBase {
|
|||
|
||||
// Create a body translation and check the form language.
|
||||
$langcode2 = $this->langcodes[1];
|
||||
$node->getTranslation($langcode2)->title->value = $this->randomString();
|
||||
$node->getTranslation($langcode2)->body->value = $this->randomMachineName(16);
|
||||
$node->getTranslation($langcode2)->setOwnerId($web_user->id());
|
||||
$translation = $node->addTranslation($langcode2);
|
||||
$translation->title->value = $this->randomString();
|
||||
$translation->body->value = $this->randomMachineName(16);
|
||||
$translation->setOwnerId($web_user->id());
|
||||
$node->save();
|
||||
$this->drupalGet($langcode2 . '/node/' . $node->id() . '/edit');
|
||||
$form_langcode = \Drupal::state()->get('entity_test.form_langcode');
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\system\Tests\Entity;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
@ -58,18 +57,15 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$this->assertEqual($field->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($field->getLangcode(), LanguageInterface::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
|
||||
|
||||
// Set the value in a certain language. As the entity is not
|
||||
// language-specific it should use the default language and so ignore the
|
||||
// specified language.
|
||||
$entity->getTranslation($this->langcodes[1])->set($this->fieldName, array(0 => array('value' => 'default value2')));
|
||||
$this->assertEqual($entity->get($this->fieldName)->value, 'default value2', format_string('%entity_type: Untranslated value updated.', array('%entity_type' => $entity_type)));
|
||||
$this->assertFalse($entity->getTranslationLanguages(FALSE), format_string('%entity_type: No translations are available', array('%entity_type' => $entity_type)));
|
||||
|
||||
// Test getting a field value using a specific language for a not
|
||||
// language-specific entity.
|
||||
$field = $entity->getTranslation($this->langcodes[1])->get($this->fieldName);
|
||||
$this->assertEqual($field->value, 'default value2', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($field->getLangcode(), LanguageInterface::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
|
||||
// Try to get add a translation to language neutral entity.
|
||||
$message = 'Adding a translation to a language-neutral entity results in an error.';
|
||||
try {
|
||||
$entity->addTranslation($this->langcodes[1]);
|
||||
$this->fail($message);
|
||||
}
|
||||
catch (\InvalidArgumentException $e) {
|
||||
$this->pass($message);
|
||||
}
|
||||
|
||||
// Now, make the entity language-specific by assigning a language and test
|
||||
// translating it.
|
||||
|
@ -87,7 +83,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$this->assertEqual($field->getLangcode(), $default_langcode, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
|
||||
|
||||
// Set a translation.
|
||||
$entity->getTranslation($this->langcodes[1])->set($this->fieldName, array(0 => array('value' => 'translation 1')));
|
||||
$entity->addTranslation($this->langcodes[1])->set($this->fieldName, array(0 => array('value' => 'translation 1')));
|
||||
$field = $entity->getTranslation($this->langcodes[1])->{$this->fieldName};
|
||||
$this->assertEqual($field->value, 'translation 1', format_string('%entity_type: Translated value set.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($field->getLangcode(), $this->langcodes[1], format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
|
||||
|
@ -100,16 +96,27 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$translations[$this->langcodes[1]] = \Drupal::languageManager()->getLanguage($this->langcodes[1]);
|
||||
$this->assertEqual($entity->getTranslationLanguages(FALSE), $translations, 'Translations retrieved.');
|
||||
|
||||
// Try to get a not available translation.
|
||||
$this->assertNull($entity->getTranslation($this->langcodes[2])->get($this->fieldName)->value, format_string('%entity_type: A translation that is not available is NULL.', array('%entity_type' => $entity_type)));
|
||||
|
||||
// Try to get a value using an invalid language code.
|
||||
// Try to get a value using a language code for a non-existing translation.
|
||||
$message = 'Getting a non existing translation results in an error.';
|
||||
try {
|
||||
$entity->getTranslation('invalid')->get($this->fieldName)->value;
|
||||
$this->fail('Getting a translation for an invalid language is NULL.');
|
||||
$entity->getTranslation($this->langcodes[2])->get($this->fieldName)->value;
|
||||
$this->fail($message);
|
||||
}
|
||||
catch (\InvalidArgumentException $e) {
|
||||
$this->pass('A translation for an invalid language is NULL.');
|
||||
$this->pass($message);
|
||||
}
|
||||
|
||||
// Try to get a not available translation.
|
||||
$this->assertNull($entity->addTranslation($this->langcodes[2])->get($this->fieldName)->value, format_string('%entity_type: A translation that is not available is NULL.', array('%entity_type' => $entity_type)));
|
||||
|
||||
// Try to get a value using an invalid language code.
|
||||
$message = 'Getting an invalid translation results in an error.';
|
||||
try {
|
||||
$entity->getTranslation('invalid')->get($this->fieldName)->value;
|
||||
$this->fail($message);
|
||||
}
|
||||
catch (\InvalidArgumentException $e) {
|
||||
$this->pass($message);
|
||||
}
|
||||
|
||||
// Try to set a value using an invalid language code.
|
||||
|
@ -164,10 +171,12 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($uid, $entity->getTranslation(LanguageInterface::LANGCODE_DEFAULT)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
|
||||
$field = $entity->getTranslation($langcode)->get('name');
|
||||
|
||||
$translation = $entity->getTranslation(LanguageInterface::LANGCODE_DEFAULT);
|
||||
$field = $translation->get('name');
|
||||
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to neutral language.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to neutral language.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($uid, $translation->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to neutral language.', array('%entity_type' => $entity_type)));
|
||||
$field = $entity->get('name');
|
||||
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
|
||||
|
@ -184,16 +193,6 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
|
||||
// Translatable properties on a translatable entity should use default
|
||||
// language if LanguageInterface::LANGCODE_NOT_SPECIFIED is passed.
|
||||
$field = $entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED)->get('name');
|
||||
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to the default language.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($uid, $entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to the default language.', array('%entity_type' => $entity_type)));
|
||||
$field = $entity->get('name');
|
||||
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
|
||||
$this->assertEqual($uid, $entity->get('user_id')->target_id, format_string('%entity_type: The entity author can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
|
||||
|
||||
// Create property translations.
|
||||
$properties = array();
|
||||
|
@ -211,7 +210,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
'user_id' => array(0 => $uid),
|
||||
);
|
||||
}
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
$translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode);
|
||||
foreach ($properties[$langcode] as $field_name => $values) {
|
||||
$translation->set($field_name, $values);
|
||||
}
|
||||
|
@ -328,7 +327,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
|
||||
// Verify that we obtain the entity object itself when we attempt to
|
||||
// retrieve a translation referring to it.
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
$translation = $entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED);
|
||||
$this->assertIdentical($entity, $translation, 'The translation object corresponding to a non-default language is the entity object itself when the entity is language-neutral.');
|
||||
$entity->{$langcode_key}->value = $default_langcode;
|
||||
$translation = $entity->getTranslation($default_langcode);
|
||||
|
@ -337,6 +336,17 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$this->assertIdentical($entity, $translation, 'The translation object corresponding to the default language (implicit) is the entity object itself.');
|
||||
$this->assertTrue($entity->{$default_langcode_key}->value, 'The translation object is the default one.');
|
||||
|
||||
// Verify that trying to retrieve a translation for a locked language when
|
||||
// the entity is language-aware causes an exception to be thrown.
|
||||
$message = 'A language-neutral translation cannot be retrieved.';
|
||||
try {
|
||||
$entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED);
|
||||
$this->fail($message);
|
||||
}
|
||||
catch (\LogicException $e) {
|
||||
$this->pass($message);
|
||||
}
|
||||
|
||||
// Create a translation and verify that the translation object and the
|
||||
// original object behave independently.
|
||||
$name = $default_langcode . '_' . $this->randomMachineName();
|
||||
|
@ -416,7 +426,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
// new translation object can be obtained also by just specifying a valid
|
||||
// language.
|
||||
$langcode2 = $this->langcodes[2];
|
||||
$translation = $entity->getTranslation($langcode2);
|
||||
$translation = $entity->addTranslation($langcode2);
|
||||
$value = $entity !== $translation && $translation->language()->getId() == $langcode2 && $entity->hasTranslation($langcode2);
|
||||
$this->assertTrue($value, 'A new translation object can be obtained also by specifying a valid language.');
|
||||
$this->assertEqual($entity->language()->getId(), $default_langcode, 'The original language has been preserved.');
|
||||
|
@ -526,7 +536,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
// 'description' field.
|
||||
$entity = $this->entityManager
|
||||
->getStorage('entity_test_mul_default_value')
|
||||
->create(array('name' => $this->randomMachineName(), 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED));
|
||||
->create(['name' => $this->randomMachineName(), 'langcode' => $langcode]);
|
||||
$translation = $entity->addTranslation($langcode2);
|
||||
$expected = array(
|
||||
array(
|
||||
|
|
|
@ -20,7 +20,7 @@ abstract class EntityUnitTestBase extends KernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('user', 'system', 'field', 'text', 'filter', 'entity_test', 'entity_reference');
|
||||
public static $modules = ['user', 'system', 'field', 'text', 'filter', 'entity_test'];
|
||||
|
||||
/**
|
||||
* The entity manager service.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Drupal\system\Tests\Entity;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
@ -22,13 +22,6 @@ class EntityViewBuilderTest extends EntityUnitTestBase {
|
|||
|
||||
use EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('entity_reference');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -49,6 +42,7 @@ class EntityViewBuilderTest extends EntityUnitTestBase {
|
|||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = $this->container->get('renderer');
|
||||
$cache_contexts_manager = \Drupal::service("cache_contexts_manager");
|
||||
$cache = \Drupal::cache();
|
||||
|
||||
// Force a request via GET so we can get drupal_render() cache working.
|
||||
$request = \Drupal::request();
|
||||
|
@ -78,8 +72,10 @@ class EntityViewBuilderTest extends EntityUnitTestBase {
|
|||
$this->assertTrue($this->container->get('cache.' . $bin)->get($cid), 'The entity render element has been cached.');
|
||||
|
||||
// Re-save the entity and check that the cache entry has been deleted.
|
||||
$cache->set('kittens', 'Kitten data', Cache::PERMANENT, $build['#cache']['tags']);
|
||||
$entity_test->save();
|
||||
$this->assertFalse($this->container->get('cache.' . $bin)->get($cid), 'The entity render cache has been cleared when the entity was saved.');
|
||||
$this->assertFalse($cache->get('kittens'), 'The entity saving has invalidated cache tags.');
|
||||
|
||||
// Rebuild the render array (creating a new cache entry in the process) and
|
||||
// delete the entity to check the cache entry is deleted.
|
||||
|
|
|
@ -47,7 +47,7 @@ class EntityViewControllerTest extends WebTestBase {
|
|||
*/
|
||||
function testEntityViewController() {
|
||||
$get_label_markup = function($label) {
|
||||
return '<h1>
|
||||
return '<h1 class="page-title">
|
||||
<div class="field field--name-name field--type-string field--label-hidden field__item">' . $label . '</div>
|
||||
</h1>';
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ class FieldAccessTest extends KernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('entity_test', 'field', 'system', 'text', 'filter', 'user', 'entity_reference');
|
||||
public static $modules = ['entity_test', 'field', 'system', 'text', 'filter', 'user'];
|
||||
|
||||
/**
|
||||
* Holds the currently active global user ID that initiated the test run.
|
||||
|
|
|
@ -469,35 +469,6 @@ class FieldSqlStorageTest extends EntityUnitTestBase {
|
|||
$this->assertEqual($schema['foreign keys'][$foreign_key_name]['columns'][$foreign_key_name], 'id', 'Foreign key column name modified after update');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests reacting to a bundle being renamed.
|
||||
*/
|
||||
function testFieldSqlStorageBundleRename() {
|
||||
$entity_type = $bundle = 'entity_test_rev';
|
||||
$field_name = $this->fieldStorage->getName();
|
||||
|
||||
// Create an entity.
|
||||
$value = mt_rand(1, 127);
|
||||
$entity = entity_create($entity_type, array(
|
||||
'type' => $bundle,
|
||||
$field_name => $value,
|
||||
));
|
||||
$entity->save();
|
||||
|
||||
// Rename the bundle.
|
||||
$bundle_new = $bundle . '_renamed';
|
||||
entity_test_rename_bundle($bundle, $bundle_new, $entity_type);
|
||||
|
||||
// Check that the 'bundle' column has been updated in storage.
|
||||
$row = db_select($this->table, 't')
|
||||
->fields('t', array('bundle', $field_name . '_value'))
|
||||
->condition('entity_id', $entity->id())
|
||||
->execute()
|
||||
->fetch();
|
||||
$this->assertEqual($row->bundle, $bundle_new);
|
||||
$this->assertEqual($row->{$field_name . '_value'}, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests table name generation.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\Tests\Entity\Update\LangcodeToAsciiUpdateFilledTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\Entity\Update;
|
||||
|
||||
/**
|
||||
* Runs LangcodeToAsciiUpdateTest with a dump filled with content.
|
||||
*
|
||||
* @group Entity
|
||||
*/
|
||||
class LangcodeToAsciiUpdateFilledTest extends LangcodeToAsciiUpdateTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.filled.standard.php.gz',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\Tests\Entity\Update\LangcodeToAsciiUpdateTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\Entity\Update;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests that the entity langcode fields have been updated to varchar_ascii.
|
||||
*
|
||||
* @group Entity
|
||||
*/
|
||||
class LangcodeToAsciiUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the column collation has been updated on MySQL.
|
||||
*/
|
||||
public function testLangcodeColumnCollation() {
|
||||
// Only testable on MySQL.
|
||||
// @see https://www.drupal.org/node/301038
|
||||
if (Database::getConnection()->databaseType() !== 'mysql') {
|
||||
$this->pass('This test can only run on MySQL');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check a few different tables.
|
||||
$tables = [
|
||||
'node_field_data' => ['langcode'],
|
||||
'users_field_data' => ['langcode', 'preferred_langcode', 'preferred_admin_langcode'],
|
||||
];
|
||||
foreach ($tables as $table => $columns) {
|
||||
foreach ($columns as $column) {
|
||||
$this->assertEqual('utf8mb4_general_ci', $this->getColumnCollation($table, $column), 'Found correct starting collation for ' . $table . '.' . $column);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply updates.
|
||||
$this->runUpdates();
|
||||
|
||||
foreach ($tables as $table => $columns) {
|
||||
foreach ($columns as $column) {
|
||||
$this->assertEqual('ascii_general_ci', $this->getColumnCollation($table, $column), 'Found correct updated collation for ' . $table . '.' . $column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the column collation.
|
||||
*
|
||||
* @param string $table
|
||||
* The table name.
|
||||
* @param string $column
|
||||
* The column name.
|
||||
*/
|
||||
protected function getColumnCollation($table, $column) {
|
||||
$query = Database::getConnection()->query("SHOW FULL COLUMNS FROM {" . $table . "}");
|
||||
while ($row = $query->fetchAssoc()) {
|
||||
if ($row['Field'] === $column) {
|
||||
return $row['Collation'];
|
||||
}
|
||||
}
|
||||
$this->fail('No collation found for ' . $table . '.' . $column);
|
||||
}
|
||||
|
||||
}
|
|
@ -68,9 +68,9 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
|
|||
$this->assertEqual(count($entity->user_id), 1);
|
||||
$this->assertEqual($entity->user_id->target_id, $user_ids[0]);
|
||||
|
||||
// Make 'user_id' multiple by running updates.
|
||||
// Make 'user_id' multiple by applying updates.
|
||||
$this->enableUpdates('entity_test', 'entity_definition_updates', 8001);
|
||||
$this->runUpdates();
|
||||
$this->applyUpdates();
|
||||
|
||||
// Check that data was correctly migrated.
|
||||
$entity = $this->reloadEntity($entity);
|
||||
|
@ -85,14 +85,21 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
|
|||
$this->assertEqual($entity->user_id[0]->target_id, $user_ids[0]);
|
||||
$this->assertEqual($entity->user_id[1]->target_id, $user_ids[1]);
|
||||
|
||||
// Make 'user_id' single again by running updates.
|
||||
// Make 'user_id' single again by applying updates.
|
||||
$this->enableUpdates('entity_test', 'entity_definition_updates', 8002);
|
||||
$this->runUpdates();
|
||||
$this->applyUpdates();
|
||||
|
||||
// Check that data was correctly migrated/dropped.
|
||||
$entity = $this->reloadEntity($entity);
|
||||
$this->assertEqual(count($entity->user_id), 1);
|
||||
$this->assertEqual($entity->user_id->target_id, $user_ids[0]);
|
||||
|
||||
// Check that only a single value is stored for 'user_id' again.
|
||||
$entity->user_id = $user_ids;
|
||||
$entity->save();
|
||||
$entity = $this->reloadEntity($entity);
|
||||
$this->assertEqual(count($entity->user_id), 1);
|
||||
$this->assertEqual($entity->user_id[0]->target_id, $user_ids[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,9 +116,9 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
|
|||
$this->assertEqual(count($entity->user_id), 1);
|
||||
$this->assertEqual($entity->user_id->target_id, $user_ids[0]);
|
||||
|
||||
// Make 'user_id' multiple and then single again by running updates.
|
||||
// Make 'user_id' multiple and then single again by applying updates.
|
||||
$this->enableUpdates('entity_test', 'entity_definition_updates', 8002);
|
||||
$this->runUpdates();
|
||||
$this->applyUpdates();
|
||||
|
||||
// Check that data was correctly migrated back and forth.
|
||||
$entity = $this->reloadEntity($entity);
|
||||
|
@ -154,8 +161,8 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
|
|||
$this->assertRaw('Out of date');
|
||||
$this->assertNoRaw('Mismatch detected');
|
||||
|
||||
// Run db updates and check that entity updates were not applied.
|
||||
$this->runUpdates();
|
||||
// Apply db updates and check that entity updates were not applied.
|
||||
$this->applyUpdates();
|
||||
$this->drupalGet('admin/reports/status');
|
||||
$this->assertNoRaw('Out of date');
|
||||
$this->assertRaw('Mismatch detected');
|
||||
|
@ -180,7 +187,7 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
|
|||
// entity updates were not applied even when no data exists.
|
||||
$entity->delete();
|
||||
$this->enableUpdates('entity_test', 'status_report', 8002);
|
||||
$this->runUpdates();
|
||||
$this->applyUpdates();
|
||||
$this->drupalGet('admin/reports/status');
|
||||
$this->assertNoRaw('Out of date');
|
||||
$this->assertRaw('Mismatch detected');
|
||||
|
|
120
core/modules/system/src/Tests/Field/FieldSettingsTest.php
Normal file
120
core/modules/system/src/Tests/Field/FieldSettingsTest.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains Drupal\system\Tests\Field\FieldSettingsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\Field;
|
||||
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
/**
|
||||
* Tests field settings methods on field definition structures.
|
||||
*
|
||||
* @group Field
|
||||
*/
|
||||
class FieldSettingsTest extends EntityUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('field', 'field_test');
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Field\BaseFieldDefinition::getSettings()
|
||||
* @covers \Drupal\Core\Field\BaseFieldDefinition::setSettings()
|
||||
*/
|
||||
public function testBaseFieldSettings() {
|
||||
$base_field = BaseFieldDefinition::create('test_field');
|
||||
|
||||
// Check that the default settings have been populated.
|
||||
$expected_settings = [
|
||||
'test_field_storage_setting' => 'dummy test string',
|
||||
'changeable' => 'a changeable field storage setting',
|
||||
'unchangeable' => 'an unchangeable field storage setting',
|
||||
'translatable_storage_setting' => 'a translatable field storage setting',
|
||||
'test_field_setting' => 'dummy test string',
|
||||
'translatable_field_setting' => 'a translatable field setting',
|
||||
];
|
||||
$this->assertEqual($base_field->getSettings(), $expected_settings);
|
||||
|
||||
// Change one single setting using setSettings(), and check that the other
|
||||
// expected settings are still present.
|
||||
$expected_settings['test_field_setting'] = 'another test string';
|
||||
$base_field->setSettings(['test_field_setting' => $expected_settings['test_field_setting']]);
|
||||
$this->assertEqual($base_field->getSettings(), $expected_settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\field\Entity\FieldStorageConfig::getSettings()
|
||||
* @covers \Drupal\field\Entity\FieldStorageConfig::setSettings()
|
||||
*/
|
||||
public function testConfigurableFieldStorageSettings() {
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => 'test_field',
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'test_field'
|
||||
]);
|
||||
|
||||
// Check that the default settings have been populated.
|
||||
$expected_settings = [
|
||||
'test_field_storage_setting' => 'dummy test string',
|
||||
'changeable' => 'a changeable field storage setting',
|
||||
'unchangeable' => 'an unchangeable field storage setting',
|
||||
'translatable_storage_setting' => 'a translatable field storage setting',
|
||||
];
|
||||
$this->assertEqual($field_storage->getSettings(), $expected_settings);
|
||||
|
||||
// Change one single setting using setSettings(), and check that the other
|
||||
// expected settings are still present.
|
||||
$expected_settings['test_field_storage_setting'] = 'another test string';
|
||||
$field_storage->setSettings(['test_field_storage_setting' => $expected_settings['test_field_storage_setting']]);
|
||||
$this->assertEqual($field_storage->getSettings(), $expected_settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\field\Entity\FieldStorageConfig::getSettings()
|
||||
* @covers \Drupal\field\Entity\FieldStorageConfig::setSettings()
|
||||
*/
|
||||
public function testConfigurableFieldSettings() {
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => 'test_field',
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'test_field'
|
||||
]);
|
||||
$field = FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'entity_test'
|
||||
]);
|
||||
// Note: FieldConfig does not populate default settings until the config
|
||||
// is saved.
|
||||
// @todo Remove once https://www.drupal.org/node/2327883 is fixed.
|
||||
$field->save();
|
||||
|
||||
// Check that the default settings have been populated. Note: getSettings()
|
||||
// returns both storage and field settings.
|
||||
$expected_settings = [
|
||||
'test_field_storage_setting' => 'dummy test string',
|
||||
'changeable' => 'a changeable field storage setting',
|
||||
'unchangeable' => 'an unchangeable field storage setting',
|
||||
'translatable_storage_setting' => 'a translatable field storage setting',
|
||||
'test_field_setting' => 'dummy test string',
|
||||
'translatable_field_setting' => 'a translatable field setting',
|
||||
'field_setting_from_config_data' => TRUE,
|
||||
];
|
||||
$this->assertEqual($field->getSettings(), $expected_settings);
|
||||
|
||||
// Change one single setting using setSettings(), and check that the other
|
||||
// expected settings are still present.
|
||||
$expected_settings['test_field_setting'] = 'another test string';
|
||||
$field->setSettings(['test_field_setting' => $expected_settings['test_field_setting']]);
|
||||
$this->assertEqual($field->getSettings(), $expected_settings);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\Tests\File\FileSaveHtaccessLoggingTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\File;
|
||||
|
||||
use Drupal\Component\PhpStorage\FileStorage;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests the log message added by file_save_htacess().
|
||||
*
|
||||
* @group File
|
||||
*/
|
||||
class FileSaveHtaccessLoggingTest extends WebTestBase {
|
||||
|
||||
protected static $modules = ['dblog'];
|
||||
|
||||
/**
|
||||
* Tests file_save_htaccess().
|
||||
*/
|
||||
function testHtaccessSave() {
|
||||
// Prepare test directories.
|
||||
$private = $this->publicFilesDirectory . '/test/private';
|
||||
|
||||
// Verify that file_save_htaccess() returns FALSE if .htaccess cannot be
|
||||
// written and writes a correctly formatted message to the error log. Set
|
||||
// $private to TRUE so all possible .htaccess lines are written.
|
||||
$this->assertFalse(file_save_htaccess($private, TRUE));
|
||||
$this->drupalLogin($this->rootUser);
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->clickLink("Security warning: Couldn't write .htaccess file. Please…");
|
||||
|
||||
$lines = FileStorage::htaccessLines(TRUE);
|
||||
foreach (array_filter(explode("\n", $lines)) as $line) {
|
||||
$this->assertEscaped($line);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -44,7 +44,7 @@ class NameMungingTest extends FileTestBase {
|
|||
$this->config('system.file')->set('allow_insecure_uploads', 0)->save();
|
||||
$munged_name = file_munge_filename($this->name, '', TRUE);
|
||||
$messages = drupal_get_messages();
|
||||
$this->assertTrue(in_array(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $munged_name)), $messages['status']), 'Alert properly set when a file is renamed.');
|
||||
$this->assertTrue(in_array(strtr('For security reasons, your upload has been renamed to <em class="placeholder">%filename</em>.', array('%filename' => $munged_name)), $messages['status']), 'Alert properly set when a file is renamed.');
|
||||
$this->assertNotEqual($munged_name, $this->name, format_string('The new filename (%munged) has been modified from the original (%original)', array('%munged' => $munged_name, '%original' => $this->name)));
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,12 @@ class ElementTest extends WebTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
// Verify that the choices are admin filtered as expected.
|
||||
$this->assertRaw("<em>Special Char</em>alert('checkboxes');");
|
||||
$this->assertRaw("<em>Special Char</em>alert('radios');");
|
||||
$this->assertRaw('<em>Bar - checkboxes</em>');
|
||||
$this->assertRaw('<em>Bar - radios</em>');
|
||||
|
||||
// Enable customized option sub-elements.
|
||||
$this->drupalGet('form-test/checkboxes-radios/customize');
|
||||
|
||||
|
@ -160,4 +166,12 @@ class ElementTest extends WebTestBase {
|
|||
$this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests form element error messages.
|
||||
*/
|
||||
public function testFormElementErrors() {
|
||||
$this->drupalPostForm('form_test/details-form', [], 'Submit');
|
||||
$this->assertText('I am an error on the details element.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ class ElementsLabelsTest extends WebTestBase {
|
|||
$elements = $this->xpath('//label[@for="edit-form-textfield-test-title-no-show"]');
|
||||
$this->assertFalse(isset($elements[0]), 'No label tag when title set not to display.');
|
||||
|
||||
$elements = $this->xpath('//div[contains(@class, "form-item-form-textfield-test-title-invisible") and contains(@class, "form-no-label")]');
|
||||
$elements = $this->xpath('//div[contains(@class, "js-form-item-form-textfield-test-title-invisible") and contains(@class, "form-no-label")]');
|
||||
$this->assertTrue(isset($elements[0]), 'Field class is form-no-label when there is no label.');
|
||||
|
||||
// Check #field_prefix and #field_suffix placement.
|
||||
|
@ -82,10 +82,10 @@ class ElementsLabelsTest extends WebTestBase {
|
|||
$this->assertTrue(isset($elements[0]), 'Properly places the #field_suffix element immediately after the form field.');
|
||||
|
||||
// Check #prefix and #suffix placement.
|
||||
$elements = $this->xpath('//div[@id="form-test-textfield-title-prefix"]/following-sibling::div[contains(@class, \'form-item-form-textfield-test-title\')]');
|
||||
$elements = $this->xpath('//div[@id="form-test-textfield-title-prefix"]/following-sibling::div[contains(@class, \'js-form-item-form-textfield-test-title\')]');
|
||||
$this->assertTrue(isset($elements[0]), 'Properly places the #prefix element before the form item.');
|
||||
|
||||
$elements = $this->xpath('//div[@id="form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'form-item-form-textfield-test-title\')]');
|
||||
$elements = $this->xpath('//div[@id="form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'js-form-item-form-textfield-test-title\')]');
|
||||
$this->assertTrue(isset($elements[0]), 'Properly places the #suffix element before the form item.');
|
||||
|
||||
// Check title attribute for radios and checkboxes.
|
||||
|
|
|
@ -35,7 +35,7 @@ class EmailTest extends WebTestBase {
|
|||
$edit['email_required'] = ' ';
|
||||
$this->drupalPostForm('form-test/email', $edit, 'Submit');
|
||||
$this->assertRaw(t('The email address %mail is not valid.', array('%mail' => 'invalid')));
|
||||
$this->assertRaw(t('!name field is required.', array('!name' => 'Address')));
|
||||
$this->assertRaw(t('@name field is required.', array('@name' => 'Address')));
|
||||
|
||||
$edit = array();
|
||||
$edit['email_required'] = ' foo.bar@example.com ';
|
||||
|
|
|
@ -144,7 +144,7 @@ class FormTest extends WebTestBase {
|
|||
// Select elements are going to have validation errors with empty
|
||||
// input, since those are illegal choices. Just make sure the
|
||||
// error is not "field is required".
|
||||
$this->assertTrue((empty($errors[$element]) || strpos('field is required', $errors[$element]) === FALSE), "Optional '$type' field '$element' is not treated as a required element");
|
||||
$this->assertTrue((empty($errors[$element]) || strpos('field is required', (string) $errors[$element]) === FALSE), "Optional '$type' field '$element' is not treated as a required element");
|
||||
}
|
||||
else {
|
||||
// Make sure there is *no* form error for this element.
|
||||
|
@ -185,12 +185,12 @@ class FormTest extends WebTestBase {
|
|||
$expected[] = $form[$key]['#form_test_required_error'];
|
||||
}
|
||||
else {
|
||||
$expected[] = t('!name field is required.', array('!name' => $form[$key]['#title']));
|
||||
$expected[] = t('@name field is required.', array('@name' => $form[$key]['#title']));
|
||||
}
|
||||
}
|
||||
|
||||
// Check the page for error messages.
|
||||
$errors = $this->xpath('//div[contains(@class, "form-item--error-message")]//strong');
|
||||
$errors = $this->xpath('//div[contains(@class, "error")]//li');
|
||||
foreach ($errors as $error) {
|
||||
$expected_key = array_search($error[0], $expected);
|
||||
// If the error message is not one of the expected messages, fail.
|
||||
|
@ -294,6 +294,18 @@ class FormTest extends WebTestBase {
|
|||
$this->assertFieldByName('url', $edit['url']);
|
||||
}
|
||||
|
||||
/**
|
||||
* CSRF tokens for GET forms should not be added by default.
|
||||
*/
|
||||
public function testGetFormsCsrfToken() {
|
||||
// We need to be logged in to have CSRF tokens.
|
||||
$account = $this->createUser();
|
||||
$this->drupalLogin($account);
|
||||
|
||||
$this->drupalGet(Url::fromRoute('form_test.get_form'));
|
||||
$this->assertNoRaw('form_token');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests validation for required textfield element without title.
|
||||
*
|
||||
|
@ -335,7 +347,7 @@ class FormTest extends WebTestBase {
|
|||
// First, try to submit without the required checkbox.
|
||||
$edit = array();
|
||||
$this->drupalPostForm('form-test/checkbox', $edit, t('Submit'));
|
||||
$this->assertRaw(t('!name field is required.', array('!name' => 'required_checkbox')), 'A required checkbox is actually mandatory');
|
||||
$this->assertRaw(t('@name field is required.', array('@name' => 'required_checkbox')), 'A required checkbox is actually mandatory');
|
||||
|
||||
// Now try to submit the form correctly.
|
||||
$values = Json::decode($this->drupalPostForm(NULL, array('required_checkbox' => 1), t('Submit')));
|
||||
|
@ -361,9 +373,12 @@ class FormTest extends WebTestBase {
|
|||
*/
|
||||
function testSelect() {
|
||||
$form = \Drupal::formBuilder()->getForm('Drupal\form_test\Form\FormTestSelectForm');
|
||||
$error = '!name field is required.';
|
||||
$this->drupalGet('form-test/select');
|
||||
|
||||
// Verify that the options are escaped as expected.
|
||||
$this->assertEscaped('<strong>four</strong>');
|
||||
$this->assertNoRaw('<strong>four</strong>');
|
||||
|
||||
// Posting without any values should throw validation errors.
|
||||
$this->drupalPostForm(NULL, array(), 'Submit');
|
||||
$no_errors = array(
|
||||
|
@ -379,7 +394,7 @@ class FormTest extends WebTestBase {
|
|||
'multiple_no_default',
|
||||
);
|
||||
foreach ($no_errors as $key) {
|
||||
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
|
||||
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
|
||||
}
|
||||
|
||||
$expected_errors = array(
|
||||
|
@ -390,7 +405,7 @@ class FormTest extends WebTestBase {
|
|||
'multiple_no_default_required',
|
||||
);
|
||||
foreach ($expected_errors as $key) {
|
||||
$this->assertText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
|
||||
$this->assertText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
|
||||
}
|
||||
|
||||
// Post values for required fields.
|
||||
|
|
|
@ -42,13 +42,18 @@ class ModulesListFormWebTest extends WebTestBase {
|
|||
$this->assertResponse('200');
|
||||
|
||||
// Check that system_test's configure link was rendered correctly.
|
||||
$this->assertFieldByXPath("//a[contains(@href, '/system-test/configure/bar') and @title='Bar.bar']");
|
||||
$this->assertFieldByXPath("//a[contains(@href, '/system-test/configure/bar') and text()='Configure ']/span[contains(@class, 'visually-hidden') and text()='the System test module']");
|
||||
|
||||
// Check that system_test's permissions link was rendered correctly.
|
||||
$this->assertFieldByXPath("//a[contains(@href, '/admin/people/permissions#module-system_test') and @title='Configure permissions']");
|
||||
|
||||
// Check that system_test's help link was rendered correctly.
|
||||
$this->assertFieldByXPath("//a[contains(@href, '/admin/help/system_test') and @title='Help']");
|
||||
|
||||
// Ensure that the Testing module's machine name is printed. Testing module
|
||||
// is used because its machine name is different than its human readable
|
||||
// name.
|
||||
$this->assertText('simpletest');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ class RebuildTest extends WebTestBase {
|
|||
|
||||
// Ensure that the form contains two items in the multi-valued field, so we
|
||||
// know we're testing a form that was correctly retrieved from cache.
|
||||
$this->assert(count($this->xpath('//form[contains(@id, "node-page-form")]//div[contains(@class, "form-item-field-ajax-test")]//input[@type="text"]')) == 2, 'Form retained its state from cache.');
|
||||
$this->assert(count($this->xpath('//form[contains(@id, "node-page-form")]//div[contains(@class, "js-form-item-field-ajax-test")]//input[@type="text"]')) == 2, 'Form retained its state from cache.');
|
||||
|
||||
// Ensure that the form's action is correct.
|
||||
$forms = $this->xpath('//form[contains(@class, "node-page-form")]');
|
||||
|
|
|
@ -19,20 +19,8 @@ use Drupal\simpletest\KernelTestBase;
|
|||
*/
|
||||
class TriggeringElementProgrammedUnitTest extends KernelTestBase implements FormInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('system');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', ['router']);
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -35,7 +35,7 @@ class UrlTest extends WebTestBase {
|
|||
$edit['url_required'] = ' ';
|
||||
$this->drupalPostForm('form-test/url', $edit, 'Submit');
|
||||
$this->assertRaw(t('The URL %url is not valid.', array('%url' => 'http://')));
|
||||
$this->assertRaw(t('!name field is required.', array('!name' => 'Required URL')));
|
||||
$this->assertRaw(t('@name field is required.', array('@name' => 'Required URL')));
|
||||
|
||||
$edit = array();
|
||||
$edit['url'] = "\n";
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\system\Tests\Form;
|
||||
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
|
@ -75,6 +74,14 @@ class ValidationTest extends WebTestBase {
|
|||
$this->assertText('The form has become outdated. Copy any unsaved work in the form below');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a form with a disabled CSRF token can be validated.
|
||||
*/
|
||||
function testDisabledToken() {
|
||||
$this->drupalPostForm('form-test/validate-no-token', [], 'Save');
|
||||
$this->assertText('The form_test_validate_no_token form has been submitted successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests partial form validation through #limit_validation_errors.
|
||||
*/
|
||||
|
@ -110,19 +117,19 @@ class ValidationTest extends WebTestBase {
|
|||
// validated, but the #element_validate handler for the 'test' field
|
||||
// is triggered.
|
||||
$this->drupalPostForm($path, $edit, t('Partial validate'));
|
||||
$this->assertNoText(t('!name field is required.', array('!name' => 'Title')));
|
||||
$this->assertNoText(t('@name field is required.', array('@name' => 'Title')));
|
||||
$this->assertText('Test element is invalid');
|
||||
|
||||
// Edge case of #limit_validation_errors containing numeric indexes: same
|
||||
// thing with the 'Partial validate (numeric index)' button and the
|
||||
// 'test_numeric_index' field.
|
||||
$this->drupalPostForm($path, $edit, t('Partial validate (numeric index)'));
|
||||
$this->assertNoText(t('!name field is required.', array('!name' => 'Title')));
|
||||
$this->assertNoText(t('@name field is required.', array('@name' => 'Title')));
|
||||
$this->assertText('Test (numeric index) element is invalid');
|
||||
|
||||
// Ensure something like 'foobar' isn't considered "inside" 'foo'.
|
||||
$this->drupalPostForm($path, $edit, t('Partial validate (substring)'));
|
||||
$this->assertNoText(t('!name field is required.', array('!name' => 'Title')));
|
||||
$this->assertNoText(t('@name field is required.', array('@name' => 'Title')));
|
||||
$this->assertText('Test (substring) foo element is invalid');
|
||||
|
||||
// Ensure not validated values are not available to submit handlers.
|
||||
|
@ -132,7 +139,7 @@ class ValidationTest extends WebTestBase {
|
|||
// Now test full form validation and ensure that the #element_validate
|
||||
// handler is still triggered.
|
||||
$this->drupalPostForm($path, $edit, t('Full validate'));
|
||||
$this->assertText(t('!name field is required.', array('!name' => 'Title')));
|
||||
$this->assertText(t('@name field is required.', array('@name' => 'Title')));
|
||||
$this->assertText('Test element is invalid');
|
||||
}
|
||||
|
||||
|
@ -207,33 +214,17 @@ class ValidationTest extends WebTestBase {
|
|||
$edit = array();
|
||||
$this->drupalPostForm('form-test/validate-required', $edit, 'Submit');
|
||||
|
||||
$messages = [];
|
||||
foreach (Element::children($form) as $key) {
|
||||
if (isset($form[$key]['#required_error'])) {
|
||||
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
|
||||
$messages[] = [
|
||||
'title' => $form[$key]['#title'],
|
||||
'message' => $form[$key]['#required_error'],
|
||||
'key' => $key,
|
||||
];
|
||||
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
|
||||
$this->assertText($form[$key]['#required_error']);
|
||||
}
|
||||
elseif (isset($form[$key]['#form_test_required_error'])) {
|
||||
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
|
||||
$messages[] = [
|
||||
'title' => $form[$key]['#title'],
|
||||
'message' => $form[$key]['#form_test_required_error'],
|
||||
'key' => $key,
|
||||
];
|
||||
}
|
||||
elseif (!empty($form[$key]['#required'])) {
|
||||
$messages[] = [
|
||||
'title' => $form[$key]['#title'],
|
||||
'message' => t('!name field is required.', ['!name' => $form[$key]['#title']]),
|
||||
'key' => $key,
|
||||
];
|
||||
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
|
||||
$this->assertText($form[$key]['#form_test_required_error']);
|
||||
}
|
||||
}
|
||||
$this->assertErrorMessages($messages);
|
||||
$this->assertNoText(t('An illegal choice has been detected. Please contact the site administrator.'));
|
||||
|
||||
// Verify that no custom validation error appears with valid values.
|
||||
$edit = array(
|
||||
|
@ -243,60 +234,17 @@ class ValidationTest extends WebTestBase {
|
|||
);
|
||||
$this->drupalPostForm('form-test/validate-required', $edit, 'Submit');
|
||||
|
||||
$messages = [];
|
||||
foreach (Element::children($form) as $key) {
|
||||
if (isset($form[$key]['#required_error'])) {
|
||||
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
|
||||
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
|
||||
$this->assertNoText($form[$key]['#required_error']);
|
||||
}
|
||||
elseif (isset($form[$key]['#form_test_required_error'])) {
|
||||
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
|
||||
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
|
||||
$this->assertNoText($form[$key]['#form_test_required_error']);
|
||||
}
|
||||
elseif (!empty($form[$key]['#required'])) {
|
||||
$messages[] = [
|
||||
'title' => $form[$key]['#title'],
|
||||
'message' => t('!name field is required.', ['!name' => $form[$key]['#title']]),
|
||||
'key' => $key,
|
||||
];
|
||||
}
|
||||
}
|
||||
$this->assertErrorMessages($messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given error messages are displayed.
|
||||
*
|
||||
* @param array $messages
|
||||
* An associative array of error messages keyed by the order they appear on
|
||||
* the page, with the following key-value pairs:
|
||||
* - title: The human readable form element title.
|
||||
* - message: The error message for this form element.
|
||||
* - key: The key used for the form element.
|
||||
*/
|
||||
protected function assertErrorMessages($messages) {
|
||||
$element = $this->xpath('//div[@class = "form-item--error-message"]/strong');
|
||||
$this->assertIdentical(count($messages), count($element));
|
||||
|
||||
$error_links = [];
|
||||
foreach ($messages as $delta => $message) {
|
||||
// Ensure the message appears in the correct place.
|
||||
if (!isset($element[$delta])) {
|
||||
$this->fail(format_string('The error message for the "@title" element with key "@key" was not found.', ['@title' => $message['title'], '@key' => $message['key']]));
|
||||
}
|
||||
else {
|
||||
$this->assertIdentical($message['message'], (string) $element[$delta]);
|
||||
}
|
||||
|
||||
// Gather the element for checking the jump link section.
|
||||
$error_links[] = \Drupal::l($message['title'], Url::fromRoute('<none>', [], ['fragment' => 'edit-' . str_replace('_', '-', $message['key']), 'external' => TRUE]));
|
||||
}
|
||||
$top_message = \Drupal::translation()->formatPlural(count($error_links), '1 error has been found:', '@count errors have been found:');
|
||||
$this->assertRaw($top_message);
|
||||
foreach ($error_links as $error_link) {
|
||||
$this->assertRaw($error_link);
|
||||
}
|
||||
$this->assertNoText('An illegal choice has been detected. Please contact the site administrator.');
|
||||
$this->assertNoText(t('An illegal choice has been detected. Please contact the site administrator.'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\Tests\HttpKernel\HeadersResponseCodeRenderTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\HttpKernel;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests rendering headers and response codes.
|
||||
*
|
||||
* @group Routing
|
||||
*/
|
||||
class HeadersResponseCodeRenderTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('httpkernel_test');
|
||||
|
||||
/**
|
||||
* Tests the rendering of an array-based header and response code.
|
||||
*/
|
||||
public function testHeaderResponseCode() {
|
||||
$this->drupalGet('/httpkernel-test/teapot');
|
||||
$this->assertResponse(418);
|
||||
$this->assertHeader('X-Test-Teapot', 'Teapot Mode Active');
|
||||
$this->assertHeader('X-Test-Teapot-Replace', 'Teapot replaced');
|
||||
$this->assertHeader('X-Test-Teapot-No-Replace', 'This value is not replaced,This one is added');
|
||||
}
|
||||
|
||||
}
|
|
@ -8,8 +8,8 @@
|
|||
namespace Drupal\system\Tests\Image;
|
||||
|
||||
use Drupal\Core\Image\ImageInterface;
|
||||
use \Drupal\simpletest\KernelTestBase;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests that core image manipulations work properly: scale, resize, rotate,
|
||||
|
@ -278,9 +278,19 @@ class ToolkitGdTest extends KernelTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
// Store the original GD resource.
|
||||
$old_res = $toolkit->getResource();
|
||||
|
||||
// Perform our operation.
|
||||
$image->apply($values['function'], $values['arguments']);
|
||||
|
||||
// If the operation replaced the resource, check that the old one has
|
||||
// been destroyed.
|
||||
$new_res = $toolkit->getResource();
|
||||
if ($new_res !== $old_res) {
|
||||
$this->assertFalse(is_resource($old_res), SafeMarkup::format("'%operation' destroyed the original resource.", ['%operation' => $values['function']]));
|
||||
}
|
||||
|
||||
// To keep from flooding the test with assert values, make a general
|
||||
// value for whether each group of values fail.
|
||||
$correct_dimensions_real = TRUE;
|
||||
|
@ -389,7 +399,7 @@ class ToolkitGdTest extends KernelTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
// Test failures of CreateNew.
|
||||
// Test failures of the 'create_new' operation.
|
||||
$image = $this->imageFactory->get();
|
||||
$image->createNew(-50, 20);
|
||||
$this->assertFalse($image->isValid(), 'CreateNew with negative width fails.');
|
||||
|
@ -401,6 +411,30 @@ class ToolkitGdTest extends KernelTestBase {
|
|||
$this->assertTrue($image->isValid(), 'CreateNew with valid arguments validates the Image.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that GD resources are freed from memory.
|
||||
*/
|
||||
public function testResourceDestruction() {
|
||||
// Test that an Image object going out of scope releases its GD resource.
|
||||
$image = $this->imageFactory->get(drupal_get_path('module', 'simpletest') . '/files/image-test.png');
|
||||
$res = $image->getToolkit()->getResource();
|
||||
$this->assertTrue(is_resource($res), 'Successfully loaded image resource.');
|
||||
$image = NULL;
|
||||
$this->assertFalse(is_resource($res), 'Image resource was destroyed after losing scope.');
|
||||
|
||||
// Test that 'create_new' operation does not leave orphaned GD resources.
|
||||
$image = $this->imageFactory->get(drupal_get_path('module', 'simpletest') . '/files/image-test.png');
|
||||
$old_res = $image->getToolkit()->getResource();
|
||||
// Check if resource has been created successfully.
|
||||
$this->assertTrue(is_resource($old_res));
|
||||
$image->createNew(20, 20);
|
||||
$new_res = $image->getToolkit()->getResource();
|
||||
// Check if the original resource has been destroyed.
|
||||
$this->assertFalse(is_resource($old_res));
|
||||
// Check if a new resource has been created successfully.
|
||||
$this->assertTrue(is_resource($new_res));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests loading an image whose transparent color index is out of range.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\Tests\Installer\ConfigAfterInstallerTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\Installer;
|
||||
|
||||
use Drupal\Core\Config\FileStorage;
|
||||
use Drupal\Core\Config\InstallStorage;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
use Drupal\KernelTests\AssertConfigTrait;
|
||||
use Drupal\simpletest\InstallerTestBase;
|
||||
|
||||
/**
|
||||
* Provides a class for install profiles to check their installed config.
|
||||
*/
|
||||
abstract class ConfigAfterInstallerTestBase extends InstallerTestBase {
|
||||
|
||||
use AssertConfigTrait;
|
||||
|
||||
/**
|
||||
* Ensures that all the installed config looks like the exported one.
|
||||
*
|
||||
* @param array $skipped_config
|
||||
* An array of skipped config.
|
||||
*/
|
||||
protected function assertInstalledConfig(array $skipped_config) {
|
||||
/** @var \Drupal\Core\Config\StorageInterface $active_config_storage */
|
||||
$active_config_storage = $this->container->get('config.storage');
|
||||
/** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
|
||||
$config_manager = $this->container->get('config.manager');
|
||||
|
||||
$default_install_path = 'core/profiles/' . $this->profile . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY;
|
||||
$profile_config_storage = new FileStorage($default_install_path, StorageInterface::DEFAULT_COLLECTION);
|
||||
|
||||
foreach ($profile_config_storage->listAll() as $config_name) {
|
||||
$result = $config_manager->diff($profile_config_storage, $active_config_storage, $config_name);
|
||||
try {
|
||||
$this->assertConfigDiff($result, $config_name, $skipped_config);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->fail($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,9 +7,11 @@
|
|||
|
||||
namespace Drupal\system\Tests\Installer;
|
||||
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\simpletest\InstallerTestBase;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Tests the installer with an existing settings file but no install profile.
|
||||
|
@ -44,17 +46,12 @@ class InstallerExistingSettingsNoProfileTest extends InstallerTestBase {
|
|||
|
||||
// Pre-configure config directories.
|
||||
$this->settings['config_directories'] = array(
|
||||
CONFIG_ACTIVE_DIRECTORY => (object) array(
|
||||
'value' => conf_path() . '/files/config_active',
|
||||
'required' => TRUE,
|
||||
),
|
||||
CONFIG_STAGING_DIRECTORY => (object) array(
|
||||
'value' => conf_path() . '/files/config_staging',
|
||||
CONFIG_SYNC_DIRECTORY => (object) array(
|
||||
'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync',
|
||||
'required' => TRUE,
|
||||
),
|
||||
);
|
||||
mkdir($this->settings['config_directories'][CONFIG_ACTIVE_DIRECTORY]->value, 0777, TRUE);
|
||||
mkdir($this->settings['config_directories'][CONFIG_STAGING_DIRECTORY]->value, 0777, TRUE);
|
||||
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
|
|
@ -55,17 +55,12 @@ class InstallerExistingSettingsTest extends InstallerTestBase {
|
|||
$site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
|
||||
// Pre-configure config directories.
|
||||
$this->settings['config_directories'] = array(
|
||||
CONFIG_ACTIVE_DIRECTORY => (object) array(
|
||||
'value' => $site_path . '/files/config_active',
|
||||
'required' => TRUE,
|
||||
),
|
||||
CONFIG_STAGING_DIRECTORY => (object) array(
|
||||
'value' => $site_path . '/files/config_staging',
|
||||
CONFIG_SYNC_DIRECTORY => (object) array(
|
||||
'value' => $site_path . '/files/config_sync',
|
||||
'required' => TRUE,
|
||||
),
|
||||
);
|
||||
mkdir($this->settings['config_directories'][CONFIG_ACTIVE_DIRECTORY]->value, 0777, TRUE);
|
||||
mkdir($this->settings['config_directories'][CONFIG_STAGING_DIRECTORY]->value, 0777, TRUE);
|
||||
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\system\Tests\Installer;
|
||||
|
||||
use Drupal\Core\Language\LanguageManager;
|
||||
use Drupal\simpletest\InstallerTestBase;
|
||||
|
||||
/**
|
||||
|
@ -26,7 +27,7 @@ class InstallerLanguagePageTest extends InstallerTestBase {
|
|||
|
||||
// Check that all predefined languages show up with their native names.
|
||||
$this->drupalGet($GLOBALS['base_url'] . '/core/install.php');
|
||||
foreach (\Drupal::languageManager()->getStandardLanguageList() as $langcode => $names) {
|
||||
foreach (LanguageManager::getStandardLanguageList() as $langcode => $names) {
|
||||
$this->assertOption('edit-langcode', $langcode);
|
||||
$this->assertRaw('>' . $names[1] . '<');
|
||||
}
|
||||
|
|
|
@ -40,6 +40,41 @@ class InstallerTest extends InstallerTestBase {
|
|||
// metatags as expected to the first page of the installer.
|
||||
$this->assertRaw('core/themes/seven/css/components/buttons.css');
|
||||
$this->assertRaw('<meta charset="utf-8" />');
|
||||
|
||||
// Assert that the expected title is present.
|
||||
$this->assertEqual('Choose language', $this->cssSelect('main h1')[0]);
|
||||
|
||||
parent::setUpLanguage();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpProfile() {
|
||||
// Assert that the expected title is present.
|
||||
$this->assertEqual('Select an installation profile', $this->cssSelect('main h1')[0]);
|
||||
|
||||
parent::setUpProfile();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpSettings() {
|
||||
// Assert that the expected title is present.
|
||||
$this->assertEqual('Database configuration', $this->cssSelect('main h1')[0]);
|
||||
|
||||
parent::setUpSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpSite() {
|
||||
// Assert that the expected title is present.
|
||||
$this->assertEqual('Configure site', $this->cssSelect('main h1')[0]);
|
||||
|
||||
parent::setUpSite();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ class InstallerTranslationTest extends InstallerTestBase {
|
|||
$edit = array('preprocess_css' => FALSE);
|
||||
$this->drupalPostForm('admin/config/development/performance', $edit, t('Save configuration'));
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertRaw('classy/css/layout.css');
|
||||
$this->assertRaw('classy/css/components/action-links.css');
|
||||
|
||||
// Verify the strings from the translation files were imported.
|
||||
$test_samples = ['Save and continue', 'Anonymous'];
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue