Update to Drupal 8.2.2. For more information, see https://www.drupal.org/project/drupal/releases/8.2.2
This commit is contained in:
parent
23ffed3665
commit
507b45a0ed
378 changed files with 11434 additions and 5542 deletions
core
.eslintrcMAINTAINERS.txt
includes
lib
Drupal.php
Drupal
Component/Utility
Core
Access
Ajax
Asset
Cache/Context
Database
Entity
EventSubscriber
Field
FieldItemListInterface.php
Plugin/Field
File
Form
Render/Element
Routing
Session
Template
Test
Utility
misc
modules
action/tests/src
aggregator/tests/src
Kernel/Plugin/migrate/source
Unit/Plugin/migrate/source
ban/tests/src
block
src
tests/src
block_content/tests/src
Kernel/Plugin/migrate/source
Unit/Plugin/migrate/source
block_place
book
src
tests/src
FunctionalJavascript
Kernel/Plugin/migrate/source/d6
Unit/Plugin/migrate/source/d6
ckeditor
src/Plugin/CKEditorPlugin
tests
modules
src/Kernel/Plugin/CKEditorPlugin
contact
migration_templates
src
tests/src
Kernel
Migrate/d6
Plugin/migrate/source
Unit/Plugin/migrate/source
content_moderation
src
tests/src
datetime/src
datetime_range
editor
field
migration_templates
src
tests
modules/field_test
src/Kernel
|
@ -80,7 +80,7 @@
|
|||
"space-infix-ops": 2,
|
||||
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||
"spaced-comment": [2, "always"],
|
||||
"strict": 2,
|
||||
"strict": [2, "function"],
|
||||
"yoda": [2, "never"],
|
||||
// Warnings.
|
||||
"max-nested-callbacks": [1, 3],
|
||||
|
|
|
@ -206,6 +206,8 @@ Entity API
|
|||
- Wolfgang Ziegler 'fago' https://www.drupal.org/u/fago
|
||||
- Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch
|
||||
- Sascha Grossenbacher 'Berdir' https://www.drupal.org/u/berdir
|
||||
- Francesco Placella 'plach' https://www.drupal.org/u/plach
|
||||
- Tobias Stöckler 'tstoeckler' https://www.drupal.org/u/tstoeckler
|
||||
|
||||
Extension API
|
||||
- ?
|
||||
|
@ -277,11 +279,13 @@ Migrate
|
|||
- Ben Dougherty 'benjy' https://www.drupal.org/u/benjy
|
||||
- Michael Anello 'ultimike' https://www.drupal.org/u/ultimike
|
||||
- Mike Ryan 'mikeryan' https://www.drupal.org/u/mikeryan
|
||||
- Vicki Spagnolo 'quietone' https://www.drupal.org/u/quietone
|
||||
|
||||
Migrate (Drupal)
|
||||
- Ben Dougherty 'benjy' https://www.drupal.org/u/benjy
|
||||
- Michael Anello 'ultimike' https://www.drupal.org/u/ultimike
|
||||
- Mike Ryan 'mikeryan' https://www.drupal.org/u/mikeryan
|
||||
- Vicki Spagnolo 'quietone' https://www.drupal.org/u/quietone
|
||||
|
||||
Menu
|
||||
- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner
|
||||
|
@ -366,11 +370,6 @@ Shortcut
|
|||
- Tobias Stöckler 'tstoeckler' https://www.drupal.org/u/tstoeckler
|
||||
- Jibran Ijaz 'jibran' https://www.drupal.org/u/jibran
|
||||
|
||||
Simpletest
|
||||
- Daniel F. Kudwien 'sun' https://www.drupal.org/u/sun
|
||||
- Sascha Grossenbacher 'Berdir' https://www.drupal.org/u/berdir
|
||||
- Alex Pott 'alexpott' https://www.drupal.org/u/alexpott
|
||||
|
||||
Stable
|
||||
- Scott Reeves 'Cottser' https://www.drupal.org/u/cottser
|
||||
|
||||
|
@ -394,12 +393,17 @@ Taxonomy
|
|||
Telephone
|
||||
- Dave Reid 'dave-reid' https://www.drupal.org/u/dave-reid
|
||||
|
||||
Testing framework
|
||||
- Alex Pott 'alexpott' https://www.drupal.org/u/alexpott
|
||||
- Sascha Grossenbacher 'Berdir' https://www.drupal.org/u/berdir
|
||||
- Klaus Purer 'klausi' https://www.drupal.org/u/klausi
|
||||
- Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner
|
||||
|
||||
Text Field
|
||||
- ?
|
||||
|
||||
Theme API
|
||||
- Alex Bronstein 'effulgentsia' https://www.drupal.org/u/effulgentsia
|
||||
- Scott Reeves 'Cottser' https://www.drupal.org/u/cottser
|
||||
- Fabian Franz 'Fabianx' https://www.drupal.org/u/fabianx
|
||||
- Joël Pittet 'joelpittet' https://www.drupal.org/u/joelpittet
|
||||
- Lauri Eskola 'lauriii' https://www.drupal.org/u/lauriii
|
||||
|
@ -523,7 +527,6 @@ participate in mentoring.
|
|||
- Lucas Hedding 'heddn' https://www.drupal.org/u/heddn
|
||||
- Valery Lourie 'valthebald' https://www.drupal.org/u/valthebald
|
||||
- Alina Mackenzie 'alimac' https://www.drupal.org/u/alimac
|
||||
- Chris McCafferty 'cilefen' https://www.drupal.org/u/cilefen
|
||||
- Jess Myrbo 'xjm' https://www.drupal.org/u/xjm
|
||||
- Andrea Soper 'ZenDoodles' https://www.drupal.org/u/zendoodles
|
||||
- Cathy Theys 'YesCT' https://www.drupal.org/u/yesct
|
||||
|
|
|
@ -511,8 +511,6 @@ function template_preprocess_form_element_label(&$variables) {
|
|||
$variables['title'] = ['#markup' => $element['#title']];
|
||||
}
|
||||
|
||||
$variables['attributes'] = array();
|
||||
|
||||
// Pass elements title_display to template.
|
||||
$variables['title_display'] = $element['#title_display'];
|
||||
|
||||
|
|
|
@ -930,27 +930,35 @@ function drupal_requirements_url($severity) {
|
|||
*/
|
||||
function drupal_check_profile($profile) {
|
||||
$info = install_profile_info($profile);
|
||||
|
||||
// Collect requirement testing results.
|
||||
$requirements = array();
|
||||
|
||||
// Performs an ExtensionDiscovery scan as the system module is unavailable and
|
||||
// we don't yet know where all the modules are located.
|
||||
// @todo Remove as part of https://www.drupal.org/node/2186491
|
||||
$listing = new ExtensionDiscovery(\Drupal::root());
|
||||
$module_list = $listing->scan('module');
|
||||
foreach ($info['dependencies'] as $module) {
|
||||
$file = \Drupal::root() . '/' . $module_list[$module]->getPath() . "/$module.install";
|
||||
if (is_file($file)) {
|
||||
require_once $file;
|
||||
}
|
||||
$function = $module . '_requirements';
|
||||
$drupal_root = \Drupal::root();
|
||||
$module_list = (new ExtensionDiscovery($drupal_root))->scan('module');
|
||||
|
||||
drupal_classloader_register($module, $module_list[$module]->getPath());
|
||||
if (function_exists($function)) {
|
||||
$requirements = array_merge($requirements, $function('install'));
|
||||
foreach ($info['dependencies'] as $module) {
|
||||
// If the module is in the module list we know it exists and we can continue
|
||||
// including and registering it.
|
||||
// @see \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory()
|
||||
if (isset($module_list[$module])) {
|
||||
$function = $module . '_requirements';
|
||||
$module_path = $module_list[$module]->getPath();
|
||||
$install_file = "$drupal_root/$module_path/$module.install";
|
||||
|
||||
if (is_file($install_file)) {
|
||||
require_once $install_file;
|
||||
}
|
||||
|
||||
drupal_classloader_register($module, $module_path);
|
||||
|
||||
if (function_exists($function)) {
|
||||
$requirements = array_merge($requirements, $function('install'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $requirements;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ class Drupal {
|
|||
/**
|
||||
* The current system version.
|
||||
*/
|
||||
const VERSION = '8.2.1';
|
||||
const VERSION = '8.2.2';
|
||||
|
||||
/**
|
||||
* Core API compatibility.
|
||||
|
|
|
@ -288,7 +288,6 @@ class Random {
|
|||
// Make a perfect circle in the image middle.
|
||||
$color = imagecolorallocate($im, rand(0, 255), rand(0, 255), rand(0, 255));
|
||||
$smaller_dimension = min($width, $height);
|
||||
$smaller_dimension = ($smaller_dimension % 2) ? $smaller_dimension : $smaller_dimension;
|
||||
imageellipse($im, $width / 2, $height / 2, $smaller_dimension, $smaller_dimension, $color);
|
||||
|
||||
$save_function = 'image' . ($extension == 'jpg' ? 'jpeg' : $extension);
|
||||
|
|
|
@ -97,12 +97,15 @@ class CsrfRequestHeaderAccessCheck implements AccessCheckInterface {
|
|||
&& $account->isAuthenticated()
|
||||
&& $this->sessionConfiguration->hasSession($request)
|
||||
) {
|
||||
if (!$request->headers->has('X-CSRF-Token')) {
|
||||
return AccessResult::forbidden()->setReason('X-CSRF-Token request header is missing')->setCacheMaxAge(0);
|
||||
}
|
||||
$csrf_token = $request->headers->get('X-CSRF-Token');
|
||||
// @todo Remove validate call using 'rest' in 8.3.
|
||||
// Kept here for sessions active during update.
|
||||
if (!$this->csrfToken->validate($csrf_token, self::TOKEN_KEY)
|
||||
&& !$this->csrfToken->validate($csrf_token, 'rest')) {
|
||||
return AccessResult::forbidden()->setReason('X-CSRF-Token request header is missing')->setCacheMaxAge(0);
|
||||
return AccessResult::forbidden()->setReason('X-CSRF-Token request header is invalid')->setCacheMaxAge(0);
|
||||
}
|
||||
}
|
||||
// Let other access checkers decide if the request is legit.
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
use Drupal\Component\Render\PlainTextOutput;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command to open certain content in a dialog.
|
||||
*
|
||||
|
@ -69,6 +71,7 @@ class OpenDialogCommand implements CommandInterface, CommandWithAttachedAssetsIn
|
|||
* populated automatically from the current request.
|
||||
*/
|
||||
public function __construct($selector, $title, $content, array $dialog_options = array(), $settings = NULL) {
|
||||
$title = PlainTextOutput::renderFromHtml($title);
|
||||
$dialog_options += array('title' => $title);
|
||||
$this->selector = $selector;
|
||||
$this->content = $content;
|
||||
|
|
|
@ -214,7 +214,7 @@ class AssetResolver implements AssetResolverInterface {
|
|||
// hook_library_info_alter(). Additionally add the current language to
|
||||
// support translation of JavaScript files via hook_js_alter().
|
||||
$libraries_to_load = $this->getLibrariesToLoad($assets);
|
||||
$cid = 'js:' . $theme_info->getName() . ':' . $this->languageManager->getCurrentLanguage()->getId() . ':' . Crypt::hashBase64(serialize($libraries_to_load) . serialize($assets->getLibraries())) . (int) (count($assets->getSettings()) > 0) . (int) $optimize;
|
||||
$cid = 'js:' . $theme_info->getName() . ':' . $this->languageManager->getCurrentLanguage()->getId() . ':' . Crypt::hashBase64(serialize($libraries_to_load)) . (int) (count($assets->getSettings()) > 0) . (int) $optimize;
|
||||
|
||||
if ($cached = $this->cache->get($cid)) {
|
||||
list($js_assets_header, $js_assets_footer, $settings, $settings_in_header) = $cached->data;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Drupal\Core\Cache\Context;
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
|
||||
/**
|
||||
* Defines the SessionCacheContext service, for "per session" caching.
|
||||
*
|
||||
|
@ -20,7 +22,8 @@ class SessionCacheContext extends RequestStackCacheContextBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
return $this->requestStack->getCurrentRequest()->getSession()->getId();
|
||||
$sid = $this->requestStack->getCurrentRequest()->getSession()->getId();
|
||||
return Crypt::hashBase64($sid);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ class Schema extends DatabaseSchema {
|
|||
// By default, MySQL uses the default collation for new tables, which is
|
||||
// 'utf8mb4_general_ci' for utf8mb4. If an alternate collation has been
|
||||
// set, it needs to be explicitly specified.
|
||||
// @see DatabaseConnection_mysql
|
||||
// @see \Drupal\Core\Database\Driver\mysql\Schema
|
||||
if (!empty($info['collation'])) {
|
||||
$sql .= ' COLLATE ' . $info['collation'];
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ class Schema extends DatabaseSchema {
|
|||
/**
|
||||
* A cache of information about blob columns and sequences of tables.
|
||||
*
|
||||
* This is collected by DatabaseConnection_pgsql->queryTableInformation(),
|
||||
* by introspecting the database.
|
||||
* This is collected by Schema::queryTableInformation(), by introspecting the
|
||||
* database.
|
||||
*
|
||||
* @see \Drupal\Core\Database\Driver\pgsql\Schema::queryTableInformation()
|
||||
* @var array
|
||||
|
|
|
@ -306,7 +306,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
|||
return $this->fetchOptions['object'];
|
||||
case \PDO::FETCH_COLUMN:
|
||||
if (isset($this->columnNames[$this->fetchOptions['column']])) {
|
||||
return $this->currentRow[$k][$this->columnNames[$this->fetchOptions['column']]];
|
||||
return $this->currentRow[$this->columnNames[$this->fetchOptions['column']]];
|
||||
}
|
||||
else {
|
||||
return;
|
||||
|
|
|
@ -301,7 +301,7 @@ class EntityController implements ContainerInjectionInterface {
|
|||
* @param array $bundles
|
||||
* An array of bundle information.
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $bundle_entity_type
|
||||
* The ID of the bundle entity type.
|
||||
* The bundle entity type definition.
|
||||
*
|
||||
* @return array
|
||||
* The expanded array of bundle information.
|
||||
|
|
|
@ -236,7 +236,7 @@ class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayIn
|
|||
// Flag entity level violations.
|
||||
foreach ($violations->getEntityViolations() as $violation) {
|
||||
/** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */
|
||||
$form_state->setErrorByName('', $violation->getMessage());
|
||||
$form_state->setError($form, $violation->getMessage());
|
||||
}
|
||||
|
||||
$this->flagWidgetsErrorsFromViolations($violations, $form, $form_state);
|
||||
|
|
|
@ -166,7 +166,10 @@ class EntityResolverManager {
|
|||
list($entity_type) = explode('.', $entity_form, 2);
|
||||
}
|
||||
|
||||
if (isset($entity_type) && isset($this->getEntityTypes()[$entity_type])) {
|
||||
// Do not add parameter information if the route does not declare a
|
||||
// parameter in the first place. This is the case for add forms, for
|
||||
// example.
|
||||
if (isset($entity_type) && isset($this->getEntityTypes()[$entity_type]) && (strpos($route->getPath(), '{' . $entity_type . '}') !== FALSE)) {
|
||||
$parameter_definitions = $route->getOption('parameters') ?: array();
|
||||
|
||||
// First try to figure out whether there is already a parameter upcasting
|
||||
|
|
|
@ -358,11 +358,18 @@ use Drupal\node\Entity\NodeType;
|
|||
* \Drupal\Core\Entity\EntityType.
|
||||
*
|
||||
* @section sec_routes Entity routes
|
||||
* Entity routes, like other routes, are defined in *.routing.yml files; see
|
||||
* the @link routing Routing API @endlink topic for more information. Entities
|
||||
* may alternatively use an auto route provider class; there is an example of
|
||||
* this at the end of this section. If providing routes directly, here is a
|
||||
* typical entry, for the block configure form:
|
||||
* Entity routes can be defined in *.routing.yml files, like any other route:
|
||||
* see the @link routing Routing API @endlink topic for more information.
|
||||
* Another option for entity routes is to use a route provider class, and
|
||||
* reference it in the annotations on the entity class: see the end of this
|
||||
* section for an example.
|
||||
*
|
||||
* It's possible to use both a YAML file and a provider class for entity
|
||||
* routes, at the same time. Avoid duplicating route names between the two:
|
||||
* if a duplicate route name is found in both locations, the one in the YAML
|
||||
* file takes precedence; regardless, such duplication can be confusing.
|
||||
*
|
||||
* Here's an example YAML route specification, for the block configure form:
|
||||
* @code
|
||||
* entity.block.edit_form:
|
||||
* path: '/admin/structure/block/manage/{block}'
|
||||
|
@ -372,7 +379,7 @@ use Drupal\node\Entity\NodeType;
|
|||
* requirements:
|
||||
* _entity_access: 'block.update'
|
||||
* @endcode
|
||||
* Some notes:
|
||||
* Some notes on this example:
|
||||
* - path: The {block} in the path is a placeholder, which (for an entity) must
|
||||
* always take the form of {machine_name_of_entity_type}. In the URL, the
|
||||
* placeholder value will be the ID of an entity item. When the route is used,
|
||||
|
@ -389,19 +396,21 @@ use Drupal\node\Entity\NodeType;
|
|||
* "form" = {
|
||||
* "default" = "Drupal\block\BlockForm",
|
||||
* @endcode
|
||||
* - Instead of putting the routes for your entity in a *.routing.yml file, you
|
||||
* can instead use a route provider class.
|
||||
* \Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider provides canonical,
|
||||
* edit-form, and delete-form routes;
|
||||
* \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider provides the same
|
||||
* If instead of YAML you want to use a route provider class:
|
||||
* - \Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider provides canonical,
|
||||
* edit-form, and delete-form routes.
|
||||
* - \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider provides the same
|
||||
* routes, set up to use the administrative theme for edit and delete pages.
|
||||
* You can also create your own class. To use a route provider class, add
|
||||
* lines like the following to your entity annotation:
|
||||
* @code
|
||||
* handlers = {
|
||||
* "route_provider" = {
|
||||
* "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
|
||||
* @endcode
|
||||
* - You can also create your own class, extending one of these two classes if
|
||||
* you only want to modify their behaviour slightly.
|
||||
*
|
||||
* To register any route provider class, add lines like the following to your
|
||||
* entity class annotation:
|
||||
* @code
|
||||
* handlers = {
|
||||
* "route_provider" = {
|
||||
* "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
|
||||
* @endcode
|
||||
*
|
||||
* @section bundle Defining a content entity bundle
|
||||
* For entity types that use bundles, such as Node (bundles are content types)
|
||||
|
|
|
@ -20,7 +20,7 @@ class PathRootsSubscriber implements EventSubscriberInterface {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pathRoots;
|
||||
protected $pathRoots = [];
|
||||
|
||||
/**
|
||||
* The state key value store.
|
||||
|
@ -58,7 +58,7 @@ class PathRootsSubscriber implements EventSubscriberInterface {
|
|||
*/
|
||||
public function onRouteFinished() {
|
||||
$this->state->set('router.path_roots', array_keys($this->pathRoots));
|
||||
unset($this->pathRoots);
|
||||
$this->pathRoots = [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,8 @@ use Drupal\Core\TypedData\ListInterface;
|
|||
*
|
||||
* When implementing this interface which extends Traversable, make sure to list
|
||||
* IteratorAggregate or Iterator before this interface in the implements clause.
|
||||
*
|
||||
* @see \Drupal\Core\Field\FieldItemInterface
|
||||
*/
|
||||
interface FieldItemListInterface extends ListInterface, AccessibleInterface {
|
||||
|
||||
|
|
|
@ -268,7 +268,26 @@ class EntityReferenceItem extends FieldItemBase implements OptionsProviderInterf
|
|||
*/
|
||||
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
|
||||
$manager = \Drupal::service('plugin.manager.entity_reference_selection');
|
||||
if ($referenceable = $manager->getSelectionHandler($field_definition)->getReferenceableEntities()) {
|
||||
|
||||
// Instead of calling $manager->getSelectionHandler($field_definition)
|
||||
// replicate the behavior to be able to override the sorting settings.
|
||||
$options = array(
|
||||
'target_type' => $field_definition->getFieldStorageDefinition()->getSetting('target_type'),
|
||||
'handler' => $field_definition->getSetting('handler'),
|
||||
'handler_settings' => $field_definition->getSetting('handler_settings') ?: array(),
|
||||
'entity' => NULL,
|
||||
);
|
||||
|
||||
$entity_type = \Drupal::entityManager()->getDefinition($options['target_type']);
|
||||
$options['handler_settings']['sort'] = [
|
||||
'field' => $entity_type->getKey('id'),
|
||||
'direction' => 'DESC',
|
||||
];
|
||||
$selection_handler = $manager->getInstance($options);
|
||||
|
||||
// Select a random number of references between the last 50 referenceable
|
||||
// entities created.
|
||||
if ($referenceable = $selection_handler->getReferenceableEntities(NULL, 'CONTAINS', 50)) {
|
||||
$group = array_rand($referenceable);
|
||||
$values['target_id'] = array_rand($referenceable[$group]);
|
||||
return $values;
|
||||
|
|
|
@ -87,11 +87,14 @@ class EntityReferenceAutocompleteWidget extends WidgetBase {
|
|||
$entity = $items->getEntity();
|
||||
$referenced_entities = $items->referencedEntities();
|
||||
|
||||
// Append the match operation to the selection settings.
|
||||
$selection_settings = $this->getFieldSetting('handler_settings') + ['match_operator' => $this->getSetting('match_operator')];
|
||||
|
||||
$element += array(
|
||||
'#type' => 'entity_autocomplete',
|
||||
'#target_type' => $this->getFieldSetting('target_type'),
|
||||
'#selection_handler' => $this->getFieldSetting('handler'),
|
||||
'#selection_settings' => $this->getFieldSetting('handler_settings'),
|
||||
'#selection_settings' => $selection_settings,
|
||||
// Entity reference field items are handling validation themselves via
|
||||
// the 'ValidReference' constraint.
|
||||
'#validate_reference' => FALSE,
|
||||
|
|
|
@ -181,8 +181,10 @@ class FileSystem implements FileSystemInterface {
|
|||
// If recursive, create each missing component of the parent directory
|
||||
// individually and set the mode explicitly to override the umask.
|
||||
if ($recursive) {
|
||||
// Ensure the path is using DIRECTORY_SEPARATOR.
|
||||
$uri = str_replace('/', DIRECTORY_SEPARATOR, $uri);
|
||||
// Ensure the path is using DIRECTORY_SEPARATOR, and trim off any trailing
|
||||
// slashes because they can throw off the loop when creating the parent
|
||||
// directories.
|
||||
$uri = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $uri), DIRECTORY_SEPARATOR);
|
||||
// Determine the components of the path.
|
||||
$components = explode(DIRECTORY_SEPARATOR, $uri);
|
||||
// If the filepath is absolute the first component will be empty as there
|
||||
|
|
|
@ -152,7 +152,7 @@ class ExtensionMimeTypeGuesser implements MimeTypeGuesserInterface {
|
|||
129 => 'application/x-iphone',
|
||||
130 => 'application/x-iso9660-image',
|
||||
131 => 'application/x-java-jnlp-file',
|
||||
132 => 'application/x-javascript',
|
||||
132 => 'application/javascript',
|
||||
133 => 'application/x-jmol',
|
||||
134 => 'application/x-kchart',
|
||||
135 => 'application/x-killustrator',
|
||||
|
|
|
@ -316,7 +316,7 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
|
|||
// In case the post request exceeds the configured allowed size
|
||||
// (post_max_size), the post request is potentially broken. Add some
|
||||
// protection against that and at the same time have a nice error message.
|
||||
if ($ajax_form_request && !isset($form_state->getUserInput()['form_id'])) {
|
||||
if ($ajax_form_request && !$request->request->has('form_id')) {
|
||||
throw new BrokenPostRequestException($this->getFileUploadMaxSize());
|
||||
}
|
||||
|
||||
|
@ -327,7 +327,9 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
|
|||
// then passed through
|
||||
// \Drupal\Core\Form\FormAjaxResponseBuilderInterface::buildResponse() to
|
||||
// build a proper AJAX response.
|
||||
if ($ajax_form_request && $form_state->isProcessingInput()) {
|
||||
// Only do this when the form ID matches, since there is no guarantee from
|
||||
// $ajax_form_request that it's an AJAX request for this particular form.
|
||||
if ($ajax_form_request && $form_state->isProcessingInput() && $request->request->get('form_id') == $form_id) {
|
||||
throw new FormAjaxException($form, $form_state);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ class Link extends RenderElement {
|
|||
/** @var \Drupal\Core\Utility\LinkGenerator $link_generator */
|
||||
$link_generator = \Drupal::service('link_generator');
|
||||
$generated_link = $link_generator->generate($element['#title'], $element['#url']->setOptions($options));
|
||||
$element['#markup'] = $generated_link->getGeneratedLink();
|
||||
$element['#markup'] = $generated_link;
|
||||
$generated_link->merge(BubbleableMetadata::createFromRenderArray($element))
|
||||
->applyTo($element);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ use Drupal\Component\Utility\Html as HtmlUtility;
|
|||
* '#header' => array($this->t('Name'), $this->t('Phone')),
|
||||
* );
|
||||
*
|
||||
* for ($i=1; $i<=4; $i++) {
|
||||
* for ($i = 1; $i <= 4; $i++) {
|
||||
* $form['contacts'][$i]['#attributes'] = array('class' => array('foo', 'baz'));
|
||||
* $form['contacts'][$i]['name'] = array(
|
||||
* '#type' => 'textfield',
|
||||
* '#title' => $this->t('Name'),
|
||||
|
@ -46,6 +47,11 @@ use Drupal\Component\Utility\Html as HtmlUtility;
|
|||
* '#title_display' => 'invisible',
|
||||
* );
|
||||
* }
|
||||
*
|
||||
* $form['contacts'][]['colspan_example'] = array(
|
||||
* '#plain_text' => 'Colspan Example',
|
||||
* '#wrapper_attributes' => array('colspan' => 2, 'class' => array('foo', 'bar')),
|
||||
* );
|
||||
* @endcode
|
||||
* @see \Drupal\Core\Render\Element\Tableselect
|
||||
*
|
||||
|
|
|
@ -42,7 +42,12 @@ class ContentTypeHeaderMatcher implements RouteFilterInterface {
|
|||
// We do not throw a
|
||||
// \Symfony\Component\Routing\Exception\ResourceNotFoundException here
|
||||
// because we don't want to return a 404 status code, but rather a 415.
|
||||
throw new UnsupportedMediaTypeHttpException('No route found that matches "Content-Type: ' . $request->headers->get('Content-Type') . '"');
|
||||
if (!$request->headers->has('Content-Type')) {
|
||||
throw new UnsupportedMediaTypeHttpException('No "Content-Type" request header specified');
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedMediaTypeHttpException('No route found that matches "Content-Type: ' . $request->headers->get('Content-Type') . '"');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -257,7 +257,8 @@ class SessionManager extends NativeSessionStorage implements SessionManagerInter
|
|||
// Unset the session cookies.
|
||||
$session_name = $this->getName();
|
||||
$cookies = $this->requestStack->getCurrentRequest()->cookies;
|
||||
if ($cookies->has($session_name)) {
|
||||
// setcookie() can only be called when headers are not yet sent.
|
||||
if ($cookies->has($session_name) && !headers_sent()) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie($session_name, '', REQUEST_TIME - 3600, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
|
||||
$cookies->remove($session_name);
|
||||
|
|
|
@ -8,6 +8,7 @@ use Drupal\Core\Cache\CacheableDependencyInterface;
|
|||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Render\AttachmentsInterface;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Drupal\Core\Render\Markup;
|
||||
use Drupal\Core\Render\RenderableInterface;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\Routing\UrlGeneratorInterface;
|
||||
|
@ -273,6 +274,11 @@ class TwigExtension extends \Twig_Extension {
|
|||
}
|
||||
$url->setOption('attributes', $attributes);
|
||||
}
|
||||
// The text has been processed by twig already, convert it to a safe object
|
||||
// for the render system.
|
||||
if ($text instanceof \Twig_Markup) {
|
||||
$text = Markup::create($text);
|
||||
}
|
||||
$build = [
|
||||
'#type' => 'link',
|
||||
'#title' => $text,
|
||||
|
|
63
core/lib/Drupal/Core/Test/TestStatus.php
Normal file
63
core/lib/Drupal/Core/Test/TestStatus.php
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Test;
|
||||
|
||||
/**
|
||||
* Consolidates test result status information.
|
||||
*
|
||||
* For our test runners, a $status of 0 = passed test, 1 = failed test,
|
||||
* 2 = exception, >2 indicates segfault timeout, or other type of system
|
||||
* failure.
|
||||
*/
|
||||
class TestStatus {
|
||||
|
||||
/**
|
||||
* Signify that the test result was a passed test.
|
||||
*/
|
||||
const PASS = 0;
|
||||
|
||||
/**
|
||||
* Signify that the test result was a failed test.
|
||||
*/
|
||||
const FAIL = 1;
|
||||
|
||||
/**
|
||||
* Signify that the test result was an exception or code error.
|
||||
*
|
||||
* This means that the test runner was able to exit and report an error.
|
||||
*/
|
||||
const EXCEPTION = 2;
|
||||
|
||||
/**
|
||||
* Signify a system error where the test runner was unable to complete.
|
||||
*
|
||||
* Note that SYSTEM actually represents the lowest value of system errors, and
|
||||
* the returned value could be as high as 127. Since that's the case, this
|
||||
* constant should be used for range comparisons, and not just for equality.
|
||||
*
|
||||
* @see http://php.net/manual/en/pcntl.constants.php
|
||||
*/
|
||||
const SYSTEM = 3;
|
||||
|
||||
/**
|
||||
* Turns a status code into a human-readable string.
|
||||
*
|
||||
* @param int $status
|
||||
* A test runner return code.
|
||||
*
|
||||
* @return string
|
||||
* The human-readable version of the status code.
|
||||
*/
|
||||
public static function label($status) {
|
||||
$statusMap = [
|
||||
static::PASS => 'pass',
|
||||
static::FAIL => 'fail',
|
||||
static::EXCEPTION => 'exception',
|
||||
static::SYSTEM => 'error',
|
||||
];
|
||||
// For status 3 and higher, we want 'error.'
|
||||
$label = $statusMap[$status > static::SYSTEM ? static::SYSTEM : $status];
|
||||
return $label;
|
||||
}
|
||||
|
||||
}
|
|
@ -31,7 +31,7 @@ interface LinkGeneratorInterface {
|
|||
* This keeps the context of the link title ('settings' in the example) for
|
||||
* translators.
|
||||
*
|
||||
* @param string|array $text
|
||||
* @param string|array|\Drupal\Component\Render\MarkupInterface $text
|
||||
* The link text for the anchor tag as a translated string or render array.
|
||||
* Strings will be sanitized automatically. If you need to output HTML in
|
||||
* the link text, use a render array or an already sanitized string such as
|
||||
|
|
|
@ -165,7 +165,7 @@
|
|||
var placement = $el.offset()[horizontal ? 'left' : 'top'];
|
||||
// Subtract scroll distance from placement to get the distance
|
||||
// to the edge of the viewport.
|
||||
placement -= window['scroll' + (horizontal ? 'X' : 'Y')] || document.documentElement['scroll' + (horizontal) ? 'Left' : 'Top'] || 0;
|
||||
placement -= window['scroll' + (horizontal ? 'X' : 'Y')] || document.documentElement['scroll' + (horizontal ? 'Left' : 'Top')] || 0;
|
||||
// Find the displacement value according to the edge.
|
||||
switch (edge) {
|
||||
// Left and top elements displace as a sum of their own offset value
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\action\Kernel\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests actions source plugin.
|
||||
*
|
||||
* @covers \Drupal\action\Plugin\migrate\source\Action
|
||||
* @group action
|
||||
*/
|
||||
class ActionTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['action', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0][0]['actions'] = [
|
||||
[
|
||||
'aid' => 'Redirect to node list page',
|
||||
'type' => 'system',
|
||||
'callback' => 'system_goto_action',
|
||||
'parameters' => 'a:1:{s:3:"url";s:4:"node";}',
|
||||
'description' => 'Redirect to node list page',
|
||||
],
|
||||
[
|
||||
'aid' => 'Test notice email',
|
||||
'type' => 'system',
|
||||
'callback' => 'system_send_email_action',
|
||||
'parameters' => 'a:3:{s:9:"recipient";s:7:"%author";s:7:"subject";s:4:"Test";s:7:"message";s:4:"Test',
|
||||
'description' => 'Test notice email',
|
||||
],
|
||||
[
|
||||
'aid' => 'comment_publish_action',
|
||||
'type' => 'comment',
|
||||
'callback' => 'comment_publish_action',
|
||||
'parameters' => NULL,
|
||||
'description' => NULL,
|
||||
],
|
||||
[
|
||||
'aid' => 'node_publish_action',
|
||||
'type' => 'comment',
|
||||
'callback' => 'node_publish_action',
|
||||
'parameters' => NULL,
|
||||
'description' => NULL,
|
||||
],
|
||||
];
|
||||
// The expected results are identical to the source data.
|
||||
$tests[0][1] = $tests[0][0]['actions'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\action\Unit\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests actions source plugin.
|
||||
*
|
||||
* @group action
|
||||
*/
|
||||
class ActionTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
// The plugin system is not working during unit testing so the source plugin
|
||||
// class needs to be manually specified.
|
||||
const PLUGIN_CLASS = 'Drupal\action\Plugin\migrate\source\Action';
|
||||
|
||||
// The fake Migration configuration entity.
|
||||
protected $migrationConfiguration = array(
|
||||
// The ID of the entity, can be any string.
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'action',
|
||||
),
|
||||
);
|
||||
|
||||
// We need to set up the database contents; it's easier to do that below.
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'aid' => 'Redirect to node list page',
|
||||
'type' => 'system',
|
||||
'callback' => 'system_goto_action',
|
||||
'parameters' => 'a:1:{s:3:"url";s:4:"node";}',
|
||||
'description' => 'Redirect to node list page',
|
||||
),
|
||||
array(
|
||||
'aid' => 'Test notice email',
|
||||
'type' => 'system',
|
||||
'callback' => 'system_send_email_action',
|
||||
'parameters' => 'a:3:{s:9:"recipient";s:7:"%author";s:7:"subject";s:4:"Test";s:7:"message";s:4:"Test',
|
||||
'description' => 'Test notice email',
|
||||
),
|
||||
array(
|
||||
'aid' => 'comment_publish_action',
|
||||
'type' => 'comment',
|
||||
'callback' => 'comment_publish_action',
|
||||
'parameters' => NULL,
|
||||
'description' => NULL,
|
||||
),
|
||||
array(
|
||||
'aid' => 'node_publish_action',
|
||||
'type' => 'comment',
|
||||
'callback' => 'node_publish_action',
|
||||
'parameters' => NULL,
|
||||
'description' => NULL,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['actions'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\aggregator\Kernel\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 aggregator feed source plugin.
|
||||
*
|
||||
* @covers \Drupal\aggregator\Plugin\migrate\source\AggregatorFeed
|
||||
* @group aggregator
|
||||
*/
|
||||
class AggregatorFeedTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['aggregator', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0]['database']['aggregator_feed'] = [
|
||||
[
|
||||
'fid' => 1,
|
||||
'title' => 'feed title 1',
|
||||
'url' => 'http://example.com/feed.rss',
|
||||
'refresh' => 900,
|
||||
'checked' => 0,
|
||||
'link' => 'http://example.com',
|
||||
'description' => 'A vague description',
|
||||
'image' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
'block' => 5,
|
||||
],
|
||||
[
|
||||
'fid' => 2,
|
||||
'title' => 'feed title 2',
|
||||
'url' => 'http://example.net/news.rss',
|
||||
'refresh' => 1800,
|
||||
'checked' => 0,
|
||||
'link' => 'http://example.net',
|
||||
'description' => 'An even more vague description',
|
||||
'image' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
'block' => 5,
|
||||
],
|
||||
];
|
||||
// The expected results are identical to the source data.
|
||||
$tests[0]['expected_results'] = $tests[0]['database']['aggregator_feed'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\aggregator\Kernel\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests aggregator item source plugin.
|
||||
*
|
||||
* @covers \Drupal\aggregator\Plugin\migrate\source\AggregatorItem
|
||||
* @group aggregator
|
||||
*/
|
||||
class AggregatorItemTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['aggregator', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0]['database']['aggregator_item'] = [
|
||||
[
|
||||
'iid' => 1,
|
||||
'fid' => 1,
|
||||
'title' => 'This (three) weeks in Drupal Core - January 10th 2014',
|
||||
'link' => 'https://groups.drupal.org/node/395218',
|
||||
'author' => 'larowlan',
|
||||
'description' => "<h2 id='new'>What's new with Drupal 8?</h2>",
|
||||
'timestamp' => 1389297196,
|
||||
'guid' => '395218 at https://groups.drupal.org',
|
||||
],
|
||||
];
|
||||
// The expected results are identical to the source data.
|
||||
$tests[0]['expected_results'] = $tests[0]['database']['aggregator_item'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\aggregator\Unit\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests aggregator item source plugin.
|
||||
*
|
||||
* @group aggregator
|
||||
*/
|
||||
class AggregatorItemTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\aggregator\Plugin\migrate\source\AggregatorItem';
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'aggregator_item',
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'iid' => 1,
|
||||
'fid' => 1,
|
||||
'title' => 'This (three) weeks in Drupal Core - January 10th 2014',
|
||||
'link' => 'https://groups.drupal.org/node/395218',
|
||||
'author' => 'larowlan',
|
||||
'description' => "<h2 id='new'>What's new with Drupal 8?</h2>",
|
||||
'timestamp' => 1389297196,
|
||||
'guid' => '395218 at https://groups.drupal.org',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['aggregator_item'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\aggregator\Unit\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests D6 aggregator feed source plugin.
|
||||
*
|
||||
* @group aggregator
|
||||
*/
|
||||
class AggregatorFeedTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\aggregator\Plugin\migrate\source\AggregatorFeed';
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'd6_aggregator_feed',
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'fid' => 1,
|
||||
'title' => 'feed title 1',
|
||||
'url' => 'http://example.com/feed.rss',
|
||||
'refresh' => 900,
|
||||
'checked' => 0,
|
||||
'link' => 'http://example.com',
|
||||
'description' => 'A vague description',
|
||||
'image' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
'block' => 5,
|
||||
),
|
||||
array(
|
||||
'fid' => 2,
|
||||
'title' => 'feed title 2',
|
||||
'url' => 'http://example.net/news.rss',
|
||||
'refresh' => 1800,
|
||||
'checked' => 0,
|
||||
'link' => 'http://example.net',
|
||||
'description' => 'An even more vague description',
|
||||
'image' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
'block' => 5,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['aggregator_feed'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\aggregator\Unit\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests D7 aggregator feed source plugin.
|
||||
*
|
||||
* @group aggregator
|
||||
*/
|
||||
class AggregatorFeedTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\aggregator\Plugin\migrate\source\AggregatorFeed';
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'd7_aggregator_feed',
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'fid' => 1,
|
||||
'title' => 'feed title 1',
|
||||
'url' => 'http://example.com/feed.rss',
|
||||
'refresh' => 900,
|
||||
'checked' => 0,
|
||||
'queued' => 0,
|
||||
'link' => 'http://example.com',
|
||||
'description' => 'A vague description',
|
||||
'image' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
'block' => 5,
|
||||
),
|
||||
array(
|
||||
'fid' => 2,
|
||||
'title' => 'feed title 2',
|
||||
'url' => 'http://example.net/news.rss',
|
||||
'refresh' => 1800,
|
||||
'checked' => 0,
|
||||
'queued' => 0,
|
||||
'link' => 'http://example.net',
|
||||
'description' => 'An even more vague description',
|
||||
'image' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
'block' => 5,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['aggregator_feed'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\ban\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D7 blocked_ip source plugin.
|
||||
*
|
||||
* @covers \Drupal\ban\Plugin\migrate\source\d7\BlockedIps
|
||||
* @group ban
|
||||
*/
|
||||
class BlockedIpsTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['ban', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0]['source_data']['blocked_ips'] = [
|
||||
[
|
||||
'iid' => 1,
|
||||
'ip' => '127.0.0.1',
|
||||
]
|
||||
];
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'ip' => '127.0.0.1',
|
||||
],
|
||||
];
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\ban\Unit\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests D7 blocked_ip source plugin.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\ban\Plugin\migrate\source\d7\BlockedIps
|
||||
* @group ban
|
||||
*/
|
||||
class BlockedIpsTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\ban\Plugin\migrate\source\d7\BlockedIps';
|
||||
|
||||
protected $migrationConfiguration = [
|
||||
'id' => 'test',
|
||||
'source' => [
|
||||
'plugin' => 'd7_blocked_ips',
|
||||
],
|
||||
];
|
||||
|
||||
protected $expectedResults = [
|
||||
[
|
||||
'ip' => '127.0.0.1',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['blocked_ips'] = [
|
||||
[
|
||||
'iid' => 1,
|
||||
'ip' => '127.0.0.1',
|
||||
]
|
||||
];
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -237,7 +237,7 @@ class BlockForm extends EntityForm {
|
|||
// @todo Allow list of conditions to be configured in
|
||||
// https://www.drupal.org/node/2284687.
|
||||
$visibility = $this->entity->getVisibility();
|
||||
foreach ($this->manager->getDefinitions() as $condition_id => $definition) {
|
||||
foreach ($this->manager->getDefinitionsForContexts($form_state->getTemporaryValue('gathered_contexts')) as $condition_id => $definition) {
|
||||
// Don't display the current theme condition.
|
||||
if ($condition_id == 'current_theme') {
|
||||
continue;
|
||||
|
|
|
@ -8,7 +8,6 @@ use Drupal\Core\Controller\ControllerBase;
|
|||
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
|
||||
use Drupal\Core\Menu\LocalActionManagerInterface;
|
||||
use Drupal\Core\Plugin\Context\LazyContextRepository;
|
||||
use Drupal\Core\Routing\RedirectDestinationInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -47,13 +46,6 @@ class BlockLibraryController extends ControllerBase {
|
|||
*/
|
||||
protected $localActionManager;
|
||||
|
||||
/**
|
||||
* The redirect destination.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RedirectDestinationInterface
|
||||
*/
|
||||
protected $redirectDestination;
|
||||
|
||||
/**
|
||||
* Constructs a BlockLibraryController object.
|
||||
*
|
||||
|
@ -65,15 +57,12 @@ class BlockLibraryController extends ControllerBase {
|
|||
* The current route match.
|
||||
* @param \Drupal\Core\Menu\LocalActionManagerInterface $local_action_manager
|
||||
* The local action manager.
|
||||
* @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
|
||||
* The redirect destination.
|
||||
*/
|
||||
public function __construct(BlockManagerInterface $block_manager, LazyContextRepository $context_repository, RouteMatchInterface $route_match, LocalActionManagerInterface $local_action_manager, RedirectDestinationInterface $redirect_destination) {
|
||||
public function __construct(BlockManagerInterface $block_manager, LazyContextRepository $context_repository, RouteMatchInterface $route_match, LocalActionManagerInterface $local_action_manager) {
|
||||
$this->blockManager = $block_manager;
|
||||
$this->routeMatch = $route_match;
|
||||
$this->localActionManager = $local_action_manager;
|
||||
$this->contextRepository = $context_repository;
|
||||
$this->redirectDestination = $redirect_destination;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,8 +73,7 @@ class BlockLibraryController extends ControllerBase {
|
|||
$container->get('plugin.manager.block'),
|
||||
$container->get('context.repository'),
|
||||
$container->get('current_route_match'),
|
||||
$container->get('plugin.manager.menu.local_action'),
|
||||
$container->get('redirect.destination')
|
||||
$container->get('plugin.manager.menu.local_action')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -148,10 +136,6 @@ class BlockLibraryController extends ControllerBase {
|
|||
if (isset($weight)) {
|
||||
$links['add']['query']['weight'] = $weight;
|
||||
}
|
||||
$destination = $this->redirectDestination->get();
|
||||
if ($destination) {
|
||||
$links['add']['query']['destination'] = $destination;
|
||||
}
|
||||
$row['operations']['data'] = [
|
||||
'#type' => 'operations',
|
||||
'#links' => $links,
|
||||
|
|
|
@ -128,49 +128,6 @@ class BlockTest extends BlockTestBase {
|
|||
$this->assertNoText($title, 'Block was not displayed to anonymous users on the front page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding a block from the library page with a destination query string.
|
||||
*/
|
||||
public function testAddBlockFromLibrary() {
|
||||
$default_theme = $this->config('system.theme')->get('default');
|
||||
$help_url = Url::fromRoute('help.page', ['name' => 'block']);
|
||||
// Set up the request so we land on the block help page after creation.
|
||||
$options = [
|
||||
'query' => [
|
||||
'region' => 'sidebar_first',
|
||||
'destination' => $help_url->toString(),
|
||||
],
|
||||
];
|
||||
$this->drupalGet(Url::fromRoute('block.admin_library', ['theme' => $default_theme], $options));
|
||||
|
||||
$block_name = 'system_powered_by_block';
|
||||
$add_url = Url::fromRoute('block.admin_add', ['plugin_id' => $block_name, 'theme' => $default_theme]);
|
||||
$links = $this->xpath('//a[contains(@href, :href)]', [':href' => $add_url->toString()]);
|
||||
$this->assertEqual(1, count($links), 'Found one matching link');
|
||||
|
||||
list($path, $query_string) = explode('?', $links[0]['href'], 2);
|
||||
parse_str($query_string, $query_parts);
|
||||
$this->assertEqual(t('Place block'), (string) $links[0]);
|
||||
$this->assertEqual($help_url->toString(), $query_parts['destination'], 'Expected destination query string is in href');
|
||||
|
||||
// Create a random title for the block.
|
||||
$title = $this->randomMachineName(8);
|
||||
$block_id = strtolower($this->randomMachineName(8));
|
||||
$edit = [
|
||||
'id' => $block_id,
|
||||
'settings[label]' => $title,
|
||||
];
|
||||
// Create the block using the link parsed from the library page.
|
||||
$this->drupalPostForm($this->getAbsoluteUrl($links[0]['href']), $edit, t('Save block'));
|
||||
// Verify that we are redirected according to the original request.
|
||||
$this->assertUrl($help_url);
|
||||
|
||||
// Ensure that the block was created.
|
||||
/** @var \Drupal\block\BlockInterface $block */
|
||||
$block = Block::load($block_id);
|
||||
$this->assertEqual($title, $block->label(), 'Found the block with expected title.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding a block from the library page with a weight query string.
|
||||
*/
|
||||
|
|
|
@ -17,7 +17,7 @@ class BlockUiTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'block_test', 'help');
|
||||
public static $modules = array('block', 'block_test', 'help', 'condition_test');
|
||||
|
||||
protected $regions;
|
||||
|
||||
|
@ -248,6 +248,11 @@ class BlockUiTest extends WebTestBase {
|
|||
$this->drupalGet('');
|
||||
$this->assertText('No context mapping selected.');
|
||||
$this->assertNoText('User context found.');
|
||||
|
||||
// Tests that conditions with missing context are not displayed.
|
||||
$this->drupalGet('admin/structure/block/manage/testcontextawareblock');
|
||||
$this->assertNoRaw('No existing type');
|
||||
$this->assertNoFieldByXPath('//*[@name="visibility[condition_test_no_existing_type][negate]"]');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block\Kernel\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests block source plugin.
|
||||
*
|
||||
* @covers \Drupal\block\Plugin\migrate\source\Block
|
||||
* @group block
|
||||
*/
|
||||
class BlockTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['blocks'] = [
|
||||
[
|
||||
'bid' => 1,
|
||||
'module' => 'block',
|
||||
'delta' => '1',
|
||||
'theme' => 'garland',
|
||||
'status' => 1,
|
||||
'weight' => 0,
|
||||
'region' => 'left',
|
||||
'visibility' => 0,
|
||||
'pages' => '',
|
||||
'title' => 'Test Title 01',
|
||||
'cache' => -1,
|
||||
],
|
||||
[
|
||||
'bid' => 2,
|
||||
'module' => 'block',
|
||||
'delta' => '2',
|
||||
'theme' => 'garland',
|
||||
'status' => 1,
|
||||
'weight' => 5,
|
||||
'region' => 'right',
|
||||
'visibility' => 0,
|
||||
'pages' => '<front>',
|
||||
'title' => 'Test Title 02',
|
||||
'cache' => -1,
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['blocks_roles'] = [
|
||||
[
|
||||
'module' => 'block',
|
||||
'delta' => 1,
|
||||
'rid' => 2,
|
||||
],
|
||||
[
|
||||
'module' => 'block',
|
||||
'delta' => 2,
|
||||
'rid' => 2,
|
||||
],
|
||||
[
|
||||
'module' => 'block',
|
||||
'delta' => 2,
|
||||
'rid' => 100,
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['role'] = [
|
||||
[
|
||||
'rid' => 2,
|
||||
'name' => 'authenticated user',
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['system'] = [
|
||||
[
|
||||
'filename' => 'modules/system/system.module',
|
||||
'name' => 'system',
|
||||
'type' => 'module',
|
||||
'owner' => '',
|
||||
'status' => '1',
|
||||
'throttle' => '0',
|
||||
'bootstrap' => '0',
|
||||
'schema_version' => '6055',
|
||||
'weight' => '0',
|
||||
'info' => 'a:0:{}',
|
||||
]
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'bid' => 1,
|
||||
'module' => 'block',
|
||||
'delta' => '1',
|
||||
'theme' => 'garland',
|
||||
'status' => 1,
|
||||
'weight' => 0,
|
||||
'region' => 'left',
|
||||
'visibility' => 0,
|
||||
'pages' => '',
|
||||
'title' => 'Test Title 01',
|
||||
'cache' => -1,
|
||||
'roles' => [2]
|
||||
],
|
||||
[
|
||||
'bid' => 2,
|
||||
'module' => 'block',
|
||||
'delta' => '2',
|
||||
'theme' => 'garland',
|
||||
'status' => 1,
|
||||
'weight' => 5,
|
||||
'region' => 'right',
|
||||
'visibility' => 0,
|
||||
'pages' => '<front>',
|
||||
'title' => 'Test Title 02',
|
||||
'cache' => -1,
|
||||
'roles' => [2]
|
||||
],
|
||||
];
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block\Unit\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests block source plugin.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\block\Plugin\migrate\source\Block
|
||||
* @group block
|
||||
*/
|
||||
class BlockTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\block\Plugin\migrate\source\Block';
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'block',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Sample block instance query results from the source.
|
||||
*/
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'bid' => 1,
|
||||
'module' => 'block',
|
||||
'delta' => '1',
|
||||
'theme' => 'garland',
|
||||
'status' => 1,
|
||||
'weight' => 0,
|
||||
'region' => 'left',
|
||||
'visibility' => 0,
|
||||
'pages' => '',
|
||||
'title' => 'Test Title 01',
|
||||
'cache' => -1,
|
||||
'roles' => [2]
|
||||
),
|
||||
array(
|
||||
'bid' => 2,
|
||||
'module' => 'block',
|
||||
'delta' => '2',
|
||||
'theme' => 'garland',
|
||||
'status' => 1,
|
||||
'weight' => 5,
|
||||
'region' => 'right',
|
||||
'visibility' => 0,
|
||||
'pages' => '<front>',
|
||||
'title' => 'Test Title 02',
|
||||
'cache' => -1,
|
||||
'roles' => [2]
|
||||
),
|
||||
);
|
||||
/**
|
||||
* Sample block table.
|
||||
*/
|
||||
protected $expectedBlocks = array(
|
||||
array(
|
||||
'bid' => 1,
|
||||
'module' => 'block',
|
||||
'delta' => '1',
|
||||
'theme' => 'garland',
|
||||
'status' => 1,
|
||||
'weight' => 0,
|
||||
'region' => 'left',
|
||||
'visibility' => 0,
|
||||
'pages' => '',
|
||||
'title' => 'Test Title 01',
|
||||
'cache' => -1,
|
||||
),
|
||||
array(
|
||||
'bid' => 2,
|
||||
'module' => 'block',
|
||||
'delta' => '2',
|
||||
'theme' => 'garland',
|
||||
'status' => 1,
|
||||
'weight' => 5,
|
||||
'region' => 'right',
|
||||
'visibility' => 0,
|
||||
'pages' => '<front>',
|
||||
'title' => 'Test Title 02',
|
||||
'cache' => -1,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Sample block roles table.
|
||||
*/
|
||||
protected $expectedBlocksRoles = array(
|
||||
array(
|
||||
'module' => 'block',
|
||||
'delta' => 1,
|
||||
'rid' => 2,
|
||||
),
|
||||
array(
|
||||
'module' => 'block',
|
||||
'delta' => 2,
|
||||
'rid' => 2,
|
||||
),
|
||||
array(
|
||||
'module' => 'block',
|
||||
'delta' => 2,
|
||||
'rid' => 100,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Sample role table.
|
||||
*/
|
||||
protected $expectedRole = array(
|
||||
array(
|
||||
'rid' => 2,
|
||||
'name' => 'authenticated user',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Prepopulate database contents.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['blocks'] = $this->expectedBlocks;
|
||||
$this->databaseContents['blocks_roles'] = $this->expectedBlocksRoles;
|
||||
$this->databaseContents['role'] = $this->expectedRole;
|
||||
$this->databaseContents['system'] = array(
|
||||
array(
|
||||
'filename' => 'modules/system/system.module',
|
||||
'name' => 'system',
|
||||
'type' => 'module',
|
||||
'owner' => '',
|
||||
'status' => '1',
|
||||
'throttle' => '0',
|
||||
'bootstrap' => '0',
|
||||
'schema_version' => '6055',
|
||||
'weight' => '0',
|
||||
'info' => 'a:0:{}',
|
||||
)
|
||||
);
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 block boxes source plugin.
|
||||
*
|
||||
* @covers \Drupal\block_content\Plugin\migrate\source\d6\Box
|
||||
* @group block_content
|
||||
*/
|
||||
class BoxTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0]['source_data']['boxes'] = [
|
||||
[
|
||||
'bid' => 1,
|
||||
'body' => '<p>I made some custom content.</p>',
|
||||
'info' => 'Static Block',
|
||||
'format' => 1,
|
||||
],
|
||||
[
|
||||
'bid' => 2,
|
||||
'body' => '<p>I made some more custom content.</p>',
|
||||
'info' => 'Test Content',
|
||||
'format' => 1,
|
||||
],
|
||||
];
|
||||
// The expected results are identical to the source data.
|
||||
$tests[0]['expected_data'] = $tests[0]['source_data']['boxes'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests d7_block_custom source plugin.
|
||||
*
|
||||
* @covers \Drupal\block_content\Plugin\migrate\source\d7\BlockCustom
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockCustomTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0]['source_data']['block_custom'] = [
|
||||
[
|
||||
'bid' => '1',
|
||||
'body' => "I don't feel creative enough to write anything clever here.",
|
||||
'info' => 'Meh',
|
||||
'format' => 'filtered_html',
|
||||
],
|
||||
];
|
||||
// The expected results are identical to the source data.
|
||||
$tests[0]['expected_data'] = $tests[0]['source_data']['block_custom'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Unit\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests D6 block boxes source plugin.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BoxTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\block_content\Plugin\migrate\source\d6\Box';
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'd6_boxes',
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'bid' => 1,
|
||||
'body' => '<p>I made some custom content.</p>',
|
||||
'info' => 'Static Block',
|
||||
'format' => 1,
|
||||
),
|
||||
array(
|
||||
'bid' => 2,
|
||||
'body' => '<p>I made some more custom content.</p>',
|
||||
'info' => 'Test Content',
|
||||
'format' => 1,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Prepopulate contents with results.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['boxes'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Unit\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\block_content\Plugin\migrate\source\d7\BlockCustom;
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\block_content\Plugin\migrate\source\d7\BlockCustom
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockCustomTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = BlockCustom::class;
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'd7_block_custom',
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'bid' => '1',
|
||||
'body' => "I don't feel creative enough to write anything clever here.",
|
||||
'info' => 'Meh',
|
||||
'format' => 'filtered_html',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['block_custom'] = $this->expectedResults;
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@ function block_place_help($route_name, RouteMatchInterface $route_match) {
|
|||
$output = '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Place Blocks module allows you to place blocks from every page. For more information, see the <a href=":blocks-documentation">online documentation for the Place Blocks module</a>.', [':blocks-documentation' => 'https://www.drupal.org/documentation/modules/block_place/']) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<p>' . t('Block placement is specific to each theme on your site. This module allows you to place blocks in the context of your content pages') . '</p>';
|
||||
$output .= '<p>' . t('Block placement is specific to each theme on your site. This module allows you to place blocks in the context of your content pages.') . '</p>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,9 +156,12 @@ class BookNavigationBlock extends BlockBase implements ContainerFactoryPluginInt
|
|||
}
|
||||
}
|
||||
elseif ($current_bid) {
|
||||
// Only display this block when the user is browsing a book.
|
||||
$query = \Drupal::entityQuery('node');
|
||||
$nid = $query->condition('nid', $node->book['bid'], '=')->execute();
|
||||
// Only display this block when the user is browsing a book and do
|
||||
// not show unpublished books.
|
||||
$nid = \Drupal::entityQuery('node')
|
||||
->condition('nid', $node->book['bid'], '=')
|
||||
->condition('status', NODE_PUBLISHED)
|
||||
->execute();
|
||||
|
||||
// Only show the block if the user has view access for the top-level node.
|
||||
if ($nid) {
|
||||
|
|
|
@ -570,34 +570,6 @@ class BookTest extends WebTestBase {
|
|||
$this->assertEqual($child->id(), $second->book['bid'], '3rd-level child node is now second level when top-level node is deleted.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests re-ordering of books.
|
||||
*/
|
||||
public function testBookOrdering() {
|
||||
// Create new book.
|
||||
$this->createBook();
|
||||
$book = $this->book;
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$node1 = $this->createBookNode($book->id());
|
||||
$node2 = $this->createBookNode($book->id());
|
||||
$pid = $node1->book['nid'];
|
||||
|
||||
// Head to admin screen and attempt to re-order.
|
||||
$this->drupalGet('admin/structure/book/' . $book->id());
|
||||
$edit = array(
|
||||
"table[book-admin-{$node1->id()}][weight]" => 1,
|
||||
"table[book-admin-{$node2->id()}][weight]" => 2,
|
||||
// Put node 2 under node 1.
|
||||
"table[book-admin-{$node2->id()}][pid]" => $pid,
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save book pages'));
|
||||
// Verify weight was updated.
|
||||
$this->assertFieldByName("table[book-admin-{$node1->id()}][weight]", 1);
|
||||
$this->assertFieldByName("table[book-admin-{$node2->id()}][weight]", 2);
|
||||
$this->assertFieldByName("table[book-admin-{$node2->id()}][pid]", $pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests outline of a book.
|
||||
*/
|
||||
|
@ -752,4 +724,29 @@ class BookTest extends WebTestBase {
|
|||
$this->assertEqual($book_node->book['bid'], $this->book->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the book navigation block when book is unpublished.
|
||||
*
|
||||
* There was a fatal error with "Show block only on book pages" block mode.
|
||||
*/
|
||||
public function testBookNavigationBlockOnUnpublishedBook() {
|
||||
// Create a new book.
|
||||
$this->createBook();
|
||||
|
||||
// Create administrator user.
|
||||
$administratorUser = $this->drupalCreateUser(['administer blocks', 'administer nodes', 'bypass node access']);
|
||||
$this->drupalLogin($administratorUser);
|
||||
|
||||
// Enable the block with "Show block only on book pages" mode.
|
||||
$this->drupalPlaceBlock('book_navigation', ['block_mode' => 'book pages']);
|
||||
|
||||
// Unpublish book node.
|
||||
$edit = [];
|
||||
$this->drupalPostForm('node/' . $this->book->id() . '/edit', $edit, t('Save and unpublish'));
|
||||
|
||||
// Test node page.
|
||||
$this->drupalGet('node/' . $this->book->id());
|
||||
$this->assertText($this->book->label(), 'Unpublished book with "Show block only on book pages" book navigation settings.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\book\FunctionalJavascript;
|
||||
|
||||
use Behat\Mink\Exception\ExpectationException;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Tests Book javascript functionality.
|
||||
*
|
||||
* @group book
|
||||
*/
|
||||
class BookJavascriptTest extends JavascriptTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['book'];
|
||||
|
||||
/**
|
||||
* Tests re-ordering of books.
|
||||
*/
|
||||
public function testBookOrdering() {
|
||||
$book = Node::create([
|
||||
'type' => 'book',
|
||||
'title' => 'Book',
|
||||
'book' => ['bid' => 'new'],
|
||||
]);
|
||||
$book->save();
|
||||
$page1 = Node::create([
|
||||
'type' => 'book',
|
||||
'title' => '1st page',
|
||||
'book' => ['bid' => $book->id(), 'pid' => $book->id(), 'weight' => 0],
|
||||
]);
|
||||
$page1->save();
|
||||
$page2 = Node::create([
|
||||
'type' => 'book',
|
||||
'title' => '2nd page',
|
||||
'book' => ['bid' => $book->id(), 'pid' => $book->id(), 'weight' => 1],
|
||||
]);
|
||||
$page2->save();
|
||||
|
||||
// Head to admin screen and attempt to re-order.
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer book outlines']));
|
||||
$this->drupalGet('admin/structure/book/' . $book->id());
|
||||
|
||||
$page = $this->getSession()->getPage();
|
||||
|
||||
$weight_select1 = $page->findField("table[book-admin-{$page1->id()}][weight]");
|
||||
$weight_select2 = $page->findField("table[book-admin-{$page2->id()}][weight]");
|
||||
|
||||
// Check that rows weight selects are hidden.
|
||||
$this->assertFalse($weight_select1->isVisible());
|
||||
$this->assertFalse($weight_select2->isVisible());
|
||||
|
||||
// Check that '2nd page' row is heavier than '1st page' row.
|
||||
$this->assertGreaterThan($weight_select1->getValue(), $weight_select2->getValue());
|
||||
|
||||
// Check that '1st page' precedes the '2nd page'.
|
||||
$this->assertOrderInPage(['1st page', '2nd page']);
|
||||
|
||||
// Check that the 'unsaved changes' text is not present in the message area.
|
||||
$this->assertSession()->pageTextNotContains('You have unsaved changes.');
|
||||
|
||||
// Drag and drop the '1st page' row over the '2nd page' row.
|
||||
// @todo: Test also the reverse, '2nd page' over '1st page', when
|
||||
// https://www.drupal.org/node/2769825 is fixed.
|
||||
// @see https://www.drupal.org/node/2769825
|
||||
$dragged = $this->xpath("//tr[@data-drupal-selector='edit-table-book-admin-{$page1->id()}']//a[@class='tabledrag-handle']")[0];
|
||||
$target = $this->xpath("//tr[@data-drupal-selector='edit-table-book-admin-{$page2->id()}']//a[@class='tabledrag-handle']")[0];
|
||||
$dragged->dragTo($target);
|
||||
|
||||
// Give javascript some time to manipulate the DOM.
|
||||
$this->getSession()->wait(1000, 'jQuery(".tabledrag-changed-warning").is(":visible")');
|
||||
|
||||
// Check that the 'unsaved changes' text appeared in the message area.
|
||||
$this->assertSession()->pageTextContains('You have unsaved changes.');
|
||||
|
||||
// Check that '2nd page' page precedes the '1st page'.
|
||||
$this->assertOrderInPage(['2nd page', '1st page']);
|
||||
|
||||
$this->submitForm([], 'Save book pages');
|
||||
$this->assertSession()->pageTextContains(new FormattableMarkup('Updated book @book.', ['@book' => $book->getTitle()]));
|
||||
|
||||
// Check that page reordering was done in the backend for drag-n-drop.
|
||||
$page1 = Node::load($page1->id());
|
||||
$page2 = Node::load($page2->id());
|
||||
$this->assertGreaterThan($page2->book['weight'], $page1->book['weight']);
|
||||
|
||||
// Check again that '2nd page' is on top after form submit in the UI.
|
||||
$this->assertOrderInPage(['2nd page', '1st page']);
|
||||
|
||||
// Toggle row weight selects as visible.
|
||||
$page->findButton('Show row weights')->click();
|
||||
|
||||
// Check that rows weight selects are visible.
|
||||
$this->assertTrue($weight_select1->isVisible());
|
||||
$this->assertTrue($weight_select2->isVisible());
|
||||
|
||||
// Check that '1st page' row became heavier than '2nd page' row.
|
||||
$this->assertGreaterThan($weight_select2->getValue(), $weight_select1->getValue());
|
||||
|
||||
// Reverse again using the weight fields. Use the current values so the test
|
||||
// doesn't rely on knowing the values in the select boxes.
|
||||
$value1 = $weight_select1->getValue();
|
||||
$value2 = $weight_select2->getValue();
|
||||
$weight_select1->setValue($value2);
|
||||
$weight_select2->setValue($value1);
|
||||
|
||||
// Toggle row weight selects back to hidden.
|
||||
$page->findButton('Hide row weights')->click();
|
||||
|
||||
// Check that rows weight selects are hidden again.
|
||||
$this->assertFalse($weight_select1->isVisible());
|
||||
$this->assertFalse($weight_select2->isVisible());
|
||||
|
||||
$this->submitForm([], 'Save book pages');
|
||||
$this->assertSession()->pageTextContains(new FormattableMarkup('Updated book @book.', ['@book' => $book->getTitle()]));
|
||||
|
||||
// Check that the '1st page' is first again.
|
||||
$this->assertOrderInPage(['1st page', '2nd page']);
|
||||
|
||||
// Check that page reordering was done in the backend for manual weight
|
||||
// field usage.
|
||||
$page1 = Node::load($page1->id());
|
||||
$page2 = Node::load($page2->id());
|
||||
$this->assertGreaterThan($page2->book['weight'], $page1->book['weight']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that several pieces of markup are in a given order in the page.
|
||||
*
|
||||
* @param string[] $items
|
||||
* An ordered list of strings.
|
||||
*
|
||||
* @throws \Behat\Mink\Exception\ExpectationException
|
||||
* When any of the given string is not found.
|
||||
*
|
||||
* @todo Remove this once https://www.drupal.org/node/2817657 is committed.
|
||||
*/
|
||||
protected function assertOrderInPage(array $items) {
|
||||
$session = $this->getSession();
|
||||
$text = $session->getPage()->getHtml();
|
||||
$strings = [];
|
||||
foreach ($items as $item) {
|
||||
if (($pos = strpos($text, $item)) === FALSE) {
|
||||
throw new ExpectationException("Cannot find '$item' in the page", $session->getDriver());
|
||||
}
|
||||
$strings[$pos] = $item;
|
||||
}
|
||||
ksort($strings);
|
||||
$ordered = implode(', ', array_map(function ($item) {
|
||||
return "'$item'";
|
||||
}, $items));
|
||||
$this->assertSame($items, array_values($strings), "Found strings, ordered as: $ordered.");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\book\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* @covers \Drupal\book\Plugin\migrate\source\d6\Book
|
||||
* @group book
|
||||
*/
|
||||
class BookTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['book', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['book'] = [
|
||||
[
|
||||
'mlid' => '1',
|
||||
'nid' => '4',
|
||||
'bid' => '4',
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['menu_links'] = [
|
||||
[
|
||||
'menu_name' => 'book-toc-1',
|
||||
'mlid' => '1',
|
||||
'plid' => '0',
|
||||
'link_path' => 'node/4',
|
||||
'router_path' => 'node/%',
|
||||
'link_title' => 'Test top book title',
|
||||
'options' => 'a:0:{}',
|
||||
'module' => 'book',
|
||||
'hidden' => '0',
|
||||
'external' => '0',
|
||||
'has_children' => '1',
|
||||
'expanded' => '0',
|
||||
'weight' => '-10',
|
||||
'depth' => '1',
|
||||
'customized' => '0',
|
||||
'p1' => '1',
|
||||
'p2' => '0',
|
||||
'p3' => '0',
|
||||
'p4' => '0',
|
||||
'p5' => '0',
|
||||
'p6' => '0',
|
||||
'p7' => '0',
|
||||
'p8' => '0',
|
||||
'p9' => '0',
|
||||
'updated' => '0',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'nid' => '4',
|
||||
'bid' => '4',
|
||||
'mlid' => '1',
|
||||
'plid' => '0',
|
||||
'weight' => '-10',
|
||||
'p1' => '1',
|
||||
'p2' => '0',
|
||||
'p3' => '0',
|
||||
'p4' => '0',
|
||||
'p5' => '0',
|
||||
'p6' => '0',
|
||||
'p7' => '0',
|
||||
'p8' => '0',
|
||||
'p9' => '0',
|
||||
],
|
||||
];
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\book\Unit\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\book\Plugin\migrate\source\d6\Book;
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\book\Plugin\migrate\source\d6\Book
|
||||
* @group book
|
||||
*/
|
||||
class BookTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = Book::class;
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'd6_book',
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'nid' => '4',
|
||||
'bid' => '4',
|
||||
'mlid' => '1',
|
||||
'plid' => '0',
|
||||
'weight' => '-10',
|
||||
'p1' => '1',
|
||||
'p2' => '0',
|
||||
'p3' => '0',
|
||||
'p4' => '0',
|
||||
'p5' => '0',
|
||||
'p6' => '0',
|
||||
'p7' => '0',
|
||||
'p8' => '0',
|
||||
'p9' => '0',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['book'] = array(
|
||||
array(
|
||||
'mlid' => '1',
|
||||
'nid' => '4',
|
||||
'bid' => '4',
|
||||
),
|
||||
);
|
||||
$this->databaseContents['menu_links'] = array(
|
||||
array(
|
||||
'menu_name' => 'book-toc-1',
|
||||
'mlid' => '1',
|
||||
'plid' => '0',
|
||||
'link_path' => 'node/4',
|
||||
'router_path' => 'node/%',
|
||||
'link_title' => 'Test top book title',
|
||||
'options' => 'a:0:{}',
|
||||
'module' => 'book',
|
||||
'hidden' => '0',
|
||||
'external' => '0',
|
||||
'has_children' => '1',
|
||||
'expanded' => '0',
|
||||
'weight' => '-10',
|
||||
'depth' => '1',
|
||||
'customized' => '0',
|
||||
'p1' => '1',
|
||||
'p2' => '0',
|
||||
'p3' => '0',
|
||||
'p4' => '0',
|
||||
'p5' => '0',
|
||||
'p6' => '0',
|
||||
'p7' => '0',
|
||||
'p8' => '0',
|
||||
'p9' => '0',
|
||||
'updated' => '0',
|
||||
),
|
||||
);
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ namespace Drupal\ckeditor\Plugin\CKEditorPlugin;
|
|||
use Drupal\ckeditor\CKEditorPluginBase;
|
||||
use Drupal\ckeditor\CKEditorPluginContextualInterface;
|
||||
use Drupal\ckeditor\CKEditorPluginManager;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
|
@ -369,7 +370,7 @@ class Internal extends CKEditorPluginBase implements ContainerFactoryPluginInter
|
|||
foreach ($possible_format_tags as $tag) {
|
||||
$input = '<' . $tag . '>TEST</' . $tag . '>';
|
||||
$output = trim(check_markup($input, $editor->id()));
|
||||
if ($input == $output) {
|
||||
if (Html::load($output)->getElementsByTagName($tag)->length !== 0) {
|
||||
$format_tags[] = $tag;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,3 +5,12 @@ ckeditor.plugin.llama_contextual_and_button:
|
|||
ultra_llama_mode:
|
||||
type: boolean
|
||||
label: 'Ultra llama mode'
|
||||
|
||||
filter_settings.test_attribute_filter:
|
||||
type: filter
|
||||
label: 'Test Attribute Filter'
|
||||
mapping:
|
||||
tags:
|
||||
type: sequence
|
||||
sequence:
|
||||
type: string
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ckeditor_test\Plugin\Filter;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\filter\FilterProcessResult;
|
||||
use Drupal\filter\Plugin\FilterBase;
|
||||
|
||||
/**
|
||||
* A filter that adds a test attribute to any configured HTML tags.
|
||||
*
|
||||
* @Filter(
|
||||
* id = "test_attribute_filter",
|
||||
* title = @Translation("Test Attribute Filter"),
|
||||
* type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE,
|
||||
* settings = {
|
||||
* "tags" = {},
|
||||
* },
|
||||
* weight = -10
|
||||
* )
|
||||
*/
|
||||
class TestAttributeFilter extends FilterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process($text, $langcode) {
|
||||
$document = Html::load($text);
|
||||
foreach ($this->settings['tags'] as $tag) {
|
||||
$tag_elements = $document->getElementsByTagName($tag);
|
||||
foreach ($tag_elements as $tag_element) {
|
||||
$tag_element->setAttribute('test_attribute', 'test attribute value');
|
||||
}
|
||||
}
|
||||
return new FilterProcessResult(Html::serialize($document));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\ckeditor\Kernel\Plugin\CKEditorPlugin;
|
||||
|
||||
use Drupal\editor\Entity\Editor;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\ckeditor\Plugin\CKEditorPlugin\Internal
|
||||
*
|
||||
* @group ckeditor
|
||||
*/
|
||||
class InternalTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'ckeditor',
|
||||
'ckeditor_test',
|
||||
'filter',
|
||||
'editor',
|
||||
];
|
||||
|
||||
/**
|
||||
* A testing text format.
|
||||
*
|
||||
* @var \Drupal\filter\Entity\FilterFormat
|
||||
*/
|
||||
protected $format;
|
||||
|
||||
/**
|
||||
* A testing text editor.
|
||||
*
|
||||
* @var \Drupal\editor\Entity\Editor
|
||||
*/
|
||||
protected $editor;
|
||||
|
||||
/**
|
||||
* The CKEditor plugin manager.
|
||||
*
|
||||
* @var \Drupal\Component\Plugin\PluginManagerInterface
|
||||
*/
|
||||
protected $ckeditorPluginManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('editor');
|
||||
$this->installEntitySchema('filter_format');
|
||||
|
||||
$this->format = FilterFormat::create([
|
||||
'format' => 'test_format',
|
||||
'name' => $this->randomMachineName(),
|
||||
]);
|
||||
$this->format->save();
|
||||
|
||||
$this->editor = Editor::create([
|
||||
'editor' => 'ckeditor',
|
||||
'format' => 'test_format',
|
||||
'settings' => [
|
||||
'toolbar' => [
|
||||
'rows' => [
|
||||
[
|
||||
[
|
||||
'name' => 'Enabled Buttons',
|
||||
'items' => [
|
||||
'Format',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->editor->save();
|
||||
|
||||
$this->ckeditorPluginManager = $this->container->get('plugin.manager.ckeditor.plugin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the format tags settings.
|
||||
*
|
||||
* @dataProvider formatTagsSettingsTestCases
|
||||
*/
|
||||
public function testFormatTagsSettings($filter_plugins, $expected_format_tags) {
|
||||
foreach ($filter_plugins as $filter_plugin_id => $filter_plugin_settings) {
|
||||
$this->format->setFilterConfig($filter_plugin_id, $filter_plugin_settings);
|
||||
}
|
||||
$this->format->save();
|
||||
|
||||
$internal_plugin = $this->ckeditorPluginManager->createInstance('internal', []);
|
||||
$plugin_config = $internal_plugin->getConfig($this->editor);
|
||||
$this->assertEquals($expected_format_tags, explode(';', $plugin_config['format_tags']));
|
||||
}
|
||||
|
||||
/**
|
||||
* A data provider for testFormatTagsSettings.
|
||||
*/
|
||||
public function formatTagsSettingsTestCases() {
|
||||
$all_tags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre'];
|
||||
|
||||
return [
|
||||
'No filter plugins enabled (all tags allowed)' => [
|
||||
[],
|
||||
$all_tags,
|
||||
],
|
||||
'HTML filter plugin enabled (some tags filtered out)' => [
|
||||
[
|
||||
'filter_html' => [
|
||||
'status' => 1,
|
||||
'settings' => [
|
||||
'allowed_html' => '<h1> <h2>',
|
||||
'filter_html_help' => 1,
|
||||
'filter_html_nofollow' => 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
['p', 'h1', 'h2'],
|
||||
],
|
||||
'Test attribute filter enabled (all tags allowed)' => [
|
||||
[
|
||||
'test_attribute_filter' => [
|
||||
'status' => 1,
|
||||
'settings' => [
|
||||
'tags' => ['h1', 'h2'],
|
||||
],
|
||||
],
|
||||
],
|
||||
$all_tags,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -12,8 +12,8 @@ process:
|
|||
source: category
|
||||
-
|
||||
plugin: dedupe_entity
|
||||
entity_type: user_role
|
||||
field: cid
|
||||
entity_type: contact_form
|
||||
field: id
|
||||
length: 32
|
||||
label: category
|
||||
recipients: recipients
|
||||
|
|
|
@ -122,7 +122,14 @@ class MailHandler implements MailHandlerInterface {
|
|||
if (!$message->isPersonal() && $contact_form->getReply()) {
|
||||
// User contact forms do not support an auto-reply message, so this
|
||||
// message always originates from the site.
|
||||
$this->mailManager->mail('contact', 'page_autoreply', $sender_cloned->getEmail(), $current_langcode, $params);
|
||||
if (!$sender_cloned->getEmail()) {
|
||||
$this->logger->error('Error sending auto-reply, missing sender e-mail address in %contact_form', [
|
||||
'%contact_form' => $contact_form->label(),
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$this->mailManager->mail('contact', 'page_autoreply', $sender_cloned->getEmail(), $current_langcode, $params);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$message->isPersonal()) {
|
||||
|
|
|
@ -27,7 +27,7 @@ class ContactSitewideTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('text', 'contact', 'field_ui', 'contact_test', 'block');
|
||||
public static $modules = ['text', 'contact', 'field_ui', 'contact_test', 'block', 'error_service_test', 'dblog'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -44,13 +44,13 @@ class ContactSitewideTest extends WebTestBase {
|
|||
*/
|
||||
function testSiteWideContact() {
|
||||
// Create and log in administrative user.
|
||||
$admin_user = $this->drupalCreateUser(array(
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'access site-wide contact form',
|
||||
'administer contact forms',
|
||||
'administer users',
|
||||
'administer account settings',
|
||||
'administer contact_message fields',
|
||||
));
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Check the presence of expected cache tags.
|
||||
|
@ -346,7 +346,13 @@ class ContactSitewideTest extends WebTestBase {
|
|||
*/
|
||||
function testAutoReply() {
|
||||
// Create and log in administrative user.
|
||||
$admin_user = $this->drupalCreateUser(array('access site-wide contact form', 'administer contact forms', 'administer permissions', 'administer users'));
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'access site-wide contact form',
|
||||
'administer contact forms',
|
||||
'administer permissions',
|
||||
'administer users',
|
||||
'access site reports'
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Set up three forms, 2 with an auto-reply and one without.
|
||||
|
@ -384,6 +390,20 @@ class ContactSitewideTest extends WebTestBase {
|
|||
$this->submitContact($this->randomMachineName(16), $email, $this->randomString(64), 'no_autoreply', $this->randomString(128));
|
||||
$captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email));
|
||||
$this->assertEqual(count($captured_emails), 0);
|
||||
|
||||
// Verify that the current error message doesn't show, that the auto-reply
|
||||
// doesn't get sent and the correct silent error gets logged.
|
||||
$email = '';
|
||||
entity_get_form_display('contact_message', 'foo', 'default')
|
||||
->removeComponent('mail')
|
||||
->save();
|
||||
$this->submitContact($this->randomMachineName(16), $email, $this->randomString(64), 'foo', $this->randomString(128));
|
||||
$this->assertNoText('Unable to send email. Contact the site administrator if the problem persists.');
|
||||
$captured_emails = $this->drupalGetMails(['id' => 'contact_page_autoreply', 'to' => $email]);
|
||||
$this->assertEqual(count($captured_emails), 0);
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertRaw('Error sending auto-reply, missing sender e-mail address in foo');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,6 +47,29 @@ class MigrateContactCategoryTest extends MigrateDrupal6TestBase {
|
|||
$this->assertIdentical(array('fortyninechars@example.com'), $contact_form->getRecipients());
|
||||
$this->assertIdentical('', $contact_form->getReply());
|
||||
$this->assertIdentical(2, $contact_form->getWeight());
|
||||
|
||||
// Test there are no duplicated roles.
|
||||
$contact_forms = [
|
||||
'website_feedback1',
|
||||
'some_other_category1',
|
||||
'a_category_much_longer_than_thir1',
|
||||
];
|
||||
$this->assertEmpty(ContactForm::loadMultiple($contact_forms));
|
||||
|
||||
/*
|
||||
* Remove the map row for the Website feedback contact form so that it
|
||||
* can be migrated again.
|
||||
*/
|
||||
$id_map = $this->getMigration('contact_category')->getIdMap();
|
||||
$id_map->delete(['cid' => '1']);
|
||||
$this->executeMigration('contact_category');
|
||||
|
||||
// Test there is a duplicate Website feedback form.
|
||||
$contact_form = ContactForm::load('website_feedback1');
|
||||
$this->assertSame('Website feedback', $contact_form->label());
|
||||
$this->assertSame(array('admin@example.com'), $contact_form->getRecipients());
|
||||
$this->assertSame('', $contact_form->getReply());
|
||||
$this->assertSame(0, $contact_form->getWeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\contact\Kernel\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 contact category source plugin.
|
||||
*
|
||||
* @covers \Drupal\contact\Plugin\migrate\source\ContactCategory
|
||||
* @group contact
|
||||
*/
|
||||
class ContactCategoryTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['contact', 'migrate_drupal', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [
|
||||
[
|
||||
'source_data' => [],
|
||||
'expected_data' => [],
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'cid' => 1,
|
||||
'category' => 'contact category value 1',
|
||||
'recipients' => ['admin@example.com', 'user@example.com'],
|
||||
'reply' => 'auto reply value 1',
|
||||
'weight' => 0,
|
||||
'selected' => 0,
|
||||
],
|
||||
[
|
||||
'cid' => 2,
|
||||
'category' => 'contact category value 2',
|
||||
'recipients' => ['admin@example.com', 'user@example.com'],
|
||||
'reply' => 'auto reply value 2',
|
||||
'weight' => 0,
|
||||
'selected' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($tests[0]['expected_data'] as $k => $row) {
|
||||
$row['recipients'] = implode(',', $row['recipients']);
|
||||
$tests[0]['source_data']['contact'][$k] = $row;
|
||||
}
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\contact\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 contact settings source plugin.
|
||||
*
|
||||
* @covers \Drupal\contact\Plugin\migrate\source\ContactSettings
|
||||
* @group contact
|
||||
*/
|
||||
class ContactSettingsTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['contact', 'migrate_drupal', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
$tests[0]['source_data']['variable'] = [
|
||||
[
|
||||
'name' => 'site_name',
|
||||
'value' => serialize('Blorf!'),
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['contact'] = [
|
||||
[
|
||||
'cid' => '1',
|
||||
'category' => 'Website feedback',
|
||||
'recipients' => 'admin@example.com',
|
||||
'reply' => '',
|
||||
'weight' => '0',
|
||||
'selected' => '1',
|
||||
]
|
||||
];
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'default_category' => '1',
|
||||
'site_name' => 'Blorf!',
|
||||
],
|
||||
];
|
||||
$tests[0]['expected_count'] = NULL;
|
||||
$tests[0]['configuration']['variables'] = ['site_name'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\contact\Unit\Plugin\migrate\source;
|
||||
|
||||
use Drupal\contact\Plugin\migrate\source\ContactCategory;
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests contact_category source plugin.
|
||||
*
|
||||
* @group contact
|
||||
*/
|
||||
class ContactCategoryTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = ContactCategory::class;
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'contact_category',
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'cid' => 1,
|
||||
'category' => 'contact category value 1',
|
||||
'recipients' => array('admin@example.com', 'user@example.com'),
|
||||
'reply' => 'auto reply value 1',
|
||||
'weight' => 0,
|
||||
'selected' => 0,
|
||||
),
|
||||
array(
|
||||
'cid' => 2,
|
||||
'category' => 'contact category value 2',
|
||||
'recipients' => array('admin@example.com', 'user@example.com'),
|
||||
'reply' => 'auto reply value 2',
|
||||
'weight' => 0,
|
||||
'selected' => 0,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
foreach ($this->expectedResults as $k => $row) {
|
||||
$this->databaseContents['contact'][$k] = $row;
|
||||
$this->databaseContents['contact'][$k]['recipients'] = implode(',', $row['recipients']);
|
||||
}
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\contact\Unit\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\contact\Plugin\migrate\source\ContactSettings;
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests D6 contact settings source plugin.
|
||||
*
|
||||
* @group contact
|
||||
*/
|
||||
class ContactSettingsTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = ContactSettings::class;
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test',
|
||||
'source' => array(
|
||||
'plugin' => 'd6_contact_settings',
|
||||
'variables' => array('site_name'),
|
||||
),
|
||||
);
|
||||
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'default_category' => '1',
|
||||
'site_name' => 'Blorf!',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['variable'] = array(
|
||||
array(
|
||||
'name' => 'site_name',
|
||||
'value' => serialize('Blorf!'),
|
||||
),
|
||||
);
|
||||
$this->databaseContents['contact'] = array(
|
||||
array(
|
||||
'cid' => '1',
|
||||
'category' => 'Website feedback',
|
||||
'recipients' => 'admin@example.com',
|
||||
'reply' => '',
|
||||
'weight' => '0',
|
||||
'selected' => '1',
|
||||
)
|
||||
);
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,6 @@ namespace Drupal\content_moderation\Entity;
|
|||
|
||||
use Drupal\content_moderation\ContentModerationStateInterface;
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityChangedTrait;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\TypedData\TranslatableInterface;
|
||||
|
@ -42,8 +41,6 @@ use Drupal\user\UserInterface;
|
|||
*/
|
||||
class ContentModerationState extends ContentEntityBase implements ContentModerationStateInterface {
|
||||
|
||||
use EntityChangedTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace Drupal\content_moderation;
|
|||
|
||||
use Drupal\content_moderation\Entity\ContentModerationState;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
|
@ -77,32 +76,6 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the default moderation state on load for an entity.
|
||||
*
|
||||
* This method is only applicable when an entity is loaded that has
|
||||
* no moderation state on it, but should. In those cases, failing to set
|
||||
* one may result in NULL references elsewhere when other code tries to check
|
||||
* the moderation state of the entity.
|
||||
*
|
||||
* The amount of indirection here makes performance a concern, but
|
||||
* given how Entity API works I don't know how else to do it.
|
||||
* This reliably gets us *A* valid state. However, that state may be
|
||||
* not the ideal one. Suggestions on how to better select the default
|
||||
* state here are welcome.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
||||
* The entity for which we want a default state.
|
||||
*
|
||||
* @return string
|
||||
* The default state for the given entity.
|
||||
*/
|
||||
protected function getDefaultLoadStateId(ContentEntityInterface $entity) {
|
||||
return $this->moderationInfo
|
||||
->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())
|
||||
->getThirdPartySetting('content_moderation', 'default_moderation_state');
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts on an entity and set published status based on the moderation state.
|
||||
*
|
||||
|
@ -170,8 +143,8 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
$moderation_state = $entity->moderation_state->target_id;
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
if (!$moderation_state) {
|
||||
$moderation_state = $this->moderationInfo
|
||||
->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())
|
||||
$moderation_state = $this->entityTypeManager
|
||||
->getStorage($entity->getEntityType()->getBundleEntityType())->load($entity->bundle())
|
||||
->getThirdPartySetting('content_moderation', 'default_moderation_state');
|
||||
}
|
||||
|
||||
|
|
|
@ -49,21 +49,15 @@ class ModerationInformation implements ModerationInformationInterface {
|
|||
return $entity_type->hasHandlerClass('moderation');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadBundleEntity($bundle_entity_type_id, $bundle_id) {
|
||||
if ($bundle_entity_type_id) {
|
||||
return $this->entityTypeManager->getStorage($bundle_entity_type_id)->load($bundle_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function shouldModerateEntitiesOfBundle(EntityTypeInterface $entity_type, $bundle) {
|
||||
if ($bundle_entity = $this->loadBundleEntity($entity_type->getBundleEntityType(), $bundle)) {
|
||||
return $bundle_entity->getThirdPartySetting('content_moderation', 'enabled', FALSE);
|
||||
if ($this->canModerateEntitiesOfEntityType($entity_type)) {
|
||||
$bundle_entity = $this->entityTypeManager->getStorage($entity_type->getBundleEntityType())->load($bundle);
|
||||
if ($bundle_entity) {
|
||||
return $bundle_entity->getThirdPartySetting('content_moderation', 'enabled', FALSE);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -11,19 +11,6 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
*/
|
||||
interface ModerationInformationInterface {
|
||||
|
||||
/**
|
||||
* Loads a specific bundle entity.
|
||||
*
|
||||
* @param string $bundle_entity_type_id
|
||||
* The bundle entity type ID.
|
||||
* @param string $bundle_id
|
||||
* The bundle ID.
|
||||
*
|
||||
* @return \Drupal\Core\Config\Entity\ConfigEntityInterface|null
|
||||
* The bundle entity.
|
||||
*/
|
||||
public function loadBundleEntity($bundle_entity_type_id, $bundle_id);
|
||||
|
||||
/**
|
||||
* Determines if an entity is moderated.
|
||||
*
|
||||
|
|
|
@ -57,8 +57,9 @@ class ModerationStateFieldItemList extends EntityReferenceFieldItemList {
|
|||
// It is possible that the bundle does not exist at this point. For example,
|
||||
// the node type form creates a fake Node entity to get default values.
|
||||
// @see \Drupal\node\NodeTypeForm::form()
|
||||
$bundle_entity = \Drupal::service('content_moderation.moderation_information')
|
||||
->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle());
|
||||
$bundle_entity = \Drupal::entityTypeManager()
|
||||
->getStorage($entity->getEntityType()->getBundleEntityType())
|
||||
->load($entity->bundle());
|
||||
if ($bundle_entity && ($default = $bundle_entity->getThirdPartySetting('content_moderation', 'default_moderation_state'))) {
|
||||
return ModerationState::load($default);
|
||||
}
|
||||
|
@ -71,7 +72,24 @@ class ModerationStateFieldItemList extends EntityReferenceFieldItemList {
|
|||
if ($index !== 0) {
|
||||
throw new \InvalidArgumentException('An entity can not have multiple moderation states at the same time.');
|
||||
}
|
||||
$this->computeModerationFieldItemList();
|
||||
return isset($this->list[$index]) ? $this->list[$index] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIterator() {
|
||||
$this->computeModerationFieldItemList();
|
||||
return parent::getIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate the moderation field item list.
|
||||
*/
|
||||
protected function computeModerationFieldItemList() {
|
||||
// Compute the value of the moderation state.
|
||||
$index = 0;
|
||||
if (!isset($this->list[$index]) || $this->list[$index]->isEmpty()) {
|
||||
$moderation_state = $this->getModerationState();
|
||||
// Do not store NULL values in the static cache.
|
||||
|
@ -79,8 +97,6 @@ class ModerationStateFieldItemList extends EntityReferenceFieldItemList {
|
|||
$this->list[$index] = $this->createItem($index, ['entity' => $moderation_state]);
|
||||
}
|
||||
}
|
||||
|
||||
return isset($this->list[$index]) ? $this->list[$index] : NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -97,8 +97,8 @@ class ModerationStateConstraintValidator extends ConstraintValidator implements
|
|||
$new_state_id = $entity->moderation_state->target_id;
|
||||
}
|
||||
else {
|
||||
$new_state_id = $default = $this->moderationInformation
|
||||
->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())
|
||||
$new_state_id = $default = $this->entityTypeManager
|
||||
->getStorage($entity->getEntityType()->getBundleEntityType())->load($entity->bundle())
|
||||
->getThirdPartySetting('content_moderation', 'default_moderation_state');
|
||||
}
|
||||
if ($new_state_id) {
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class ModerationStateFieldItemListTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'node',
|
||||
'content_moderation',
|
||||
'user',
|
||||
'system',
|
||||
'language',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $testNode;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installSchema('node', 'node_access');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('content_moderation_state');
|
||||
$this->installConfig('content_moderation');
|
||||
|
||||
$node_type = NodeType::create([
|
||||
'type' => 'example',
|
||||
]);
|
||||
$node_type->setThirdPartySetting('content_moderation', 'enabled', TRUE);
|
||||
$node_type->setThirdPartySetting('content_moderation', 'allowed_moderation_states', ['draft']);
|
||||
$node_type->setThirdPartySetting('content_moderation', 'default_moderation_state', 'draft');
|
||||
$node_type->save();
|
||||
$this->testNode = Node::create([
|
||||
'type' => 'example',
|
||||
'title' => 'Test title',
|
||||
]);
|
||||
$this->testNode->save();
|
||||
\Drupal::entityTypeManager()->getStorage('node')->resetCache();
|
||||
$this->testNode = Node::load($this->testNode->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the field item list when accessing an index.
|
||||
*/
|
||||
public function testArrayIndex() {
|
||||
$this->assertEquals('draft', $this->testNode->moderation_state[0]->entity->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the field item list when iterating.
|
||||
*/
|
||||
public function testArrayIteration() {
|
||||
$states = [];
|
||||
foreach ($this->testNode->moderation_state as $item) {
|
||||
$states[] = $item->entity->id();
|
||||
}
|
||||
$this->assertEquals(['draft'], $states);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\Tests\content_moderation\Unit;
|
||||
|
||||
use Drupal\content_moderation\Entity\Handler\ModerationHandler;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\ContentEntityType;
|
||||
|
@ -70,6 +71,7 @@ class ModerationInformationTest extends \PHPUnit_Framework_TestCase {
|
|||
$entity_type = new ContentEntityType([
|
||||
'id' => 'test_entity_type',
|
||||
'bundle_entity_type' => 'entity_test_bundle',
|
||||
'handlers' => ['moderation' => ModerationHandler::class],
|
||||
]);
|
||||
$entity = $this->prophesize(ContentEntityInterface::class);
|
||||
$entity->getEntityType()->willReturn($entity_type);
|
||||
|
@ -104,6 +106,7 @@ class ModerationInformationTest extends \PHPUnit_Framework_TestCase {
|
|||
$entity_type = new ContentEntityType([
|
||||
'id' => 'test_entity_type',
|
||||
'bundle_entity_type' => 'entity_test_bundle',
|
||||
'handlers' => ['moderation' => ModerationHandler::class],
|
||||
]);
|
||||
|
||||
$moderation_information = new ModerationInformation($this->setupModerationEntityManager($status), $this->getUser());
|
||||
|
|
|
@ -92,11 +92,19 @@ class DateTimeFieldItemList extends FieldItemList {
|
|||
$default_value = parent::processDefaultValue($default_value, $entity, $definition);
|
||||
|
||||
if (isset($default_value[0]['default_date_type'])) {
|
||||
// A default value should be in the format and timezone used for date
|
||||
// storage.
|
||||
$date = new DrupalDateTime($default_value[0]['default_date'], DATETIME_STORAGE_TIMEZONE);
|
||||
$storage_format = $definition->getSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE ? DATETIME_DATE_STORAGE_FORMAT : DATETIME_DATETIME_STORAGE_FORMAT;
|
||||
$value = $date->format($storage_format);
|
||||
if ($definition->getSetting('datetime_type') === DateTimeItem::DATETIME_TYPE_DATE) {
|
||||
// A default date only value should be in the format used for date
|
||||
// storage but in the user's local timezone.
|
||||
$date = new DrupalDateTime($default_value[0]['default_date'], drupal_get_user_timezone());
|
||||
$format = DATETIME_DATE_STORAGE_FORMAT;
|
||||
}
|
||||
else {
|
||||
// A default date+time value should be in the format and timezone used
|
||||
// for date storage.
|
||||
$date = new DrupalDateTime($default_value[0]['default_date'], DATETIME_STORAGE_TIMEZONE);
|
||||
$format = DATETIME_DATETIME_STORAGE_FORMAT;
|
||||
}
|
||||
$value = $date->format($format);
|
||||
// We only provide a default value for the first item, as do all fields.
|
||||
// Otherwise, there is no way to clear out unwanted values on multiple value
|
||||
// fields.
|
||||
|
|
|
@ -594,83 +594,103 @@ class DateTimeFieldTest extends DateTestBase {
|
|||
]);
|
||||
$field->save();
|
||||
|
||||
// Set now as default_value.
|
||||
$field_edit = array(
|
||||
'default_value_input[default_date_type]' => 'now',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name, $field_edit, t('Save settings'));
|
||||
// Loop through defined timezones to test that date-only defaults work at
|
||||
// the extremes.
|
||||
foreach (static::$timezones as $timezone) {
|
||||
|
||||
// Check that default value is selected in default value form.
|
||||
$this->drupalGet('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name);
|
||||
$this->assertOptionSelected('edit-default-value-input-default-date-type', 'now', 'The default value is selected in instance settings page');
|
||||
$this->assertFieldByName('default_value_input[default_date]', '', 'The relative default value is empty in instance settings page');
|
||||
$this->setSiteTimezone($timezone);
|
||||
|
||||
// Check if default_date has been stored successfully.
|
||||
$config_entity = $this->config('field.field.node.date_content.' . $field_name)->get();
|
||||
$this->assertEqual($config_entity['default_value'][0], array('default_date_type' => 'now', 'default_date' => 'now'), 'Default value has been stored successfully');
|
||||
// Set now as default_value.
|
||||
$field_edit = array(
|
||||
'default_value_input[default_date_type]' => 'now',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name, $field_edit, t('Save settings'));
|
||||
|
||||
// Clear field cache in order to avoid stale cache values.
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
// Check that default value is selected in default value form.
|
||||
$this->drupalGet('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name);
|
||||
$this->assertOptionSelected('edit-default-value-input-default-date-type', 'now', 'The default value is selected in instance settings page');
|
||||
$this->assertFieldByName('default_value_input[default_date]', '', 'The relative default value is empty in instance settings page');
|
||||
|
||||
// Create a new node to check that datetime field default value is today.
|
||||
$new_node = Node::create(['type' => 'date_content']);
|
||||
$expected_date = new DrupalDateTime('now', DATETIME_STORAGE_TIMEZONE);
|
||||
$this->assertEqual($new_node->get($field_name)->offsetGet(0)->value, $expected_date->format(DATETIME_DATE_STORAGE_FORMAT));
|
||||
// Check if default_date has been stored successfully.
|
||||
$config_entity = $this->config('field.field.node.date_content.' . $field_name)
|
||||
->get();
|
||||
$this->assertEqual($config_entity['default_value'][0], array(
|
||||
'default_date_type' => 'now',
|
||||
'default_date' => 'now',
|
||||
), 'Default value has been stored successfully');
|
||||
|
||||
// Set an invalid relative default_value to test validation.
|
||||
$field_edit = array(
|
||||
'default_value_input[default_date_type]' => 'relative',
|
||||
'default_value_input[default_date]' => 'invalid date',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name, $field_edit, t('Save settings'));
|
||||
// Clear field cache in order to avoid stale cache values.
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
|
||||
$this->assertText('The relative date value entered is invalid.');
|
||||
// Create a new node to check that datetime field default value is today.
|
||||
$new_node = Node::create(['type' => 'date_content']);
|
||||
$expected_date = new DrupalDateTime('now', drupal_get_user_timezone());
|
||||
$this->assertEqual($new_node->get($field_name)
|
||||
->offsetGet(0)->value, $expected_date->format(DATETIME_DATE_STORAGE_FORMAT));
|
||||
|
||||
// Set a relative default_value.
|
||||
$field_edit = array(
|
||||
'default_value_input[default_date_type]' => 'relative',
|
||||
'default_value_input[default_date]' => '+90 days',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name, $field_edit, t('Save settings'));
|
||||
// Set an invalid relative default_value to test validation.
|
||||
$field_edit = array(
|
||||
'default_value_input[default_date_type]' => 'relative',
|
||||
'default_value_input[default_date]' => 'invalid date',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name, $field_edit, t('Save settings'));
|
||||
|
||||
// Check that default value is selected in default value form.
|
||||
$this->drupalGet('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name);
|
||||
$this->assertOptionSelected('edit-default-value-input-default-date-type', 'relative', 'The default value is selected in instance settings page');
|
||||
$this->assertFieldByName('default_value_input[default_date]', '+90 days', 'The relative default value is displayed in instance settings page');
|
||||
$this->assertText('The relative date value entered is invalid.');
|
||||
|
||||
// Check if default_date has been stored successfully.
|
||||
$config_entity = $this->config('field.field.node.date_content.' . $field_name)->get();
|
||||
$this->assertEqual($config_entity['default_value'][0], array('default_date_type' => 'relative', 'default_date' => '+90 days'), 'Default value has been stored successfully');
|
||||
// Set a relative default_value.
|
||||
$field_edit = array(
|
||||
'default_value_input[default_date_type]' => 'relative',
|
||||
'default_value_input[default_date]' => '+90 days',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name, $field_edit, t('Save settings'));
|
||||
|
||||
// Clear field cache in order to avoid stale cache values.
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
// Check that default value is selected in default value form.
|
||||
$this->drupalGet('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name);
|
||||
$this->assertOptionSelected('edit-default-value-input-default-date-type', 'relative', 'The default value is selected in instance settings page');
|
||||
$this->assertFieldByName('default_value_input[default_date]', '+90 days', 'The relative default value is displayed in instance settings page');
|
||||
|
||||
// Create a new node to check that datetime field default value is +90 days.
|
||||
$new_node = Node::create(['type' => 'date_content']);
|
||||
$expected_date = new DrupalDateTime('+90 days', DATETIME_STORAGE_TIMEZONE);
|
||||
$this->assertEqual($new_node->get($field_name)->offsetGet(0)->value, $expected_date->format(DATETIME_DATE_STORAGE_FORMAT));
|
||||
// Check if default_date has been stored successfully.
|
||||
$config_entity = $this->config('field.field.node.date_content.' . $field_name)
|
||||
->get();
|
||||
$this->assertEqual($config_entity['default_value'][0], array(
|
||||
'default_date_type' => 'relative',
|
||||
'default_date' => '+90 days',
|
||||
), 'Default value has been stored successfully');
|
||||
|
||||
// Remove default value.
|
||||
$field_edit = array(
|
||||
'default_value_input[default_date_type]' => '',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name, $field_edit, t('Save settings'));
|
||||
// Clear field cache in order to avoid stale cache values.
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
|
||||
// Check that default value is selected in default value form.
|
||||
$this->drupalGet('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name);
|
||||
$this->assertOptionSelected('edit-default-value-input-default-date-type', '', 'The default value is selected in instance settings page');
|
||||
$this->assertFieldByName('default_value_input[default_date]', '', 'The relative default value is empty in instance settings page');
|
||||
// Create a new node to check that datetime field default value is +90
|
||||
// days.
|
||||
$new_node = Node::create(['type' => 'date_content']);
|
||||
$expected_date = new DrupalDateTime('+90 days', drupal_get_user_timezone());
|
||||
$this->assertEqual($new_node->get($field_name)
|
||||
->offsetGet(0)->value, $expected_date->format(DATETIME_DATE_STORAGE_FORMAT));
|
||||
|
||||
// Check if default_date has been stored successfully.
|
||||
$config_entity = $this->config('field.field.node.date_content.' . $field_name)->get();
|
||||
$this->assertTrue(empty($config_entity['default_value']), 'Empty default value has been stored successfully');
|
||||
// Remove default value.
|
||||
$field_edit = array(
|
||||
'default_value_input[default_date_type]' => '',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name, $field_edit, t('Save settings'));
|
||||
|
||||
// Clear field cache in order to avoid stale cache values.
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
// Check that default value is selected in default value form.
|
||||
$this->drupalGet('admin/structure/types/manage/date_content/fields/node.date_content.' . $field_name);
|
||||
$this->assertOptionSelected('edit-default-value-input-default-date-type', '', 'The default value is selected in instance settings page');
|
||||
$this->assertFieldByName('default_value_input[default_date]', '', 'The relative default value is empty in instance settings page');
|
||||
|
||||
// Create a new node to check that datetime field default value is not set.
|
||||
$new_node = Node::create(['type' => 'date_content']);
|
||||
$this->assertNull($new_node->get($field_name)->value, 'Default value is not set');
|
||||
// Check if default_date has been stored successfully.
|
||||
$config_entity = $this->config('field.field.node.date_content.' . $field_name)
|
||||
->get();
|
||||
$this->assertTrue(empty($config_entity['default_value']), 'Empty default value has been stored successfully');
|
||||
|
||||
// Clear field cache in order to avoid stale cache values.
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
|
||||
// Create a new node to check that datetime field default value is not
|
||||
// set.
|
||||
$new_node = Node::create(['type' => 'date_content']);
|
||||
$this->assertNull($new_node->get($field_name)->value, 'Default value is not set');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,24 +32,27 @@ field.formatter.settings.daterange_default:
|
|||
label: 'Date range default display format settings'
|
||||
mapping:
|
||||
separator:
|
||||
type: string
|
||||
type: label
|
||||
label: 'Separator'
|
||||
translation context: 'Date range separator'
|
||||
|
||||
field.formatter.settings.daterange_plain:
|
||||
type: field.formatter.settings.datetime_plain
|
||||
label: 'Date range plain display format settings'
|
||||
mapping:
|
||||
separator:
|
||||
type: string
|
||||
type: label
|
||||
label: 'Separator'
|
||||
translation context: 'Date range separator'
|
||||
|
||||
field.formatter.settings.daterange_custom:
|
||||
type: field.formatter.settings.datetime_custom
|
||||
label: 'Date range custom display format settings'
|
||||
mapping:
|
||||
separator:
|
||||
type: string
|
||||
type: label
|
||||
label: 'Separator'
|
||||
translation context: 'Date range separator'
|
||||
|
||||
field.widget.settings.daterange_datelist:
|
||||
type: mapping
|
||||
|
|
22
core/modules/datetime_range/datetime_range.post_update.php
Normal file
22
core/modules/datetime_range/datetime_range.post_update.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Post-update functions for Datetime Range module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup updates-8.2.x
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Clear caches to ensure schema changes are read.
|
||||
*/
|
||||
function datetime_range_post_update_translatable_separator() {
|
||||
// Empty post-update hook to cause a cache rebuild.
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-8.2.x".
|
||||
*/
|
|
@ -58,13 +58,12 @@ class DateRangeDefaultFormatter extends DateTimeDefaultFormatter {
|
|||
}
|
||||
else {
|
||||
$elements[$delta] = $this->buildDateWithIsoAttribute($start_date);
|
||||
}
|
||||
|
||||
if (!empty($item->_attributes)) {
|
||||
$elements[$delta]['#attributes'] += $item->_attributes;
|
||||
// Unset field item attributes since they have been included in the
|
||||
// formatter output and should not be rendered in the field template.
|
||||
unset($item->_attributes);
|
||||
if (!empty($item->_attributes)) {
|
||||
$elements[$delta]['#attributes'] += $item->_attributes;
|
||||
// Unset field item attributes since they have been included in the
|
||||
// formatter output and should not be rendered in the field template.
|
||||
unset($item->_attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,6 +140,11 @@ class DateRangeFieldTest extends DateTestBase {
|
|||
]));
|
||||
$this->assertText(' THESEPARATOR ', 'Found proper separator');
|
||||
|
||||
// Verify that hook_entity_prepare_view can add attributes.
|
||||
// @see entity_test_entity_prepare_view()
|
||||
$this->drupalGet('entity_test/' . $id);
|
||||
$this->assertFieldByXPath('//div[@data-field-item-attr="foobar"]');
|
||||
|
||||
// Verify that the plain formatter works.
|
||||
$this->displayOptions['type'] = 'daterange_plain';
|
||||
$this->displayOptions['settings'] = $this->defaultSettings;
|
||||
|
@ -203,6 +208,11 @@ class DateRangeFieldTest extends DateTestBase {
|
|||
]));
|
||||
$this->assertNoText(' THESEPARATOR ', 'Separator not found on page');
|
||||
|
||||
// Verify that hook_entity_prepare_view can add attributes.
|
||||
// @see entity_test_entity_prepare_view()
|
||||
$this->drupalGet('entity_test/' . $id);
|
||||
$this->assertFieldByXPath('//time[@data-field-item-attr="foobar"]');
|
||||
|
||||
$this->displayOptions['type'] = 'daterange_plain';
|
||||
$this->displayOptions['settings'] = $this->defaultSettings;
|
||||
entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
|
||||
|
@ -289,6 +299,11 @@ class DateRangeFieldTest extends DateTestBase {
|
|||
$this->assertFieldByXPath('//time[@datetime="' . $end_expected_iso . '"]', $end_expected, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', ['%value' => 'long', '%expected' => $end_expected, '%expected_iso' => $end_expected_iso]));
|
||||
$this->assertText(' THESEPARATOR ', 'Found proper separator');
|
||||
|
||||
// Verify that hook_entity_prepare_view can add attributes.
|
||||
// @see entity_test_entity_prepare_view()
|
||||
$this->drupalGet('entity_test/' . $id);
|
||||
$this->assertFieldByXPath('//div[@data-field-item-attr="foobar"]');
|
||||
|
||||
// Verify that the plain formatter works.
|
||||
$this->displayOptions['type'] = 'daterange_plain';
|
||||
$this->displayOptions['settings'] = $this->defaultSettings;
|
||||
|
@ -360,6 +375,11 @@ class DateRangeFieldTest extends DateTestBase {
|
|||
$this->assertFieldByXPath('//time[@datetime="' . $start_expected_iso . '"]', $start_expected, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', ['%value' => 'long', '%expected' => $start_expected, '%expected_iso' => $start_expected_iso]));
|
||||
$this->assertNoText(' THESEPARATOR ', 'Separator not found on page');
|
||||
|
||||
// Verify that hook_entity_prepare_view can add attributes.
|
||||
// @see entity_test_entity_prepare_view()
|
||||
$this->drupalGet('entity_test/' . $id);
|
||||
$this->assertFieldByXPath('//time[@data-field-item-attr="foobar"]');
|
||||
|
||||
$this->displayOptions['type'] = 'daterange_plain';
|
||||
$this->displayOptions['settings'] = $this->defaultSettings;
|
||||
entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
|
||||
|
@ -440,6 +460,11 @@ class DateRangeFieldTest extends DateTestBase {
|
|||
$this->assertFieldByXPath('//time[@datetime="' . $end_expected_iso . '"]', $end_expected, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', ['%value' => 'long', '%expected' => $end_expected, '%expected_iso' => $end_expected_iso]));
|
||||
$this->assertText(' THESEPARATOR ', 'Found proper separator');
|
||||
|
||||
// Verify that hook_entity_prepare_view can add attributes.
|
||||
// @see entity_test_entity_prepare_view()
|
||||
$this->drupalGet('entity_test/' . $id);
|
||||
$this->assertFieldByXPath('//div[@data-field-item-attr="foobar"]');
|
||||
|
||||
// Verify that the plain formatter works.
|
||||
$this->displayOptions['type'] = 'daterange_plain';
|
||||
$this->displayOptions['settings'] = $this->defaultSettings;
|
||||
|
@ -513,6 +538,11 @@ class DateRangeFieldTest extends DateTestBase {
|
|||
$this->assertFieldByXPath('//time[@datetime="' . $end_expected_iso . '"]', $end_expected, new FormattableMarkup('Formatted date field using %value format displayed as %expected with %expected_iso attribute.', ['%value' => 'long', '%expected' => $end_expected, '%expected_iso' => $end_expected_iso]));
|
||||
$this->assertText(' THESEPARATOR ', 'Found proper separator');
|
||||
|
||||
// Verify that hook_entity_prepare_view can add attributes.
|
||||
// @see entity_test_entity_prepare_view()
|
||||
$this->drupalGet('entity_test/' . $id);
|
||||
$this->assertFieldByXPath('//div[@data-field-item-attr="foobar"]');
|
||||
|
||||
$this->displayOptions['type'] = 'daterange_plain';
|
||||
entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full')
|
||||
->setComponent($field_name, $this->displayOptions)
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\datetime_range\Kernel;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Entity\Entity\EntityViewDisplay;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Test to ensure the datetime range separator is translatable.
|
||||
*
|
||||
* @group datetime
|
||||
*/
|
||||
class SeparatorTranslationTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* A field storage to use in this test class.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldStorageConfig
|
||||
*/
|
||||
protected $fieldStorage;
|
||||
|
||||
/**
|
||||
* The field used in this test class.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldConfig
|
||||
*/
|
||||
protected $field;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'datetime',
|
||||
'datetime_range',
|
||||
'entity_test',
|
||||
'field',
|
||||
'language',
|
||||
'system',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('entity_test');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installConfig(['system']);
|
||||
$this->installSchema('system', ['sequences', 'key_value']);
|
||||
|
||||
// Add a datetime range field.
|
||||
$this->fieldStorage = FieldStorageConfig::create([
|
||||
'field_name' => Unicode::strtolower($this->randomMachineName()),
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'daterange',
|
||||
'settings' => ['datetime_type' => DateTimeItem::DATETIME_TYPE_DATE],
|
||||
]);
|
||||
$this->fieldStorage->save();
|
||||
|
||||
$this->field = FieldConfig::create([
|
||||
'field_storage' => $this->fieldStorage,
|
||||
'bundle' => 'entity_test',
|
||||
'required' => TRUE,
|
||||
]);
|
||||
$this->field->save();
|
||||
|
||||
$display_options = [
|
||||
'type' => 'daterange_default',
|
||||
'label' => 'hidden',
|
||||
'settings' => [
|
||||
'format_type' => 'fallback',
|
||||
'separator' => 'UNTRANSLATED',
|
||||
],
|
||||
];
|
||||
EntityViewDisplay::create([
|
||||
'targetEntityType' => $this->field->getTargetEntityTypeId(),
|
||||
'bundle' => $this->field->getTargetBundle(),
|
||||
'mode' => 'default',
|
||||
'status' => TRUE,
|
||||
])->setComponent($this->fieldStorage->getName(), $display_options)
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the translation of the range separator.
|
||||
*/
|
||||
public function testSeparatorTranslation() {
|
||||
// Create an entity.
|
||||
$entity = EntityTest::create([
|
||||
'name' => $this->randomString(),
|
||||
$this->fieldStorage->getName() => [
|
||||
'value' => '2016-09-20',
|
||||
'end_value' => '2016-09-21',
|
||||
],
|
||||
]);
|
||||
|
||||
// Verify the untranslated separator.
|
||||
$display = EntityViewDisplay::collectRenderDisplay($entity, 'default');
|
||||
$build = $display->build($entity);
|
||||
$output = $this->container->get('renderer')->renderRoot($build);
|
||||
$this->verbose($output);
|
||||
$this->assertContains('UNTRANSLATED', (string) $output);
|
||||
|
||||
// Translate the separator.
|
||||
ConfigurableLanguage::createFromLangcode('nl')->save();
|
||||
/** @var \Drupal\language\ConfigurableLanguageManagerInterface $language_manager */
|
||||
$language_manager = $this->container->get('language_manager');
|
||||
$language_manager->getLanguageConfigOverride('nl', 'core.entity_view_display.entity_test.entity_test.default')
|
||||
->set('content.' . $this->fieldStorage->getName() . '.settings.separator', 'NL_TRANSLATED!')
|
||||
->save();
|
||||
|
||||
$this->container->get('language.config_factory_override')
|
||||
->setLanguage(new Language(['id' => 'nl']));
|
||||
$this->container->get('cache_tags.invalidator')->invalidateTags($entity->getCacheTags());
|
||||
$display = EntityViewDisplay::collectRenderDisplay($entity, 'default');
|
||||
$build = $display->build($entity);
|
||||
$output = $this->container->get('renderer')->renderRoot($build);
|
||||
$this->verbose($output);
|
||||
$this->assertContains('NL_TRANSLATED!', (string) $output);
|
||||
}
|
||||
|
||||
}
|
|
@ -467,6 +467,78 @@ function _editor_delete_file_usage(array $uuids, EntityInterface $entity, $count
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_download().
|
||||
*
|
||||
* @see file_file_download()
|
||||
* @see file_get_file_references()
|
||||
*/
|
||||
function editor_file_download($uri) {
|
||||
// Get the file record based on the URI. If not in the database just return.
|
||||
/** @var \Drupal\file\FileInterface[] $files */
|
||||
$files = \Drupal::entityTypeManager()
|
||||
->getStorage('file')
|
||||
->loadByProperties(['uri' => $uri]);
|
||||
if (count($files)) {
|
||||
foreach ($files as $item) {
|
||||
// Since some database servers sometimes use a case-insensitive comparison
|
||||
// by default, double check that the filename is an exact match.
|
||||
if ($item->getFileUri() === $uri) {
|
||||
$file = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isset($file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Temporary files are handled by file_file_download(), so nothing to do here
|
||||
// about them.
|
||||
// @see file_file_download()
|
||||
|
||||
// Find out if any editor-backed field contains the file.
|
||||
$usage_list = \Drupal::service('file.usage')->listUsage($file);
|
||||
|
||||
// Stop processing if there are no references in order to avoid returning
|
||||
// headers for files controlled by other modules. Make an exception for
|
||||
// temporary files where the host entity has not yet been saved (for example,
|
||||
// an image preview on a node creation form) in which case, allow download by
|
||||
// the file's owner.
|
||||
if (empty($usage_list['editor']) && ($file->isPermanent() || $file->getOwnerId() != \Drupal::currentUser()->id())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Editor.module MUST NOT call $file->access() here (like file_file_download()
|
||||
// does) as checking the 'download' access to a file entity would end up in
|
||||
// FileAccessControlHandler->checkAccess() and ->getFileReferences(), which
|
||||
// calls file_get_file_references(). This latter one would allow downloading
|
||||
// files only handled by the file.module, which is exactly not the case right
|
||||
// here. So instead we must check if the current user is allowed to view any
|
||||
// of the entities that reference the image using the 'editor' module.
|
||||
if ($file->isPermanent()) {
|
||||
$referencing_entity_is_accessible = FALSE;
|
||||
$references = empty($usage_list['editor']) ? [] : $usage_list['editor'];
|
||||
foreach ($references as $entity_type => $entity_ids) {
|
||||
$referencing_entities = entity_load_multiple($entity_type, $entity_ids);
|
||||
/** @var \Drupal\Core\Entity\EntityInterface $referencing_entity */
|
||||
foreach ($referencing_entities as $referencing_entity) {
|
||||
if ($referencing_entity->access('view', NULL, TRUE)->isAllowed()) {
|
||||
$referencing_entity_is_accessible = TRUE;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$referencing_entity_is_accessible) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Access is granted.
|
||||
$headers = file_get_content_headers($file);
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all files referenced (data-entity-uuid) by formatted text fields.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\editor\Tests;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests Editor module's file reference filter with private files.
|
||||
*
|
||||
* @group editor
|
||||
*/
|
||||
class EditorPrivateFileReferenceFilterTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
// Needed for the config: this is the only module in core that utilizes the
|
||||
// functionality in editor.module to be tested, and depends on that.
|
||||
'ckeditor',
|
||||
// Depends on filter.module (indirectly).
|
||||
'node',
|
||||
// Pulls in the config we're using during testing which create a text format
|
||||
// - with the filter_html_image_secure filter DISABLED,
|
||||
// - with the editor set to CKEditor,
|
||||
// - with drupalimage.image_upload.scheme set to 'private',
|
||||
// - with drupalimage.image_upload.directory set to ''.
|
||||
'editor_private_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* Tests the editor file reference filter with private files.
|
||||
*/
|
||||
function testEditorPrivateFileReferenceFilter() {
|
||||
$author = $this->drupalCreateUser();
|
||||
$this->drupalLogin($author);
|
||||
|
||||
// Create a content type with a body field.
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create a file in the 'private:// ' stream.
|
||||
$filename = 'test.png';
|
||||
$src = '/system/files/' . $filename;
|
||||
/** @var \Drupal\file\FileInterface $file */
|
||||
$file = File::create([
|
||||
'uri' => 'private://' . $filename,
|
||||
]);
|
||||
$file->setTemporary();
|
||||
$file->setOwner($author);
|
||||
// Create the file itself.
|
||||
file_put_contents($file->getFileUri(), $this->randomString());
|
||||
$file->save();
|
||||
|
||||
// The image should be visible for its author.
|
||||
$this->drupalGet($src);
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
// The not-yet-permanent image should NOT be visible for anonymous.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet($src);
|
||||
$this->assertSession()->statusCodeEquals(403);
|
||||
|
||||
// Resave the file to be permanent.
|
||||
$file->setPermanent();
|
||||
$file->save();
|
||||
|
||||
// Create a node with its body field properly pointing to the just-created
|
||||
// file.
|
||||
$node = $this->drupalCreateNode([
|
||||
'type' => 'page',
|
||||
'body' => [
|
||||
'value' => '<img alt="alt" data-entity-type="file" data-entity-uuid="' . $file->uuid() . '" src="' . $src . '" />',
|
||||
'format' => 'private_images',
|
||||
],
|
||||
'uid' => $author->id(),
|
||||
]);
|
||||
|
||||
// Do the actual test. The image should be visible for anonymous users,
|
||||
// because they can view the referencing entity.
|
||||
$this->drupalGet($node->toUrl());
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->drupalGet($src);
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
|
||||
// Disallow anonymous users to view the entity, which then should also
|
||||
// disallow them to view the image.
|
||||
Role::load(RoleInterface::ANONYMOUS_ID)
|
||||
->revokePermission('access content')
|
||||
->save();
|
||||
$this->drupalGet($node->toUrl());
|
||||
$this->assertSession()->statusCodeEquals(403);
|
||||
$this->drupalGet($src);
|
||||
$this->assertSession()->statusCodeEquals(403);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
format: private_images
|
||||
status: true
|
||||
langcode: en
|
||||
editor: ckeditor
|
||||
settings:
|
||||
toolbar:
|
||||
rows:
|
||||
-
|
||||
-
|
||||
name: Media
|
||||
items:
|
||||
- DrupalImage
|
||||
-
|
||||
name: Tools
|
||||
items:
|
||||
- Source
|
||||
plugins:
|
||||
language:
|
||||
language_list: un
|
||||
stylescombo:
|
||||
styles: ''
|
||||
image_upload:
|
||||
status: true
|
||||
scheme: private
|
||||
directory: ''
|
||||
max_size: ''
|
||||
max_dimensions:
|
||||
width: null
|
||||
height: null
|
||||
dependencies:
|
||||
config:
|
||||
- filter.format.private_images
|
||||
module:
|
||||
- ckeditor
|
|
@ -0,0 +1,23 @@
|
|||
format: private_images
|
||||
name: 'Private images'
|
||||
status: true
|
||||
langcode: en
|
||||
filters:
|
||||
editor_file_reference:
|
||||
id: editor_file_reference
|
||||
provider: editor
|
||||
status: true
|
||||
weight: 0
|
||||
settings: { }
|
||||
filter_html:
|
||||
id: filter_html
|
||||
provider: filter
|
||||
status: false
|
||||
weight: -10
|
||||
settings:
|
||||
allowed_html: '<img src alt data-entity-type data-entity-uuid>'
|
||||
filter_html_help: true
|
||||
filter_html_nofollow: false
|
||||
dependencies:
|
||||
module:
|
||||
- editor
|
|
@ -0,0 +1,9 @@
|
|||
name: 'Text Editor Private test'
|
||||
type: module
|
||||
description: 'Support module for the Text Editor Private module tests.'
|
||||
core: 8.x
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- filter
|
||||
- ckeditor
|
|
@ -15,105 +15,101 @@ process:
|
|||
langcode: 'constants/langcode'
|
||||
field_name: field_name
|
||||
type:
|
||||
-
|
||||
plugin: field_type
|
||||
source:
|
||||
- type
|
||||
- widget_type
|
||||
map:
|
||||
number_integer:
|
||||
number: integer
|
||||
optionwidgets_select: list_integer
|
||||
optionwidgets_buttons: list_integer
|
||||
optionwidgets_onoff: boolean
|
||||
number_decimal:
|
||||
number: decimal
|
||||
optionwidgets_select: list_float
|
||||
optionwidgets_buttons: list_float
|
||||
optionwidgets_onoff: boolean
|
||||
number_float:
|
||||
number: float
|
||||
optionwidgets_select: list_float
|
||||
optionwidgets_buttons: list_float
|
||||
optionwidgets_onoff: boolean
|
||||
email:
|
||||
email_textfield: email
|
||||
filefield:
|
||||
imagefield_widget: image
|
||||
filefield_widget: file
|
||||
date:
|
||||
date_select: datetime
|
||||
datestamp:
|
||||
date_select: datetime
|
||||
datetime:
|
||||
date_select: datetime
|
||||
fr_phone:
|
||||
phone_textfield: telephone
|
||||
be_phone:
|
||||
phone_textfield: telephone
|
||||
it_phone:
|
||||
phone_textfield: telephone
|
||||
el_phone:
|
||||
phone_textfield: telephone
|
||||
ch_phone:
|
||||
phone_textfield: telephone
|
||||
ca_phone:
|
||||
phone_textfield: telephone
|
||||
cr_phone:
|
||||
phone_textfield: telephone
|
||||
pa_phone:
|
||||
phone_textfield: telephone
|
||||
gb_phone:
|
||||
phone_textfield: telephone
|
||||
ru_phone:
|
||||
phone_textfield: telephone
|
||||
ua_phone:
|
||||
phone_textfield: telephone
|
||||
es_phone:
|
||||
phone_textfield: telephone
|
||||
au_phone:
|
||||
phone_textfield: telephone
|
||||
cs_phone:
|
||||
phone_textfield: telephone
|
||||
hu_phone:
|
||||
phone_textfield: telephone
|
||||
pl_phone:
|
||||
phone_textfield: telephone
|
||||
nl_phone:
|
||||
phone_textfield: telephone
|
||||
se_phone:
|
||||
phone_textfield: telephone
|
||||
za_phone:
|
||||
phone_textfield: telephone
|
||||
il_phone:
|
||||
phone_textfield: telephone
|
||||
nz_phone:
|
||||
phone_textfield: telephone
|
||||
br_phone:
|
||||
phone_textfield: telephone
|
||||
cl_phone:
|
||||
phone_textfield: telephone
|
||||
cn_phone:
|
||||
phone_textfield: telephone
|
||||
hk_phone:
|
||||
phone_textfield: telephone
|
||||
mo_phone:
|
||||
phone_textfield: telephone
|
||||
ph_phone:
|
||||
phone_textfield: telephone
|
||||
sg_phone:
|
||||
phone_textfield: telephone
|
||||
jo_phone:
|
||||
phone_textfield: telephone
|
||||
eg_phone:
|
||||
phone_textfield: telephone
|
||||
pk_phone:
|
||||
phone_textfield: telephone
|
||||
int_phone:
|
||||
phone_textfield: telephone
|
||||
-
|
||||
plugin: skip_on_empty
|
||||
method: row
|
||||
plugin: field_type
|
||||
source:
|
||||
- type
|
||||
- widget_type
|
||||
map:
|
||||
number_integer:
|
||||
number: integer
|
||||
optionwidgets_select: list_integer
|
||||
optionwidgets_buttons: list_integer
|
||||
optionwidgets_onoff: boolean
|
||||
number_decimal:
|
||||
number: decimal
|
||||
optionwidgets_select: list_float
|
||||
optionwidgets_buttons: list_float
|
||||
optionwidgets_onoff: boolean
|
||||
number_float:
|
||||
number: float
|
||||
optionwidgets_select: list_float
|
||||
optionwidgets_buttons: list_float
|
||||
optionwidgets_onoff: boolean
|
||||
email:
|
||||
email_textfield: email
|
||||
filefield:
|
||||
imagefield_widget: image
|
||||
filefield_widget: file
|
||||
date:
|
||||
date_select: datetime
|
||||
datestamp:
|
||||
date_select: datetime
|
||||
datetime:
|
||||
date_select: datetime
|
||||
fr_phone:
|
||||
phone_textfield: telephone
|
||||
be_phone:
|
||||
phone_textfield: telephone
|
||||
it_phone:
|
||||
phone_textfield: telephone
|
||||
el_phone:
|
||||
phone_textfield: telephone
|
||||
ch_phone:
|
||||
phone_textfield: telephone
|
||||
ca_phone:
|
||||
phone_textfield: telephone
|
||||
cr_phone:
|
||||
phone_textfield: telephone
|
||||
pa_phone:
|
||||
phone_textfield: telephone
|
||||
gb_phone:
|
||||
phone_textfield: telephone
|
||||
ru_phone:
|
||||
phone_textfield: telephone
|
||||
ua_phone:
|
||||
phone_textfield: telephone
|
||||
es_phone:
|
||||
phone_textfield: telephone
|
||||
au_phone:
|
||||
phone_textfield: telephone
|
||||
cs_phone:
|
||||
phone_textfield: telephone
|
||||
hu_phone:
|
||||
phone_textfield: telephone
|
||||
pl_phone:
|
||||
phone_textfield: telephone
|
||||
nl_phone:
|
||||
phone_textfield: telephone
|
||||
se_phone:
|
||||
phone_textfield: telephone
|
||||
za_phone:
|
||||
phone_textfield: telephone
|
||||
il_phone:
|
||||
phone_textfield: telephone
|
||||
nz_phone:
|
||||
phone_textfield: telephone
|
||||
br_phone:
|
||||
phone_textfield: telephone
|
||||
cl_phone:
|
||||
phone_textfield: telephone
|
||||
cn_phone:
|
||||
phone_textfield: telephone
|
||||
hk_phone:
|
||||
phone_textfield: telephone
|
||||
mo_phone:
|
||||
phone_textfield: telephone
|
||||
ph_phone:
|
||||
phone_textfield: telephone
|
||||
sg_phone:
|
||||
phone_textfield: telephone
|
||||
jo_phone:
|
||||
phone_textfield: telephone
|
||||
eg_phone:
|
||||
phone_textfield: telephone
|
||||
pk_phone:
|
||||
phone_textfield: telephone
|
||||
int_phone:
|
||||
phone_textfield: telephone
|
||||
cardinality:
|
||||
plugin: static_map
|
||||
bypass: true
|
||||
|
@ -126,6 +122,5 @@ process:
|
|||
source:
|
||||
- '@type'
|
||||
- global_settings
|
||||
|
||||
destination:
|
||||
plugin: md_entity:field_storage_config
|
||||
|
|
|
@ -21,8 +21,6 @@ class FieldInstancePerFormDisplay extends DrupalSqlBase {
|
|||
$rows = array();
|
||||
$result = $this->prepareQuery()->execute();
|
||||
while ($field_row = $result->fetchAssoc()) {
|
||||
$field_row['display_settings'] = unserialize($field_row['display_settings']);
|
||||
$field_row['widget_settings'] = unserialize($field_row['widget_settings']);
|
||||
$bundle = $field_row['type_name'];
|
||||
$field_name = $field_row['field_name'];
|
||||
|
||||
|
@ -34,7 +32,8 @@ class FieldInstancePerFormDisplay extends DrupalSqlBase {
|
|||
$rows[$index]['module'] = $field_row['module'];
|
||||
$rows[$index]['weight'] = $field_row['weight'];
|
||||
$rows[$index]['widget_type'] = $field_row['widget_type'];
|
||||
$rows[$index]['widget_settings'] = $field_row['widget_settings'];
|
||||
$rows[$index]['widget_settings'] = unserialize($field_row['widget_settings']);
|
||||
$rows[$index]['display_settings'] = unserialize($field_row['display_settings']);
|
||||
}
|
||||
|
||||
return new \ArrayIterator($rows);
|
||||
|
|
|
@ -165,4 +165,30 @@ class NestedFormTest extends FieldTestBase {
|
|||
$this->assertFieldValues($entity_2, 'field_unlimited', array(13, 14, 15));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests entity level validation within subforms.
|
||||
*/
|
||||
public function testNestedEntityFormEntityLevelValidation() {
|
||||
// Create two entities.
|
||||
$storage = $this->container->get('entity_type.manager')
|
||||
->getStorage('entity_test_constraints');
|
||||
|
||||
$entity_1 = $storage->create();
|
||||
$entity_1->save();
|
||||
|
||||
$entity_2 = $storage->create();
|
||||
$entity_2->save();
|
||||
|
||||
// Display the 'combined form'.
|
||||
$this->drupalGet("test-entity-constraints/nested/{$entity_1->id()}/{$entity_2->id()}");
|
||||
$this->assertFieldByName('entity_2[changed]', 0, 'Entity 2: changed value appears correctly in the form.');
|
||||
|
||||
// Submit the form and check that the entities are updated accordingly.
|
||||
$edit = ['entity_2[changed]' => REQUEST_TIME - 86400];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
$elements = $this->cssSelect('.entity-2.error');
|
||||
$this->assertEqual(1, count($elements), 'The whole nested entity form has been correctly flagged with an error class.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,3 +11,17 @@ field_test.entity_nested_form:
|
|||
type: 'entity:entity_test'
|
||||
requirements:
|
||||
_permission: 'administer entity_test content'
|
||||
|
||||
field_test.entity_constraints_nested_form:
|
||||
path: '/test-entity-constraints/nested/{entity_1}/{entity_2}'
|
||||
defaults:
|
||||
_title: 'Nested entity form'
|
||||
_form: '\Drupal\field_test\Form\NestedEntityTestForm'
|
||||
options:
|
||||
parameters:
|
||||
entity_1:
|
||||
type: 'entity:entity_test_constraints'
|
||||
entity_2:
|
||||
type: 'entity:entity_test_constraints'
|
||||
requirements:
|
||||
_permission: 'administer entity_test content'
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\field_test\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityChangedInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
@ -33,16 +34,26 @@ class NestedEntityTestForm extends FormBase {
|
|||
$form_state->set('entity_2', $entity_2);
|
||||
$form_display_2 = EntityFormDisplay::collectRenderDisplay($entity_2, 'default');
|
||||
$form_state->set('form_display_2', $form_display_2);
|
||||
$form['entity_2'] = array(
|
||||
$form['entity_2'] = [
|
||||
'#type' => 'details',
|
||||
'#title' => t('Second entity'),
|
||||
'#tree' => TRUE,
|
||||
'#parents' => array('entity_2'),
|
||||
'#parents' => ['entity_2'],
|
||||
'#weight' => 50,
|
||||
);
|
||||
'#attributes' => ['class' => ['entity-2']]
|
||||
];
|
||||
|
||||
$form_display_2->buildForm($entity_2, $form['entity_2'], $form_state);
|
||||
|
||||
if ($entity_2 instanceof EntityChangedInterface) {
|
||||
// Changed must be sent to the client, for later overwrite error checking.
|
||||
// @see Drupal\field\Tests\NestedFormTest::testNestedEntityFormEntityLevelValidation()
|
||||
$form['entity_2']['changed'] = [
|
||||
'#type' => 'hidden',
|
||||
'#default_value' => $entity_1->getChangedTime(),
|
||||
];
|
||||
}
|
||||
|
||||
$form['save'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save'),
|
||||
|
@ -65,7 +76,16 @@ class NestedEntityTestForm extends FormBase {
|
|||
$entity_2 = $form_state->get('entity_2');
|
||||
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display_2 */
|
||||
$form_display_2 = $form_state->get('form_display_2');
|
||||
$form_display_2->extractFormValues($entity_2, $form['entity_2'], $form_state);
|
||||
$extracted = $form_display_2->extractFormValues($entity_2, $form['entity_2'], $form_state);
|
||||
// Extract the values of fields that are not rendered through widgets, by
|
||||
// simply copying from top-level form values. This leaves the fields that
|
||||
// are not being edited within this form untouched.
|
||||
// @see Drupal\field\Tests\NestedFormTest::testNestedEntityFormEntityLevelValidation()
|
||||
foreach ($form_state->getValues()['entity_2'] as $name => $values) {
|
||||
if ($entity_2->hasField($name) && !isset($extracted[$name])) {
|
||||
$entity_2->set($name, $values);
|
||||
}
|
||||
}
|
||||
$form_display_2->validateFormValues($entity_2, $form['entity_2'], $form_state);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,19 @@ class MigrateFieldInstanceTest extends MigrateDrupal7TestBase {
|
|||
$this->assertIdentical($expected_entity_type . '.' . $expected_name, $field->getFieldStorageDefinition()->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the settings of a link field config entity.
|
||||
*
|
||||
* @param $id
|
||||
* The entity ID in the form ENTITY_TYPE.BUNDLE.FIELD_NAME.
|
||||
* @param $title_setting
|
||||
* The expected title setting.
|
||||
*/
|
||||
protected function assertLinkFields($id, $title_setting) {
|
||||
$field = FieldConfig::load($id);
|
||||
$this->assertSame($title_setting, $field->getSetting('title'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migrating D7 field instances to field_config entities.
|
||||
*/
|
||||
|
@ -131,6 +144,10 @@ class MigrateFieldInstanceTest extends MigrateDrupal7TestBase {
|
|||
$this->assertEntity('node.test_content_type.field_text', 'Text', 'text', FALSE);
|
||||
$this->assertEntity('comment.comment_node_test_content_type.field_integer', 'Integer', 'integer', FALSE);
|
||||
$this->assertEntity('user.user.field_file', 'File', 'file', FALSE);
|
||||
|
||||
$this->assertLinkFields('node.test_content_type.field_link', DRUPAL_OPTIONAL);
|
||||
$this->assertLinkFields('node.article.field_link', DRUPAL_DISABLED);
|
||||
$this->assertLinkFields('node.blog.field_link', DRUPAL_REQUIRED);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests d6_field_instance_per_form_display source plugin.
|
||||
*
|
||||
* @covers \Drupal\field\Plugin\migrate\source\d6\FieldInstancePerFormDisplay
|
||||
* @group field
|
||||
*/
|
||||
class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['field', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [
|
||||
[
|
||||
'source_data' => [],
|
||||
'expected_data' => [],
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'display_settings' => [],
|
||||
'widget_settings' => [],
|
||||
'type_name' => 'story',
|
||||
'widget_active' => TRUE,
|
||||
'field_name' => 'field_test_filefield',
|
||||
'type' => 'filefield',
|
||||
'module' => 'filefield',
|
||||
'weight' => '8',
|
||||
'widget_type' => 'filefield_widget',
|
||||
],
|
||||
];
|
||||
|
||||
// The source data.
|
||||
$empty_array = serialize([]);
|
||||
$tests[0]['source_data']['content_node_field'] = [
|
||||
[
|
||||
'field_name' => 'field_test_filefield',
|
||||
'type' => 'filefield',
|
||||
'global_settings' => $empty_array,
|
||||
'required' => '0',
|
||||
'multiple' => '0',
|
||||
'db_storage' => '1',
|
||||
'module' => 'filefield',
|
||||
'db_columns' => $empty_array,
|
||||
'active' => '1',
|
||||
'locked' => '0',
|
||||
]
|
||||
];
|
||||
$tests[0]['source_data']['content_node_field_instance'] = [
|
||||
[
|
||||
'field_name' => 'field_test_filefield',
|
||||
'type_name' => 'story',
|
||||
'weight' => '8',
|
||||
'label' => 'File Field',
|
||||
'widget_type' => 'filefield_widget',
|
||||
'widget_settings' => $empty_array,
|
||||
'display_settings' => $empty_array,
|
||||
'description' => 'An example image field.',
|
||||
'widget_module' => 'filefield',
|
||||
'widget_active' => '1',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 fields per view mode source plugin.
|
||||
*
|
||||
* @covers \Drupal\field\Plugin\migrate\source\d6\FieldInstancePerViewMode
|
||||
* @group field
|
||||
*/
|
||||
class FieldInstancePerViewModeTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['field', 'migrate_drupal', 'node', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [
|
||||
[
|
||||
'source_data' => [],
|
||||
'expected_data' => [],
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'entity_type' => 'node',
|
||||
'view_mode' => 4,
|
||||
'type_name' => 'article',
|
||||
'field_name' => 'field_test',
|
||||
'type' => 'text',
|
||||
'module' => 'text',
|
||||
'weight' => 1,
|
||||
'label' => 'above',
|
||||
'display_settings' => [
|
||||
'weight' => 1,
|
||||
'parent' => '',
|
||||
'label' => [
|
||||
'format' => 'above',
|
||||
],
|
||||
4 => [
|
||||
'format' => 'trimmed',
|
||||
'exclude' => 0,
|
||||
],
|
||||
],
|
||||
'widget_settings' => [],
|
||||
],
|
||||
[
|
||||
'entity_type' => 'node',
|
||||
'view_mode' => 'teaser',
|
||||
'type_name' => 'story',
|
||||
'field_name' => 'field_test',
|
||||
'type' => 'text',
|
||||
'module' => 'text',
|
||||
'weight' => 2,
|
||||
'label' => 'above',
|
||||
'display_settings' => [
|
||||
'weight' => 1,
|
||||
'parent' => '',
|
||||
'label' => [
|
||||
'format' => 'above',
|
||||
],
|
||||
'teaser' => [
|
||||
'format' => 'trimmed',
|
||||
'exclude' => 0,
|
||||
],
|
||||
],
|
||||
'widget_settings' => [],
|
||||
],
|
||||
];
|
||||
|
||||
// The source data.
|
||||
foreach ($tests[0]['expected_data'] as $k => $field_view_mode) {
|
||||
// These are stored as serialized strings.
|
||||
$field_view_mode['display_settings'] = serialize($field_view_mode['display_settings']);
|
||||
$field_view_mode['widget_settings'] = serialize($field_view_mode['widget_settings']);
|
||||
|
||||
$tests[0]['source_data']['content_node_field'][] = [
|
||||
'field_name' => $field_view_mode['field_name'],
|
||||
'type' => $field_view_mode['type'],
|
||||
'module' => $field_view_mode['module'],
|
||||
];
|
||||
unset($field_view_mode['type'], $field_view_mode['module']);
|
||||
|
||||
$tests[0]['source_data']['content_node_field_instance'][] = $field_view_mode;
|
||||
|
||||
// Update the expected display settings.
|
||||
$tests[0]['expected_data'][$k]['display_settings'] = $tests[0]['expected_data'][$k]['display_settings'][$field_view_mode['view_mode']];
|
||||
}
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 field instance source plugin.
|
||||
*
|
||||
* @covers \Drupal\field\Plugin\migrate\source\d6\FieldInstance
|
||||
* @group field
|
||||
*/
|
||||
class FieldInstanceTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['field', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [
|
||||
[
|
||||
'source_data' => [],
|
||||
'expected_data' => [],
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'field_name' => 'field_body',
|
||||
'type_name' => 'page',
|
||||
'weight' => 1,
|
||||
'label' => 'body',
|
||||
'widget_type' => 'text_textarea',
|
||||
'description' => '',
|
||||
'widget_module' => 'text',
|
||||
'widget_active' => 1,
|
||||
'required' => 1,
|
||||
'active' => 1,
|
||||
'global_settings' => [],
|
||||
'widget_settings' => [
|
||||
'rows' => 5,
|
||||
'size' => 60,
|
||||
'default_value' => [
|
||||
[
|
||||
'value' => '',
|
||||
'_error_element' => 'default_value_widget][field_body][0][value',
|
||||
'default_value_php' => '',
|
||||
],
|
||||
],
|
||||
],
|
||||
'display_settings' => [
|
||||
'label' => [
|
||||
'format' => 'above',
|
||||
'exclude' => 0,
|
||||
],
|
||||
'teaser' => [
|
||||
'format' => 'default',
|
||||
'exclude' => 0,
|
||||
],
|
||||
'full' => [
|
||||
'format' => 'default',
|
||||
'exclude' => 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['content_node_field_instance'] = array_map(
|
||||
function (array $row) {
|
||||
$row['widget_settings'] = serialize($row['widget_settings']);
|
||||
$row['display_settings'] = serialize($row['display_settings']);
|
||||
$row['global_settings'] = serialize($row['global_settings']);
|
||||
return $row;
|
||||
},
|
||||
$tests[0]['expected_data']
|
||||
);
|
||||
$tests[0]['source_data']['content_node_field'] = [
|
||||
[
|
||||
'field_name' => 'field_body',
|
||||
'required' => 1,
|
||||
'type' => 'text',
|
||||
'active' => 1,
|
||||
'global_settings' => serialize([]),
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 field source plugin.
|
||||
*
|
||||
* @covers \Drupal\field\Plugin\migrate\source\d6\Field
|
||||
* @group field
|
||||
*/
|
||||
class FieldTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['field', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [
|
||||
[
|
||||
'source_data' => [],
|
||||
'expected_data' => [],
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'field_name' => 'field_body',
|
||||
'type' => 'text',
|
||||
'global_settings' => [
|
||||
'text_processing' => 0,
|
||||
'max_length' => '',
|
||||
'allowed_values' => '',
|
||||
'allowed_values_php' => '',
|
||||
],
|
||||
'required' => 0,
|
||||
'multiple' => 0,
|
||||
'db_storage' => 1,
|
||||
'module' => 'text',
|
||||
'db_columns' => [
|
||||
'value' => [
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
'not null' => '',
|
||||
'sortable' => 1,
|
||||
'views' => 1,
|
||||
],
|
||||
],
|
||||
'active' => 1,
|
||||
'locked' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['content_node_field'] = array_map(
|
||||
function (array $row) {
|
||||
$row['global_settings'] = serialize($row['global_settings']);
|
||||
$row['db_columns'] = serialize($row['db_columns']);
|
||||
return $row;
|
||||
},
|
||||
$tests[0]['expected_data']
|
||||
);
|
||||
$tests[0]['source_data']['content_node_field_instance'] = [
|
||||
[
|
||||
'widget_type' => 'text_textarea',
|
||||
'field_name' => 'field_body',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,84 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Unit\Plugin\migrate\source\d7;
|
||||
namespace Drupal\Tests\field\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D7 field instance per form display source plugin.
|
||||
*
|
||||
* @covers \Drupal\field\Plugin\migrate\source\d7\FieldInstancePerFormDisplay
|
||||
* @group field
|
||||
*/
|
||||
class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\field\Plugin\migrate\source\d7\FieldInstancePerFormDisplay';
|
||||
|
||||
protected $migrationConfiguration = array(
|
||||
'id' => 'test_fieldinstance',
|
||||
'source' => array(
|
||||
'plugin' => 'd7_field_instance_per_form_display',
|
||||
),
|
||||
);
|
||||
|
||||
// We need to set up the database contents; it's easier to do that below.
|
||||
// These are sample result queries.
|
||||
protected $expectedResults = array(
|
||||
array(
|
||||
'field_name' => 'body',
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'page',
|
||||
'widget_settings' => array(
|
||||
),
|
||||
'display_settings' => array(
|
||||
),
|
||||
'description' => '',
|
||||
'required' => FALSE,
|
||||
'global_settings' => array(),
|
||||
),
|
||||
array(
|
||||
'field_name' => 'field_file',
|
||||
'entity_type' => 'user',
|
||||
'bundle' => 'user',
|
||||
'widget_settings' => array(
|
||||
),
|
||||
'display_settings' => array(
|
||||
),
|
||||
'description' => '',
|
||||
'required' => FALSE,
|
||||
'global_settings' => array(),
|
||||
),
|
||||
array(
|
||||
'field_name' => 'field_integer',
|
||||
'entity_type' => 'comment',
|
||||
'bundle' => 'comment_node_test_content_type',
|
||||
'widget_settings' => array(
|
||||
),
|
||||
'display_settings' => array(
|
||||
),
|
||||
'description' => '',
|
||||
'required' => FALSE,
|
||||
'global_settings' => array(),
|
||||
),
|
||||
array(
|
||||
'field_name' => 'field_link',
|
||||
'entity_type' => 'taxonomy_term',
|
||||
'bundle' => 'test_vocabulary',
|
||||
'widget_settings' => array(
|
||||
),
|
||||
'display_settings' => array(
|
||||
),
|
||||
'description' => '',
|
||||
'required' => FALSE,
|
||||
'global_settings' => array(),
|
||||
),
|
||||
);
|
||||
class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* Prepopulate contents with results.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['field_config_instance'] = array(
|
||||
array(
|
||||
public static $modules = ['field', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [
|
||||
[
|
||||
'source_data' => [],
|
||||
'expected_data' => [],
|
||||
],
|
||||
];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['field_config_instance'] = [
|
||||
[
|
||||
'id' => '2',
|
||||
'field_id' => '2',
|
||||
'field_name' => 'body',
|
||||
|
@ -86,8 +38,8 @@ class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
|||
'bundle' => 'page',
|
||||
'data' => 'a:6:{s:5:"label";s:4:"Body";s:6:"widget";a:4:{s:4:"type";s:26:"text_textarea_with_summary";s:8:"settings";a:2:{s:4:"rows";i:20;s:12:"summary_rows";i:5;}s:6:"weight";i:-4;s:6:"module";s:4:"text";}s:8:"settings";a:3:{s:15:"display_summary";b:1;s:15:"text_processing";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:2:{s:7:"default";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:12:"text_default";s:8:"settings";a:0:{}s:6:"module";s:4:"text";s:6:"weight";i:0;}s:6:"teaser";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:23:"text_summary_or_trimmed";s:8:"settings";a:1:{s:11:"trim_length";i:600;}s:6:"module";s:4:"text";s:6:"weight";i:0;}}s:8:"required";b:0;s:11:"description";s:0:"";}',
|
||||
'deleted' => '0',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'id' => '33',
|
||||
'field_id' => '11',
|
||||
'field_name' => 'field_file',
|
||||
|
@ -95,8 +47,8 @@ class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
|||
'bundle' => 'user',
|
||||
'data' => 'a:6:{s:5:"label";s:4:"File";s:6:"widget";a:5:{s:6:"weight";s:1:"8";s:4:"type";s:12:"file_generic";s:6:"module";s:4:"file";s:6:"active";i:1;s:8:"settings";a:1:{s:18:"progress_indicator";s:8:"throbber";}}s:8:"settings";a:5:{s:14:"file_directory";s:0:"";s:15:"file_extensions";s:3:"txt";s:12:"max_filesize";s:0:"";s:17:"description_field";i:0;s:18:"user_register_form";i:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:12:"file_default";s:8:"settings";a:0:{}s:6:"module";s:4:"file";s:6:"weight";i:0;}}s:8:"required";i:0;s:11:"description";s:0:"";}',
|
||||
'deleted' => '0',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'id' => '32',
|
||||
'field_id' => '14',
|
||||
'field_name' => 'field_integer',
|
||||
|
@ -104,8 +56,8 @@ class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
|||
'bundle' => 'comment_node_test_content_type',
|
||||
'data' => 'a:7:{s:5:"label";s:7:"Integer";s:6:"widget";a:5:{s:6:"weight";s:1:"2";s:4:"type";s:6:"number";s:6:"module";s:6:"number";s:6:"active";i:0;s:8:"settings";a:0:{}}s:8:"settings";a:5:{s:3:"min";s:0:"";s:3:"max";s:0:"";s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:14:"number_integer";s:8:"settings";a:4:{s:18:"thousand_separator";s:1:" ";s:17:"decimal_separator";s:1:".";s:5:"scale";i:0;s:13:"prefix_suffix";b:1;}s:6:"module";s:6:"number";s:6:"weight";i:1;}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}',
|
||||
'deleted' => '0',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'id' => '25',
|
||||
'field_id' => '15',
|
||||
'field_name' => 'field_link',
|
||||
|
@ -113,10 +65,10 @@ class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
|||
'bundle' => 'test_vocabulary',
|
||||
'data' => 'a:7:{s:5:"label";s:4:"Link";s:6:"widget";a:5:{s:6:"weight";s:2:"10";s:4:"type";s:10:"link_field";s:6:"module";s:4:"link";s:6:"active";i:0;s:8:"settings";a:0:{}}s:8:"settings";a:12:{s:12:"absolute_url";i:1;s:12:"validate_url";i:1;s:3:"url";i:0;s:5:"title";s:8:"optional";s:11:"title_value";s:19:"Unused Static Title";s:27:"title_label_use_field_label";i:0;s:15:"title_maxlength";s:3:"128";s:7:"display";a:1:{s:10:"url_cutoff";s:2:"81";}s:10:"attributes";a:6:{s:6:"target";s:6:"_blank";s:3:"rel";s:8:"nofollow";s:18:"configurable_class";i:0;s:5:"class";s:7:"classes";s:18:"configurable_title";i:1;s:5:"title";s:0:"";}s:10:"rel_remove";s:19:"rel_remove_external";s:13:"enable_tokens";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:12:"link_default";s:6:"weight";s:1:"9";s:8:"settings";a:0:{}s:6:"module";s:4:"link";}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}',
|
||||
'deleted' => '0',
|
||||
),
|
||||
);
|
||||
$this->databaseContents['field_config'] = array(
|
||||
array(
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['field_config'] = [
|
||||
[
|
||||
'id' => '2',
|
||||
'field_name' => 'body',
|
||||
'type' => 'text_with_summary',
|
||||
|
@ -130,8 +82,8 @@ class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
|||
'cardinality' => '1',
|
||||
'translatable' => '0',
|
||||
'deleted' => '0',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'id' => '11',
|
||||
'field_name' => 'field_file',
|
||||
'type' => 'file',
|
||||
|
@ -145,8 +97,8 @@ class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
|||
'cardinality' => '1',
|
||||
'translatable' => '0',
|
||||
'deleted' => '0',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'id' => '14',
|
||||
'field_name' => 'field_integer',
|
||||
'type' => 'number_integer',
|
||||
|
@ -160,8 +112,8 @@ class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
|||
'cardinality' => '1',
|
||||
'translatable' => '0',
|
||||
'deleted' => '0',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'id' => '15',
|
||||
'field_name' => 'field_link',
|
||||
'type' => 'link_field',
|
||||
|
@ -175,10 +127,43 @@ class FieldInstancePerFormDisplayTest extends MigrateSqlSourceTestCase {
|
|||
'cardinality' => '1',
|
||||
'translatable' => '0',
|
||||
'deleted' => '0',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
parent::setUp();
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'field_name' => 'body',
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'page',
|
||||
'widget_settings' => [
|
||||
'rows' => 20,
|
||||
'summary_rows' => 5,
|
||||
],
|
||||
],
|
||||
[
|
||||
'field_name' => 'field_file',
|
||||
'entity_type' => 'user',
|
||||
'bundle' => 'user',
|
||||
'widget_settings' => [
|
||||
'progress_indicator' => 'throbber',
|
||||
],
|
||||
],
|
||||
[
|
||||
'field_name' => 'field_integer',
|
||||
'entity_type' => 'comment',
|
||||
'bundle' => 'comment_node_test_content_type',
|
||||
'widget_settings' => [],
|
||||
],
|
||||
[
|
||||
'field_name' => 'field_link',
|
||||
'entity_type' => 'taxonomy_term',
|
||||
'bundle' => 'test_vocabulary',
|
||||
'widget_settings' => [],
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue