Update to Drupal 8.0.6. For more information, see https://www.drupal.org/drupal-8.0.6-release-notes
This commit is contained in:
parent
4297c64508
commit
b11a755ba8
159 changed files with 2340 additions and 543 deletions
|
@ -12,7 +12,7 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Form controller for the aggregator feed edit forms.
|
||||
* Form handler for the aggregator feed edit forms.
|
||||
*/
|
||||
class FeedForm extends ContentEntityForm {
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use Drupal\Core\Url;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Render controller for aggregator feed items.
|
||||
* View builder handler for aggregator feeds.
|
||||
*/
|
||||
class FeedViewBuilder extends EntityViewBuilder {
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Drupal\aggregator;
|
|||
use Drupal\Core\Entity\EntityViewBuilder;
|
||||
|
||||
/**
|
||||
* Render controller for aggregator feed items.
|
||||
* View builder handler for aggregator feed items.
|
||||
*/
|
||||
class ItemViewBuilder extends EntityViewBuilder {
|
||||
|
||||
|
|
|
@ -125,14 +125,21 @@
|
|||
// Make our new row and select field.
|
||||
var row = $(this).closest('tr');
|
||||
var select = $(this);
|
||||
|
||||
// Find the correct region and insert the row as the last in the
|
||||
// region.
|
||||
table.find('.region-' + select[0].value + '-message').nextUntil('.region-message').eq(-1).before(row);
|
||||
|
||||
tableDrag.rowObject = new tableDrag.row(row[0]);
|
||||
var region_message = table.find('.region-' + select[0].value + '-message');
|
||||
var region_items = region_message.nextUntil('.region-message, .region-title');
|
||||
if (region_items.length) {
|
||||
region_items.last().after(row);
|
||||
}
|
||||
// We found that region_message is the last row.
|
||||
else {
|
||||
region_message.after(row);
|
||||
}
|
||||
updateBlockWeights(table, select[0].value);
|
||||
// Modify empty regions with added or removed fields.
|
||||
checkEmptyRegions(table, row);
|
||||
checkEmptyRegions(table, tableDrag.rowObject);
|
||||
// Update last placed block indication.
|
||||
updateLastPlaced(table, row);
|
||||
// Show unsaved changes warning.
|
||||
|
|
|
@ -74,7 +74,6 @@ process:
|
|||
help: help
|
||||
header: header
|
||||
footer: footer
|
||||
label: title
|
||||
weight: weight
|
||||
settings:
|
||||
plugin: block_settings
|
||||
|
@ -82,6 +81,7 @@ process:
|
|||
- '@plugin'
|
||||
- delta
|
||||
- settings
|
||||
- title
|
||||
visibility:
|
||||
plugin: block_visibility
|
||||
source:
|
||||
|
|
|
@ -75,7 +75,6 @@ process:
|
|||
help: help
|
||||
header: header
|
||||
footer: footer
|
||||
label: title
|
||||
weight: weight
|
||||
settings:
|
||||
plugin: block_settings
|
||||
|
@ -83,6 +82,7 @@ process:
|
|||
- '@plugin'
|
||||
- delta
|
||||
- settings
|
||||
- title
|
||||
visibility:
|
||||
plugin: block_visibility
|
||||
source:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\block\BlockInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
@ -24,8 +25,15 @@ class BlockSettings extends ProcessPluginBase {
|
|||
* Set the block configuration.
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($plugin, $delta, $old_settings) = $value;
|
||||
list($plugin, $delta, $old_settings, $title) = $value;
|
||||
$settings = array();
|
||||
$settings['label'] = $title;
|
||||
if ($title) {
|
||||
$settings['label_display'] = BlockInterface::BLOCK_LABEL_VISIBLE;
|
||||
}
|
||||
else {
|
||||
$settings['label_display'] = '0';
|
||||
}
|
||||
switch ($plugin) {
|
||||
case 'aggregator_feed_block':
|
||||
list(, $id) = explode('-', $delta);
|
||||
|
|
|
@ -69,14 +69,22 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
* The theme.
|
||||
* @param string $weight
|
||||
* The block weight.
|
||||
* @param string $label
|
||||
* The block label.
|
||||
* @param string $label_display
|
||||
* The block label display setting.
|
||||
*/
|
||||
public function assertEntity($id, $visibility, $region, $theme, $weight) {
|
||||
public function assertEntity($id, $visibility, $region, $theme, $weight, $label, $label_display) {
|
||||
$block = Block::load($id);
|
||||
$this->assertTrue($block instanceof Block);
|
||||
$this->assertIdentical($visibility, $block->getVisibility());
|
||||
$this->assertIdentical($region, $block->getRegion());
|
||||
$this->assertIdentical($theme, $block->getTheme());
|
||||
$this->assertIdentical($weight, $block->getWeight());
|
||||
|
||||
$config = $this->config('block.block.' . $id);
|
||||
$this->assertIdentical($label, $config->get('settings.label'));
|
||||
$this->assertIdentical($label_display, $config->get('settings.label_display'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,10 +99,10 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = TRUE;
|
||||
$visibility['request_path']['pages'] = "<front>\n/node/1\n/blog/*";
|
||||
$this->assertEntity('user', $visibility, 'sidebar_first', 'bartik', 0);
|
||||
$this->assertEntity('user', $visibility, 'sidebar_first', 'bartik', 0, '', '0');
|
||||
|
||||
$visibility = [];
|
||||
$this->assertEntity('user_1', $visibility, 'sidebar_first', 'bartik', 0);
|
||||
$this->assertEntity('user_1', $visibility, 'sidebar_first', 'bartik', 0, '', '0');
|
||||
|
||||
$visibility['user_role']['id'] = 'user_role';
|
||||
$roles['authenticated'] = 'authenticated';
|
||||
|
@ -102,7 +110,7 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
$context_mapping['user'] = '@user.current_user_context:current_user';
|
||||
$visibility['user_role']['context_mapping'] = $context_mapping;
|
||||
$visibility['user_role']['negate'] = FALSE;
|
||||
$this->assertEntity('user_2', $visibility, 'sidebar_second', 'bartik', -9);
|
||||
$this->assertEntity('user_2', $visibility, 'sidebar_second', 'bartik', -9, '', '0');
|
||||
|
||||
$visibility = [];
|
||||
$visibility['user_role']['id'] = 'user_role';
|
||||
|
@ -112,32 +120,32 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
$context_mapping['user'] = '@user.current_user_context:current_user';
|
||||
$visibility['user_role']['context_mapping'] = $context_mapping;
|
||||
$visibility['user_role']['negate'] = FALSE;
|
||||
$this->assertEntity('user_3', $visibility, 'sidebar_second', 'bartik', -6);
|
||||
$this->assertEntity('user_3', $visibility, 'sidebar_second', 'bartik', -6, '', '0');
|
||||
|
||||
// Check system block
|
||||
$visibility = [];
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = TRUE;
|
||||
$visibility['request_path']['pages'] = '/node/1';
|
||||
$this->assertEntity('system', $visibility, 'footer', 'bartik', -5);
|
||||
$this->assertEntity('system', $visibility, 'footer', 'bartik', -5, '', '0');
|
||||
|
||||
// Check menu blocks
|
||||
$visibility = [];
|
||||
$this->assertEntity('menu', $visibility, 'header', 'bartik', -5);
|
||||
$this->assertEntity('menu', $visibility, 'header', 'bartik', -5, '', '0');
|
||||
|
||||
// Check custom blocks
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = FALSE;
|
||||
$visibility['request_path']['pages'] = '<front>';
|
||||
$this->assertEntity('block', $visibility, 'content', 'bartik', 0);
|
||||
$this->assertEntity('block', $visibility, 'content', 'bartik', 0, 'Static Block', 'visible');
|
||||
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = FALSE;
|
||||
$visibility['request_path']['pages'] = '/node';
|
||||
$this->assertEntity('block_1', $visibility, 'sidebar_second', 'bluemarine', -4);
|
||||
$this->assertEntity('block_1', $visibility, 'sidebar_second', 'bluemarine', -4, 'Another Static Block', 'visible');
|
||||
|
||||
$visibility = [];
|
||||
$this->assertEntity('block_2', $visibility, 'right', 'test_theme', -7);
|
||||
$this->assertEntity('block_2', $visibility, 'right', 'test_theme', -7, '', '0');
|
||||
|
||||
// Custom block with php code is not migrated.
|
||||
$block = Block::load('block_3');
|
||||
|
|
|
@ -77,8 +77,13 @@ class MigrateBlockTest extends MigrateDrupal7TestBase {
|
|||
* The theme.
|
||||
* @param string $weight
|
||||
* The block weight.
|
||||
* @param string $label
|
||||
* The block label.
|
||||
* @param string $label_display
|
||||
* The block label display setting.
|
||||
|
||||
*/
|
||||
public function assertEntity($id, $plugin_id, array $roles, $pages, $region, $theme, $weight) {
|
||||
public function assertEntity($id, $plugin_id, array $roles, $pages, $region, $theme, $weight, $label, $label_display) {
|
||||
$block = Block::load($id);
|
||||
$this->assertTrue($block instanceof Block);
|
||||
/** @var \Drupal\block\BlockInterface $block */
|
||||
|
@ -96,24 +101,28 @@ class MigrateBlockTest extends MigrateDrupal7TestBase {
|
|||
$this->assertIdentical($region, $block->getRegion());
|
||||
$this->assertIdentical($theme, $block->getTheme());
|
||||
$this->assertIdentical($weight, $block->getWeight());
|
||||
|
||||
$config = $this->config('block.block.' . $id);
|
||||
$this->assertIdentical($label, $config->get('settings.label'));
|
||||
$this->assertIdentical($label_display, $config->get('settings.label_display'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block migration.
|
||||
*/
|
||||
public function testBlockMigration() {
|
||||
$this->assertEntity('bartik_system_main', 'system_main_block', [], '', 'content', 'bartik', 0);
|
||||
$this->assertEntity('bartik_search_form', 'search_form_block', [], '', 'sidebar_first', 'bartik', -1);
|
||||
$this->assertEntity('bartik_user_login', 'user_login_block', [], '', 'sidebar_first', 'bartik', 0);
|
||||
$this->assertEntity('bartik_system_powered-by', 'system_powered_by_block', [], '', 'footer', 'bartik', 10);
|
||||
$this->assertEntity('seven_system_main', 'system_main_block', [], '', 'content', 'seven', 0);
|
||||
$this->assertEntity('seven_user_login', 'user_login_block', [], '', 'content', 'seven', 10);
|
||||
$this->assertEntity('bartik_system_main', 'system_main_block', [], '', 'content', 'bartik', 0, '', '0');
|
||||
$this->assertEntity('bartik_search_form', 'search_form_block', [], '', 'sidebar_first', 'bartik', -1, '', '0');
|
||||
$this->assertEntity('bartik_user_login', 'user_login_block', [], '', 'sidebar_first', 'bartik', 0, '', '0');
|
||||
$this->assertEntity('bartik_system_powered-by', 'system_powered_by_block', [], '', 'footer', 'bartik', 10, '', '0');
|
||||
$this->assertEntity('seven_system_main', 'system_main_block', [], '', 'content', 'seven', 0, '', '0');
|
||||
$this->assertEntity('seven_user_login', 'user_login_block', [], '', 'content', 'seven', 10, '', '0');
|
||||
|
||||
// The d7_custom_block migration should have migrated a block containing a
|
||||
// mildly amusing limerick. We'll need its UUID to determine
|
||||
// bartik_block_1's plugin ID.
|
||||
$uuid = BlockContent::load(1)->uuid();
|
||||
$this->assertEntity('bartik_block_1', 'block_content:' . $uuid, ['authenticated'], '', 'highlighted', 'bartik', 0);
|
||||
$this->assertEntity('bartik_block_1', 'block_content:' . $uuid, ['authenticated'], '', 'highlighted', 'bartik', 0, 'Mildly amusing limerick of the day', 'visible');
|
||||
|
||||
// Assert that disabled blocks (or enabled blocks whose plugin IDs could
|
||||
// be resolved) did not migrate.
|
||||
|
|
|
@ -16,7 +16,7 @@ use Drupal\Core\Language\LanguageManagerInterface;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Form controller for the custom block edit forms.
|
||||
* Form handler for the custom block edit forms.
|
||||
*/
|
||||
class BlockContentForm extends ContentEntityForm {
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use Drupal\Core\Entity\EntityInterface;
|
|||
use Drupal\Core\Entity\EntityViewBuilder;
|
||||
|
||||
/**
|
||||
* Render controller for custom blocks.
|
||||
* View builder handler for custom blocks.
|
||||
*/
|
||||
class BlockContentViewBuilder extends EntityViewBuilder {
|
||||
|
||||
|
|
|
@ -587,18 +587,20 @@ class BookManager implements BookManagerInterface {
|
|||
* The Book ID to find links for.
|
||||
* @param array $parameters
|
||||
* (optional) An associative array of build parameters. Possible keys:
|
||||
* - expanded: An array of parent link ids to return only book links that
|
||||
* are children of one of the plids in this list. If empty, the whole
|
||||
* outline is built, unless 'only_active_trail' is TRUE.
|
||||
* - active_trail: An array of nids, representing the coordinates of the
|
||||
* currently active book link.
|
||||
* - expanded: An array of parent link IDs to return only book links that
|
||||
* are children of one of the parent link IDs in this list. If empty,
|
||||
* the whole outline is built, unless 'only_active_trail' is TRUE.
|
||||
* - active_trail: An array of node IDs, representing the currently active
|
||||
* book link.
|
||||
* - only_active_trail: Whether to only return links that are in the active
|
||||
* trail. This option is ignored, if 'expanded' is non-empty.
|
||||
* trail. This option is ignored if 'expanded' is non-empty.
|
||||
* - min_depth: The minimum depth of book links in the resulting tree.
|
||||
* Defaults to 1, which is the default to build a whole tree for a book.
|
||||
* Defaults to 1, which is to build the whole tree for the book.
|
||||
* - max_depth: The maximum depth of book links in the resulting tree.
|
||||
* - conditions: An associative array of custom database select query
|
||||
* condition key/value pairs; see _menu_build_tree() for the actual query.
|
||||
* condition key/value pairs; see
|
||||
* \Drupal\book\BookOutlineStorage::getBookMenuTree() for the actual
|
||||
* query.
|
||||
*
|
||||
* @return array
|
||||
* A fully built book tree.
|
||||
|
@ -618,7 +620,29 @@ class BookManager implements BookManagerInterface {
|
|||
* to further massage the data manually before further processing happens.
|
||||
* _menu_tree_check_access() needs to be invoked afterwards.
|
||||
*
|
||||
* @see menu_build_tree()
|
||||
* @param int $bid
|
||||
* The book ID to find links for.
|
||||
* @param array $parameters
|
||||
* (optional) An associative array of build parameters. Possible keys:
|
||||
* - expanded: An array of parent link IDs to return only book links that
|
||||
* are children of one of the parent link IDs in this list. If empty,
|
||||
* the whole outline is built, unless 'only_active_trail' is TRUE.
|
||||
* - active_trail: An array of node IDs, representing the currently active
|
||||
* book link.
|
||||
* - only_active_trail: Whether to only return links that are in the active
|
||||
* trail. This option is ignored if 'expanded' is non-empty.
|
||||
* - min_depth: The minimum depth of book links in the resulting tree.
|
||||
* Defaults to 1, which is to build the whole tree for the book.
|
||||
* - max_depth: The maximum depth of book links in the resulting tree.
|
||||
* - conditions: An associative array of custom database select query
|
||||
* condition key/value pairs; see
|
||||
* \Drupal\book\BookOutlineStorage::getBookMenuTree() for the actual
|
||||
* query.
|
||||
*
|
||||
* @return array
|
||||
* An array with links representing the tree structure of the book.
|
||||
*
|
||||
* @see \Drupal\book\BookOutlineStorageInterface::getBookMenuTree()
|
||||
*/
|
||||
protected function doBookTreeBuild($bid, array $parameters = array()) {
|
||||
// Static cache of already built menu trees.
|
||||
|
@ -885,7 +909,7 @@ class BookManager implements BookManagerInterface {
|
|||
* Sets the p1 through p9 properties for a book link being saved.
|
||||
*
|
||||
* @param array $link
|
||||
* The book link to update.
|
||||
* The book link to update, passed by reference.
|
||||
* @param array $parent
|
||||
* The parent values to set.
|
||||
*/
|
||||
|
@ -930,6 +954,9 @@ class BookManager implements BookManagerInterface {
|
|||
|
||||
/**
|
||||
* Sorts the menu tree and recursively checks access for each item.
|
||||
*
|
||||
* @param array $tree
|
||||
* The book tree to operate on.
|
||||
*/
|
||||
protected function doBookTreeCheckAccess(&$tree) {
|
||||
$new_tree = array();
|
||||
|
@ -1010,6 +1037,20 @@ class BookManager implements BookManagerInterface {
|
|||
*
|
||||
* The function is a bit complex because the rendering of a link depends on
|
||||
* the next book link.
|
||||
*
|
||||
* @param array $links
|
||||
* A flat array of book links that are part of the book. Each array element
|
||||
* is an associative array of information about the book link, containing
|
||||
* the fields from the {book} table. This array must be ordered depth-first.
|
||||
* @param array $parents
|
||||
* An array of the node ID values that are in the path from the current page
|
||||
* to the root of the book tree.
|
||||
* @param int $depth
|
||||
* The minimum depth to include in the returned book tree.
|
||||
*
|
||||
* @return array
|
||||
* Book tree.
|
||||
*
|
||||
*/
|
||||
protected function buildBookOutlineRecursive(&$links, $parents, $depth) {
|
||||
$tree = array();
|
||||
|
|
|
@ -253,7 +253,7 @@
|
|||
// the "image" command's CKEditor dialog with a Drupal-native dialog.
|
||||
editor.addCommand('editdrupalimage', {
|
||||
allowedContent: 'img[alt,!src,width,height,!data-entity-type,!data-entity-uuid]',
|
||||
requiredContent: 'img[alt,src,width,height,data-entity-type,data-entity-uuid]',
|
||||
requiredContent: 'img[alt,src,data-entity-type,data-entity-uuid]',
|
||||
modes: {wysiwyg: 1},
|
||||
canUndo: true,
|
||||
exec: function (editor, data) {
|
||||
|
|
|
@ -42,8 +42,8 @@ interface CKEditorPluginConfigurableInterface extends CKEditorPluginInterface {
|
|||
* @param \Drupal\editor\Entity\Editor $editor
|
||||
* A configured text editor object.
|
||||
*
|
||||
* @return array|FALSE
|
||||
* A render array for the settings form, or FALSE if there is none.
|
||||
* @return array
|
||||
* A render array for the settings form.
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use Drupal\Core\Session\AccountInterface;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Base for controller for comment forms.
|
||||
* Base handler for comment forms.
|
||||
*/
|
||||
class CommentForm extends ContentEntityForm {
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use Drupal\Core\Language\LanguageManagerInterface;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines the controller class for comments.
|
||||
* Defines the storage handler class for comments.
|
||||
*
|
||||
* This extends the Drupal\Core\Entity\Sql\SqlContentEntityStorage class,
|
||||
* adding required special handling for comment entities.
|
||||
|
|
|
@ -16,7 +16,7 @@ use Psr\Log\LoggerInterface;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Base form controller for category edit forms.
|
||||
* Base form handler for comment type edit forms.
|
||||
*/
|
||||
class CommentTypeForm extends EntityForm {
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use Drupal\Core\Session\AccountInterface;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Render controller for comments.
|
||||
* View builder handler for comments.
|
||||
*/
|
||||
class CommentViewBuilder extends EntityViewBuilder {
|
||||
|
||||
|
|
|
@ -64,9 +64,14 @@ class ConfigOtherModuleTest extends WebTestBase {
|
|||
|
||||
// Ensure that optional configuration with unmet dependencies is only
|
||||
// installed once all the dependencies are met.
|
||||
$this->assertNull(entity_load('config_test', 'other_module_test_unmet', TRUE), 'The optional configuration whose dependencies are met is not created.');
|
||||
$this->assertNull(entity_load('config_test', 'other_module_test_unmet', TRUE), 'The optional configuration config_test.dynamic.other_module_test_unmet whose dependencies are not met is not created.');
|
||||
$this->assertNull(entity_load('config_test', 'other_module_test_optional_entity_unmet', TRUE), 'The optional configuration config_test.dynamic.other_module_test_optional_entity_unmet whose dependencies are not met is not created.');
|
||||
$this->installModule('config_install_dependency_test');
|
||||
$this->assertTrue(entity_load('config_test', 'other_module_test_unmet', TRUE), 'The optional configuration whose dependencies are met is now created.');
|
||||
$this->assertTrue(entity_load('config_test', 'other_module_test_unmet', TRUE), 'The optional configuration config_test.dynamic.other_module_test_unmet whose dependencies are met is now created.');
|
||||
// Although the following configuration entity's are now met it is not
|
||||
// installed because it does not have a direct dependency on the
|
||||
// config_install_dependency_test module.
|
||||
$this->assertNull(entity_load('config_test', 'other_module_test_optional_entity_unmet', TRUE), 'The optional configuration config_test.dynamic.other_module_test_optional_entity_unmet whose dependencies are met is not created.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
id: other_module_test_optional_entity_unmet
|
||||
label: 'Other module test to test optional config installation'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
config:
|
||||
- config_test.dynamic.other_module_test_unmet
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\config_translation\Tests;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Language\Language;
|
||||
|
@ -733,6 +734,46 @@ class ConfigTranslationUiTest extends WebTestBase {
|
|||
$this->assertEscaped($translatable_storage_setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the translation of a boolean field settings.
|
||||
*/
|
||||
public function testBooleanFieldConfigTranslation() {
|
||||
// Add a test boolean field.
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'boolean',
|
||||
])->save();
|
||||
|
||||
$bundle = strtolower($this->randomMachineName());
|
||||
entity_test_create_bundle($bundle);
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'bundle' => $bundle,
|
||||
]);
|
||||
|
||||
$on_label = 'On label (with <em>HTML</em> & things)';
|
||||
$field->setSetting('on_label', $on_label);
|
||||
$off_label = 'Off label (with <em>HTML</em> & things)';
|
||||
$field->setSetting('off_label', $off_label);
|
||||
$field->save();
|
||||
|
||||
$this->drupalLogin($this->translatorUser);
|
||||
|
||||
$this->drupalGet("/entity_test/structure/$bundle/fields/entity_test.$bundle.$field_name/translate");
|
||||
$this->clickLink('Add');
|
||||
|
||||
// Checks the text of details summary element that surrounds the translation
|
||||
// options.
|
||||
$this->assertText(Html::escape(strip_tags($on_label)) . ' Boolean settings');
|
||||
|
||||
// Checks that the correct on and off labels appear on the form.
|
||||
$this->assertEscaped($on_label);
|
||||
$this->assertEscaped($off_label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test translation storage in locale storage.
|
||||
*/
|
||||
|
|
|
@ -11,11 +11,14 @@ use Drupal\content_translation\ContentTranslationManagerInterface;
|
|||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
|
||||
/**
|
||||
* Provides dynamic local tasks for content translation.
|
||||
*/
|
||||
class ContentTranslationLocalTasks extends DeriverBase implements ContainerDeriverInterface {
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The base plugin ID
|
||||
|
@ -38,10 +41,13 @@ class ContentTranslationLocalTasks extends DeriverBase implements ContainerDeriv
|
|||
* The base plugin ID.
|
||||
* @param \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager
|
||||
* The content translation manager.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The translation manager.
|
||||
*/
|
||||
public function __construct($base_plugin_id, ContentTranslationManagerInterface $content_translation_manager) {
|
||||
public function __construct($base_plugin_id, ContentTranslationManagerInterface $content_translation_manager, TranslationInterface $string_translation) {
|
||||
$this->basePluginId = $base_plugin_id;
|
||||
$this->contentTranslationManager = $content_translation_manager;
|
||||
$this->stringTranslation = $string_translation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,7 +56,8 @@ class ContentTranslationLocalTasks extends DeriverBase implements ContainerDeriv
|
|||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$base_plugin_id,
|
||||
$container->get('content_translation.manager')
|
||||
$container->get('content_translation.manager'),
|
||||
$container->get('string_translation')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -66,7 +73,7 @@ class ContentTranslationLocalTasks extends DeriverBase implements ContainerDeriv
|
|||
$base_route_name = "entity.$entity_type_id.canonical";
|
||||
$this->derivatives[$translation_route_name] = array(
|
||||
'entity_type' => $entity_type_id,
|
||||
'title' => 'Translate',
|
||||
'title' => $this->t('Translate'),
|
||||
'route_name' => $translation_route_name,
|
||||
'base_route' => $base_route_name,
|
||||
) + $base_plugin_definition;
|
||||
|
|
|
@ -37,8 +37,11 @@ class ContentTranslationOperationsTest extends NodeTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['language', 'content_translation', 'node', 'views'];
|
||||
public static $modules = ['language', 'content_translation', 'node', 'views', 'block'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
|
@ -63,7 +66,7 @@ class ContentTranslationOperationsTest extends NodeTestBase {
|
|||
/**
|
||||
* Test that the operation "Translate" is displayed in the content listing.
|
||||
*/
|
||||
function testOperationTranslateLink() {
|
||||
public function testOperationTranslateLink() {
|
||||
$node = $this->drupalCreateNode(['type' => 'article', 'langcode' => 'es']);
|
||||
// Verify no translation operation links are displayed for users without
|
||||
// permission.
|
||||
|
@ -103,9 +106,30 @@ class ContentTranslationOperationsTest extends NodeTestBase {
|
|||
$node->setPublished(FALSE)->save();
|
||||
$this->drupalGet($node->urlInfo('drupal:content-translation-overview'));
|
||||
$this->assertResponse(403);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Ensure the 'Translate' local task does not show up anymore when disabling
|
||||
// translations for a content type.
|
||||
$node->setPublished(TRUE)->save();
|
||||
user_role_change_permissions(
|
||||
Role::AUTHENTICATED_ID,
|
||||
[
|
||||
'administer content translation' => TRUE,
|
||||
'administer languages' => TRUE,
|
||||
]
|
||||
);
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalLogin($this->baseUser2);
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertLinkByHref('node/' . $node->id() . '/translations');
|
||||
$this->drupalPostForm('admin/config/regional/content-language', ['settings[node][article][translatable]' => FALSE], t('Save configuration'));
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertNoLinkByHref('node/' . $node->id() . '/translations');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the access to the overview page for translations.
|
||||
*
|
||||
* @see content_translation_translate_access()
|
||||
*/
|
||||
public function testContentTranslationOverviewAccess() {
|
||||
|
|
|
@ -37,6 +37,7 @@ class ContentTranslationLocalTasksTest extends LocalTaskIntegrationTestBase {
|
|||
'node' => $entity_type,
|
||||
)));
|
||||
\Drupal::getContainer()->set('content_translation.manager', $content_translation_manager);
|
||||
\Drupal::getContainer()->set('string_translation', $this->getStringTranslationStub());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -130,14 +130,14 @@ class EntityDisplayModeListBuilder extends ConfigEntityListBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* Filters entities based on their controllers.
|
||||
* Filters entities based on their view builder handlers.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type of the entity that needs to be validated.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the entity has the correct controller, FALSE if the entity
|
||||
* doesn't has the correct controller.
|
||||
* TRUE if the entity has the correct view builder handler, FALSE if the
|
||||
* entity doesn't have the correct view builder handler.
|
||||
*/
|
||||
protected function isValidEntity($entity_type) {
|
||||
return $this->entityTypes[$entity_type]->get('field_ui_base_route') && $this->entityTypes[$entity_type]->hasViewBuilderClass();
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Drupal\field_ui;
|
|||
class EntityFormModeListBuilder extends EntityDisplayModeListBuilder {
|
||||
|
||||
/**
|
||||
* Filters entities based on their controllers.
|
||||
* Filters entities based on their form mode handlers.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type of the entity that needs to be validated.
|
||||
|
|
|
@ -472,7 +472,7 @@ class ConfigurableLanguageManager extends LanguageManager implements Configurabl
|
|||
}
|
||||
$predefined[$key] = new TranslatableMarkup($value[0]);
|
||||
}
|
||||
asort($predefined);
|
||||
natcasesort($predefined);
|
||||
return $predefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ use Drupal\language\ContentLanguageSettingsInterface;
|
|||
* entity_keys = {
|
||||
* "id" = "id"
|
||||
* },
|
||||
* list_cache_tags = { "rendered" }
|
||||
* )
|
||||
*/
|
||||
class ContentLanguageSettings extends ConfigEntityBase implements ContentLanguageSettingsInterface {
|
||||
|
|
|
@ -61,7 +61,7 @@ class LanguageListBuilder extends DraggableListBuilder {
|
|||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type definition.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The entity storage controller class.
|
||||
* The entity storage handler class.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
|
|
79
core/modules/language/src/Tests/LanguageLocaleListTest.php
Normal file
79
core/modules/language/src/Tests/LanguageLocaleListTest.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\language\Tests\LanguageListTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\language\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
||||
/**
|
||||
* Adds a new language with translations and tests language list order.
|
||||
*
|
||||
* @group language
|
||||
*/
|
||||
class LanguageLocaleListTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('language', 'locale');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Add a default locale storage for all these tests.
|
||||
$this->storage = $this->container->get('locale.storage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding, editing, and deleting languages.
|
||||
*/
|
||||
function testLanguageLocaleList() {
|
||||
// User to add and remove language.
|
||||
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add predefined language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'fr',
|
||||
);
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
$this->assertText('The language French has been created and can now be used');
|
||||
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]));
|
||||
$this->rebuildContainer();
|
||||
|
||||
// Translate Spanish language to French (Espagnol).
|
||||
$source = $this->storage->createString(array(
|
||||
'source' => 'Spanish',
|
||||
'context' => '',
|
||||
))->save();
|
||||
$this->storage->createTranslation(array(
|
||||
'lid' => $source->lid,
|
||||
'language' => 'fr',
|
||||
'translation' => 'Espagnol',
|
||||
))->save();
|
||||
|
||||
// Get language list displayed in select list.
|
||||
$this->drupalGet('fr/admin/config/regional/language/add');
|
||||
$select = $this->xpath('//select[@id="edit-predefined-langcode"]');
|
||||
$select_element = (array) end($select);
|
||||
$options = $select_element['option'];
|
||||
// Remove the 'Custom language...' option form the end.
|
||||
array_pop($options);
|
||||
// Order language list.
|
||||
$options_ordered = $options;
|
||||
natcasesort($options_ordered);
|
||||
|
||||
// Check the language list displayed is ordered.
|
||||
$this->assertTrue($options === $options_ordered, 'Language list is ordered.');
|
||||
}
|
||||
}
|
|
@ -51,6 +51,10 @@ class CckLink extends ProcessPluginBase implements ContainerFactoryPluginInterfa
|
|||
$attributes = unserialize($attributes);
|
||||
}
|
||||
|
||||
if (!$attributes) {
|
||||
$attributes = [];
|
||||
}
|
||||
|
||||
// Massage the values into the correct form for the link.
|
||||
$route['uri'] = $value['url'];
|
||||
$route['options']['attributes'] = $attributes;
|
||||
|
|
|
@ -33,10 +33,10 @@ require_once __DIR__ . '/locale.translation.inc';
|
|||
* batch is finished. Optional, defaults to TRUE.
|
||||
* - 'use_remote': Whether or not to check the remote translation file.
|
||||
* Optional, defaults to TRUE.
|
||||
* @param array $context
|
||||
* @param array|\ArrayAccess $context.
|
||||
* The batch context.
|
||||
*/
|
||||
function locale_translation_batch_status_check($project, $langcode, array $options, array &$context) {
|
||||
function locale_translation_batch_status_check($project, $langcode, array $options, &$context) {
|
||||
$failure = $checked = FALSE;
|
||||
$options += array(
|
||||
'finish_feedback' => TRUE,
|
||||
|
|
|
@ -185,10 +185,10 @@ function locale_translate_batch_build(array $files, array $options) {
|
|||
* LOCALE_NOT_CUSTOMIZED.
|
||||
* - 'message': Alternative message to display during import. Note, this must
|
||||
* be sanitized text.
|
||||
* @param array $context
|
||||
* @param array|\ArrayAccess $context.
|
||||
* Contains a list of files imported.
|
||||
*/
|
||||
function locale_translate_batch_import($file, array $options, array &$context) {
|
||||
function locale_translate_batch_import($file, array $options, &$context) {
|
||||
// Merge the default values in the $options array.
|
||||
$options += array(
|
||||
'overwrite_options' => array(),
|
||||
|
@ -268,10 +268,10 @@ function locale_translate_batch_import($file, array $options, array &$context) {
|
|||
*
|
||||
* Save data of imported files.
|
||||
*
|
||||
* @param array $context
|
||||
* @param array|\ArrayAccess $context.
|
||||
* Contains a list of imported files.
|
||||
*/
|
||||
function locale_translate_batch_import_save(array $context) {
|
||||
function locale_translate_batch_import_save($context) {
|
||||
if (isset($context['results']['files'])) {
|
||||
foreach ($context['results']['files'] as $file) {
|
||||
// Update the file history if both project and version are known. This
|
||||
|
@ -293,10 +293,10 @@ function locale_translate_batch_import_save(array $context) {
|
|||
*
|
||||
* Refreshes translations after importing strings.
|
||||
*
|
||||
* @param array $context
|
||||
* @param array|\ArrayAccess $context.
|
||||
* Contains a list of strings updated and information about the progress.
|
||||
*/
|
||||
function locale_translate_batch_refresh(array &$context) {
|
||||
function locale_translate_batch_refresh(&$context) {
|
||||
if (!isset($context['sandbox']['refresh'])) {
|
||||
$strings = $langcodes = array();
|
||||
if (isset($context['results']['stats'])) {
|
||||
|
@ -597,12 +597,12 @@ function locale_config_batch_build(array $names, array $langcodes, array $option
|
|||
* An array of names of configuration objects to update.
|
||||
* @param array $langcodes
|
||||
* (optional) Array of language codes to update. Defaults to all languages.
|
||||
* @param array $context
|
||||
* @param array|\ArrayAccess $context.
|
||||
* Contains a list of files imported.
|
||||
*
|
||||
* @see locale_config_batch_build()
|
||||
*/
|
||||
function locale_config_batch_refresh_name(array $names, array $langcodes, array &$context) {
|
||||
function locale_config_batch_refresh_name(array $names, array $langcodes, &$context) {
|
||||
if (!isset($context['result']['stats']['config'])) {
|
||||
$context['result']['stats']['config'] = 0;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class MenuLink extends DrupalSqlBase {
|
|||
'link_path' => t('The Drupal path or external path this link points to.'),
|
||||
'router_path' => t('For links corresponding to a Drupal path (external = 0), this connects the link to a {menu_router}.path for joins.'),
|
||||
'link_title' => t('The text displayed for the link, which may be modified by a title callback stored in {menu_router}.'),
|
||||
'options' => t('A serialized array of options to be passed to the url() or l() function, such as a query string or HTML attributes.'),
|
||||
'options' => t('A serialized array of options to set on the URL, such as a query string or HTML attributes.'),
|
||||
'module' => t('The name of the module that generated this link.'),
|
||||
'hidden' => t('A flag for whether the link should be rendered in menus. (1 = a disabled menu item that may be shown on admin screens, -1 = a menu callback, 0 = a normal, visible link)'),
|
||||
'external' => t('A flag to indicate if the link points to a full URL starting with a protocol, like http:// (1 = external, 0 = internal).'),
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Drupal\migrate\Plugin\migrate\destination;
|
|||
use Drupal\Component\Plugin\DependentPluginInterface;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Entity\DependencyTrait;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\Entity\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
|
@ -38,6 +39,13 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
|
|||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $language_manager;
|
||||
|
||||
/**
|
||||
* Constructs a Config destination object.
|
||||
*
|
||||
|
@ -51,10 +59,13 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
|
|||
* The migration entity.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The configuration factory.
|
||||
* @param \Drupal\Core\Language\ConfigurableLanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, ConfigFactoryInterface $config_factory) {
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, ConfigFactoryInterface $config_factory, LanguageManagerInterface $language_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
|
||||
$this->config = $config_factory->getEditable($configuration['config_name']);
|
||||
$this->language_manager = $language_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,7 +77,8 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
|
|||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$migration,
|
||||
$container->get('config.factory')
|
||||
$container->get('config.factory'),
|
||||
$container->get('language_manager')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -74,6 +86,10 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface,
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function import(Row $row, array $old_destination_id_values = array()) {
|
||||
if ($row->hasDestinationProperty('langcode')) {
|
||||
$this->config = $this->language_manager->getLanguageConfigOverride($row->getDestinationProperty('langcode'), $this->config->getName());
|
||||
}
|
||||
|
||||
foreach ($row->getRawDestination() as $key => $value) {
|
||||
if (isset($value) || !empty($this->configuration['store null'])) {
|
||||
$this->config->set(str_replace(Row::PROPERTY_SEPARATOR, '.', $key), $value);
|
||||
|
|
|
@ -35,10 +35,7 @@ class Get extends ProcessPluginBase {
|
|||
$properties = is_string($source) ? array($source) : $source;
|
||||
$return = array();
|
||||
foreach ($properties as $property) {
|
||||
if (empty($property)) {
|
||||
$return[] = $value;
|
||||
}
|
||||
else {
|
||||
if ($property || (string) $property === '0') {
|
||||
$is_source = TRUE;
|
||||
if ($property[0] == '@') {
|
||||
$property = preg_replace_callback('/^(@?)((?:@@)*)([^@]|$)/', function ($matches) use (&$is_source) {
|
||||
|
@ -57,7 +54,11 @@ class Get extends ProcessPluginBase {
|
|||
$return[] = $row->getDestinationProperty($property);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$return[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_string($source)) {
|
||||
$this->multiple = is_array($return[0]);
|
||||
return $return[0];
|
||||
|
|
|
@ -96,7 +96,7 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter
|
|||
protected $skipCount = FALSE;
|
||||
|
||||
/**
|
||||
* Flags whether to track changes to incloming data.
|
||||
* Flags whether to track changes to incoming data.
|
||||
*
|
||||
* If TRUE, we will maintain hashed source rows to determine whether incoming
|
||||
* data has changed.
|
||||
|
|
|
@ -263,6 +263,15 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi
|
|||
}
|
||||
$id_map_database_options = $id_map->getDatabase()->getConnectionOptions();
|
||||
$source_database_options = $this->getDatabase()->getConnectionOptions();
|
||||
|
||||
// Special handling for sqlite which deals with files.
|
||||
if ($id_map_database_options['driver'] === 'sqlite' &&
|
||||
$source_database_options['driver'] === 'sqlite' &&
|
||||
$id_map_database_options['database'] != $source_database_options['database']
|
||||
) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
foreach (array('username', 'password', 'host', 'port', 'namespace', 'driver') as $key) {
|
||||
if (isset($source_database_options[$key])) {
|
||||
if ($id_map_database_options[$key] != $source_database_options[$key]) {
|
||||
|
|
|
@ -107,16 +107,33 @@ class SqlBaseTest extends UnitTestCase {
|
|||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
['username' => 'different_from_map', 'password' => 'different_from_map'],
|
||||
['username' => 'different_from_source', 'password' => 'different_from_source'],
|
||||
['driver' => 'mysql', 'username' => 'different_from_map', 'password' => 'different_from_map'],
|
||||
['driver' => 'mysql', 'username' => 'different_from_source', 'password' => 'different_from_source'],
|
||||
],
|
||||
// Returns true because source and id map connection options are the same.
|
||||
[
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
['username' => 'same_value', 'password' => 'same_value'],
|
||||
['username' => 'same_value', 'password' => 'same_value'],
|
||||
['driver' => 'pgsql', 'username' => 'same_value', 'password' => 'same_value'],
|
||||
['driver' => 'pgsql', 'username' => 'same_value', 'password' => 'same_value'],
|
||||
],
|
||||
// Returns false because driver is sqlite and the databases are not the
|
||||
// same.
|
||||
[
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
['driver' => 'sqlite', 'database' => '1.sqlite', 'username' => '', 'password' => ''],
|
||||
['driver' => 'sqlite', 'database' => '2.sqlite', 'username' => '', 'password' => ''],
|
||||
],
|
||||
// Returns false because driver is not the same.
|
||||
[
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
['driver' => 'pgsql', 'username' => 'same_value', 'password' => 'same_value'],
|
||||
['driver' => 'mysql', 'username' => 'same_value', 'password' => 'same_value'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
|
|
@ -49,9 +49,72 @@ class ConfigTest extends UnitTestCase {
|
|||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$row->expects($this->once())
|
||||
->method('hasDestinationProperty')
|
||||
->will($this->returnValue(FALSE));
|
||||
$row->expects($this->any())
|
||||
->method('getRawDestination')
|
||||
->will($this->returnValue($source));
|
||||
$destination = new Config(array('config_name' => 'd8_config'), 'd8_config', array('pluginId' => 'd8_config'), $migration, $config_factory);
|
||||
$language_manager = $this->getMockBuilder('Drupal\language\ConfigurableLanguageManagerInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$language_manager->expects($this->never())
|
||||
->method('getLanguageConfigOverride')
|
||||
->with('fr', 'd8_config')
|
||||
->will($this->returnValue($config));
|
||||
$destination = new Config(array('config_name' => 'd8_config'), 'd8_config', array('pluginId' => 'd8_config'), $migration, $config_factory, $language_manager);
|
||||
$destination_id = $destination->import($row);
|
||||
$this->assertEquals($destination_id, ['d8_config']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the import method.
|
||||
*/
|
||||
public function testLanguageImport() {
|
||||
$source = array(
|
||||
'langcode' => 'mi',
|
||||
);
|
||||
$migration = $this->getMockBuilder('Drupal\migrate\Entity\Migration')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
foreach ($source as $key => $val) {
|
||||
$config->expects($this->once())
|
||||
->method('set')
|
||||
->with($this->equalTo($key), $this->equalTo($val))
|
||||
->will($this->returnValue($config));
|
||||
}
|
||||
$config->expects($this->once())
|
||||
->method('save');
|
||||
$config->expects($this->any())
|
||||
->method('getName')
|
||||
->willReturn('d8_config');
|
||||
$config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
|
||||
$config_factory->expects($this->once())
|
||||
->method('getEditable')
|
||||
->with('d8_config')
|
||||
->will($this->returnValue($config));
|
||||
$row = $this->getMockBuilder('Drupal\migrate\Row')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$row->expects($this->once())
|
||||
->method('hasDestinationProperty')
|
||||
->will($this->returnValue($source));
|
||||
$row->expects($this->any())
|
||||
->method('getRawDestination')
|
||||
->will($this->returnValue($source));
|
||||
$row->expects($this->any())
|
||||
->method('getDestinationProperty')
|
||||
->will($this->returnValue($source['langcode']));
|
||||
$language_manager = $this->getMockBuilder('Drupal\language\ConfigurableLanguageManagerInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$language_manager->expects($this->any())
|
||||
->method('getLanguageConfigOverride')
|
||||
->with('mi', 'd8_config')
|
||||
->will($this->returnValue($config));
|
||||
$destination = new Config(array('config_name' => 'd8_config'), 'd8_config', array('pluginId' => 'd8_config'), $migration, $config_factory, $language_manager);
|
||||
$destination_id = $destination->import($row);
|
||||
$this->assertEquals($destination_id, ['d8_config']);
|
||||
}
|
||||
|
|
|
@ -82,6 +82,28 @@ class GetTest extends MigrateProcessTestCase {
|
|||
$value = $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destinationproperty');
|
||||
$this->assertSame($value, array('source_value1', 'source_value2', 'source_value3', 'source_value4'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Get plugin when source has integer values.
|
||||
*/
|
||||
public function testIntegerValues() {
|
||||
$this->row->expects($this->exactly(2))
|
||||
->method('getSourceProperty')
|
||||
->willReturnOnConsecutiveCalls('val1', 'val2');
|
||||
|
||||
$this->plugin->setSource([0 => 0, 1 => 'test']);
|
||||
$return = $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destinationproperty');
|
||||
$this->assertSame([0 => 'val1', 1 => 'val2'], $return);
|
||||
|
||||
$this->plugin->setSource([FALSE]);
|
||||
$return = $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destinationproperty');
|
||||
$this->assertSame([NULL], $return);
|
||||
|
||||
$this->plugin->setSource([NULL]);
|
||||
$return = $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destinationproperty');
|
||||
$this->assertSame([NULL], $return);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Drupal\migrate\Plugin\migrate\process;
|
||||
|
|
|
@ -151,3 +151,42 @@ migrate_entity_constant:
|
|||
migrate.source.md_empty:
|
||||
type: migrate.source.empty
|
||||
label: 'Empty source for migrate_drupal migrations'
|
||||
|
||||
migrate.source.i18n_variable:
|
||||
type: migrate_source_sql
|
||||
label: 'i18n Variable'
|
||||
mapping:
|
||||
variables:
|
||||
type: sequence
|
||||
label: 'Variables'
|
||||
sequence:
|
||||
type: string
|
||||
label: 'Variable'
|
||||
constants:
|
||||
type: mapping
|
||||
label: 'Constants'
|
||||
mapping:
|
||||
entity_type:
|
||||
type: string
|
||||
label: 'Entity type'
|
||||
id:
|
||||
type: string
|
||||
label: 'ID'
|
||||
label:
|
||||
type: label
|
||||
label: 'Label'
|
||||
description:
|
||||
type: text
|
||||
label: 'Description'
|
||||
path:
|
||||
type: string
|
||||
label: 'Path'
|
||||
plugin:
|
||||
type: string
|
||||
label: 'Plugin'
|
||||
status:
|
||||
type: boolean
|
||||
label: 'Status'
|
||||
slash:
|
||||
type: string
|
||||
label: 'Slash'
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\migrate_drupal\Plugin\migrate\source\d6\i18nVariable.
|
||||
*/
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\migrate\Entity\MigrationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal i18n_variable source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "i18n_variable"
|
||||
* )
|
||||
*/
|
||||
class i18nVariable extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* The variable names to fetch.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variables;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityManagerInterface $entity_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_manager);
|
||||
$this->variables = $this->configuration['variables'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initializeIterator() {
|
||||
return new \ArrayIterator($this->values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the values of the variables specified in the plugin configuration.
|
||||
*
|
||||
* @return array
|
||||
* An associative array where the keys are the variables specified in the
|
||||
* plugin configuration and the values are the values found in the source.
|
||||
* A key/value pair is added for the language code. Only those values are
|
||||
* returned that are actually in the database.
|
||||
*/
|
||||
protected function values() {
|
||||
$values = [];
|
||||
$result = $this->prepareQuery()->execute()->FetchAllAssoc('language');
|
||||
foreach ($result as $i18n_variable) {
|
||||
$values[]['language'] = $i18n_variable->language;
|
||||
}
|
||||
$result = $this->prepareQuery()->execute()->FetchAll();
|
||||
foreach ($result as $i18n_variable) {
|
||||
foreach ($values as $key => $value) {
|
||||
if ($values[$key]['language'] === $i18n_variable->language) {
|
||||
$values[$key][$i18n_variable->name] = unserialize($i18n_variable->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count() {
|
||||
return $this->initializeIterator()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return array_combine($this->variables, $this->variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->getDatabase()
|
||||
->select('i18n_variable', 'v')
|
||||
->fields('v')
|
||||
->condition('name', (array) $this->configuration['variables'], 'IN');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['language']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
|
@ -30531,6 +30531,21 @@ $connection->insert('profile_fields')
|
|||
'autocomplete' => '1',
|
||||
'options' => '',
|
||||
))
|
||||
->values(array(
|
||||
'fid' => '13',
|
||||
'title' => 'Blog',
|
||||
'name' => 'profile_blog',
|
||||
'explanation' => 'Paste the full URL, including http://, of your personal blog.',
|
||||
'category' => 'Personal information',
|
||||
'page' => '',
|
||||
'type' => 'url',
|
||||
'weight' => '3',
|
||||
'required' => '0',
|
||||
'register' => '0',
|
||||
'visibility' => '3',
|
||||
'autocomplete' => '0',
|
||||
'options' => '',
|
||||
))
|
||||
->values(array(
|
||||
'fid' => '14',
|
||||
'title' => 'Birthdate',
|
||||
|
@ -30561,21 +30576,6 @@ $connection->insert('profile_fields')
|
|||
'autocomplete' => '0',
|
||||
'options' => '',
|
||||
))
|
||||
->values(array(
|
||||
'fid' => '16',
|
||||
'title' => 'Blog',
|
||||
'name' => 'profile_blog',
|
||||
'explanation' => 'Paste the full URL, including http://, of your personal blog.',
|
||||
'category' => 'Personal information',
|
||||
'page' => '',
|
||||
'type' => 'url',
|
||||
'weight' => '3',
|
||||
'required' => '0',
|
||||
'register' => '0',
|
||||
'visibility' => '3',
|
||||
'autocomplete' => '0',
|
||||
'options' => '',
|
||||
))
|
||||
->execute();
|
||||
|
||||
$connection->schema()->createTable('profile_values', array(
|
||||
|
@ -34072,7 +34072,7 @@ $connection->insert('vocabulary')
|
|||
'help' => '',
|
||||
'relations' => '1',
|
||||
'hierarchy' => '2',
|
||||
'multiple' => '0',
|
||||
'multiple' => '1',
|
||||
'required' => '0',
|
||||
'tags' => '0',
|
||||
'module' => 'taxonomy',
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\migrate_drupal\Unit\source\d6\i18nVariableTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Unit\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests the variable source plugin.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class i18nVariableTest 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\migrate_drupal\Plugin\migrate\source\d6\i18nVariable';
|
||||
|
||||
/**
|
||||
* Define bare minimum migration configuration.
|
||||
*/
|
||||
protected $migrationConfiguration = [
|
||||
'id' => 'test',
|
||||
'highWaterProperty' => array('field' => 'test'),
|
||||
'source' => [
|
||||
'plugin' => 'i18n_variable',
|
||||
'variables' => [
|
||||
'site_slogan',
|
||||
'site_name',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Expected results from the source.
|
||||
*/
|
||||
protected $expectedResults = [
|
||||
[
|
||||
'language' => 'fr',
|
||||
'site_slogan' => 'Migrate est génial',
|
||||
'site_name' => 'nom de site',
|
||||
],
|
||||
[
|
||||
'language' => 'mi',
|
||||
'site_slogan' => 'Ko whakamataku heke',
|
||||
'site_name' => 'ingoa_pae',
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* Database contents for tests.
|
||||
*/
|
||||
protected $databaseContents = [
|
||||
'i18n_variable' => [
|
||||
array('name' => 'site_slogan', 'language' => 'fr', 'value' => 's:19:"Migrate est génial";'),
|
||||
array('name' => 'site_name', 'language' => 'fr', 'value' => 's:11:"nom de site";'),
|
||||
array('name' => 'site_slogan', 'language' => 'mi', 'value' => 's:19:"Ko whakamataku heke";'),
|
||||
array('name' => 'site_name', 'language' => 'mi', 'value' => 's:9:"ingoa_pae";'),
|
||||
],
|
||||
];
|
||||
|
||||
}
|
|
@ -108,10 +108,10 @@ function _node_mass_update_helper(NodeInterface $node, array $updates, $langcode
|
|||
* @param bool $revisions
|
||||
* (optional) TRUE if $nodes contains an array of revision IDs instead of
|
||||
* node IDs. Defaults to FALSE; will be ignored if $load is FALSE.
|
||||
* @param array $context
|
||||
* @param array|\ArrayAccess $context.
|
||||
* An array of contextual key/values.
|
||||
*/
|
||||
function _node_mass_update_batch_process(array $nodes, array $updates, $load, $revisions, array &$context) {
|
||||
function _node_mass_update_batch_process(array $nodes, array $updates, $load, $revisions, &$context) {
|
||||
if (!isset($context['sandbox']['progress'])) {
|
||||
$context['sandbox']['progress'] = 0;
|
||||
$context['sandbox']['max'] = count($nodes);
|
||||
|
|
|
@ -1046,18 +1046,29 @@ function node_query_node_access_alter(AlterableInterface $query) {
|
|||
|
||||
$tables = $query->getTables();
|
||||
$base_table = $query->getMetaData('base_table');
|
||||
// If the base table is not given, default to node if present.
|
||||
// If the base table is not given, default to one of the node base tables.
|
||||
if (!$base_table) {
|
||||
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
|
||||
$table_mapping = \Drupal::entityTypeManager()->getStorage('node')->getTableMapping();
|
||||
$node_base_tables = $table_mapping->getTableNames();
|
||||
|
||||
foreach ($tables as $table_info) {
|
||||
if (!($table_info instanceof SelectInterface)) {
|
||||
$table = $table_info['table'];
|
||||
// If the node table is in the query, it wins immediately.
|
||||
// Ensure that 'node' and 'node_field_data' are always preferred over
|
||||
// 'node_revision' and 'node_field_revision'.
|
||||
if ($table == 'node' || $table == 'node_field_data') {
|
||||
$base_table = $table;
|
||||
break;
|
||||
}
|
||||
// If one of the node base tables are in the query, add it to the list
|
||||
// of possible base tables to join against.
|
||||
if (in_array($table, $node_base_tables)) {
|
||||
$base_table = $table;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bail out if the base table is missing.
|
||||
if (!$base_table) {
|
||||
throw new Exception(t('Query tagged for node access but there is no node table, specify the base_table using meta data.'));
|
||||
|
|
|
@ -14,7 +14,7 @@ use Drupal\user\PrivateTempStoreFactory;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Form controller for the node edit forms.
|
||||
* Form handler for the node edit forms.
|
||||
*/
|
||||
class NodeForm extends ContentEntityForm {
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use Drupal\Core\Language\LanguageManagerInterface;
|
|||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines a controller class that handles the node grants system.
|
||||
* Defines a storage handler class that handles the node grants system.
|
||||
*
|
||||
* This is used to build node query access.
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@ use Drupal\Core\Session\AccountInterface;
|
|||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
||||
/**
|
||||
* Defines the controller class for nodes.
|
||||
* Defines the storage handler class for nodes.
|
||||
*
|
||||
* This extends the base storage class, adding required special handling for
|
||||
* node entities.
|
||||
|
|
|
@ -15,7 +15,7 @@ use Drupal\language\Entity\ContentLanguageSettings;
|
|||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Form controller for node type forms.
|
||||
* Form handler for node type forms.
|
||||
*/
|
||||
class NodeTypeForm extends BundleEntityFormBase {
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use Drupal\Core\Entity\EntityViewBuilder;
|
|||
use Drupal\node\Entity\Node;
|
||||
|
||||
/**
|
||||
* Render controller for nodes.
|
||||
* View builder handler for nodes.
|
||||
*/
|
||||
class NodeViewBuilder extends EntityViewBuilder {
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
->select('search_index', 'i', array('target' => 'replica'))
|
||||
->extend('Drupal\search\SearchQuery')
|
||||
->extend('Drupal\Core\Database\Query\PagerSelectExtender');
|
||||
$query->join('node_field_data', 'n', 'n.nid = i.sid');
|
||||
$query->join('node_field_data', 'n', 'n.nid = i.sid AND n.langcode = i.langcode');
|
||||
$query->condition('n.status', 1)
|
||||
->addTag('node_access')
|
||||
->searchExpression($keys, $this->getPluginId());
|
||||
|
@ -429,8 +429,23 @@ class NodeSearch extends ConfigurableSearchPluginBase implements AccessibleInter
|
|||
// per cron run.
|
||||
$limit = (int) $this->searchSettings->get('index.cron_limit');
|
||||
|
||||
$result = $this->database->queryRange("SELECT n.nid, MAX(sd.reindex) FROM {node} n LEFT JOIN {search_dataset} sd ON sd.sid = n.nid AND sd.type = :type WHERE sd.sid IS NULL OR sd.reindex <> 0 GROUP BY n.nid ORDER BY MAX(sd.reindex) is null DESC, MAX(sd.reindex) ASC, n.nid ASC", 0, $limit, array(':type' => $this->getPluginId()), array('target' => 'replica'));
|
||||
$nids = $result->fetchCol();
|
||||
$query = db_select('node', 'n', array('target' => 'replica'));
|
||||
$query->addField('n', 'nid');
|
||||
$query->leftJoin('search_dataset', 'sd', 'sd.sid = n.nid AND sd.type = :type', array(':type' => $this->getPluginId()));
|
||||
$query->addExpression('CASE MAX(sd.reindex) WHEN NULL THEN 0 ELSE 1 END', 'ex');
|
||||
$query->addExpression('MAX(sd.reindex)', 'ex2');
|
||||
$query->condition(
|
||||
$query->orConditionGroup()
|
||||
->where('sd.sid IS NULL')
|
||||
->condition('sd.reindex', 0, '<>')
|
||||
);
|
||||
$query->orderBy('ex', 'DESC')
|
||||
->orderBy('ex2')
|
||||
->orderBy('n.nid')
|
||||
->groupBy('n.nid')
|
||||
->range(0, $limit);
|
||||
|
||||
$nids = $query->execute()->fetchCol();
|
||||
if (!$nids) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
class Type extends StringArgument {
|
||||
|
||||
/**
|
||||
* NodeType storage controller.
|
||||
* NodeType storage handler.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
|
|
|
@ -57,6 +57,30 @@ class MigrateNodeTest extends MigrateNodeTestBase {
|
|||
$this->assertIdentical('test rev 3', $node->body->value);
|
||||
$this->assertIdentical('filtered_html', $node->body->format);
|
||||
|
||||
// Test that link fields are migrated.
|
||||
$this->assertIdentical('http://groups.drupal.org/', $node->field_test_link->uri);
|
||||
$this->assertIdentical('Drupal Groups', $node->field_test_link->title);
|
||||
$this->assertIdentical([], $node->field_test_link->options['attributes']);
|
||||
|
||||
// Rerun migration with invalid link attributes and a different URL and
|
||||
// title. If only the attributes are changed the error does not occur.
|
||||
Database::getConnection('default', 'migrate')
|
||||
->update('content_type_story')
|
||||
->fields([
|
||||
'field_test_link_url' => 'https://www.drupal.org/node/2127611',
|
||||
'field_test_link_title' => 'Migrate API in Drupal 8',
|
||||
'field_test_link_attributes' => '',
|
||||
])
|
||||
->condition('nid', '2')
|
||||
->condition('vid', '3')
|
||||
->execute();
|
||||
|
||||
$this->rerunMigration();
|
||||
$node = Node::load(2);
|
||||
$this->assertIdentical('https://www.drupal.org/node/2127611', $node->field_test_link->uri);
|
||||
$this->assertIdentical('Migrate API in Drupal 8', $node->field_test_link->title);
|
||||
$this->assertIdentical([], $node->field_test_link->options['attributes']);
|
||||
|
||||
// Test that we can re-import using the EntityContentBase destination.
|
||||
$title = $this->rerunMigration();
|
||||
$node = Node::load(2);
|
||||
|
|
|
@ -72,6 +72,24 @@ class NodeQueryAlterTest extends NodeTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests 'node_access' query alter with revision-enabled nodes.
|
||||
*/
|
||||
public function testNodeQueryAlterWithRevisions() {
|
||||
// Execute a query that only deals with the 'node_revision' table.
|
||||
try {
|
||||
$query = \Drupal::entityTypeManager()->getStorage('node')->getQuery();
|
||||
$result = $query
|
||||
->allRevisions()
|
||||
->execute();
|
||||
|
||||
$this->assertEqual(count($result), 4, 'User with access can see correct nodes');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->fail('Altered query is malformed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests 'node_access' query alter, for user without access.
|
||||
*
|
||||
|
|
|
@ -14,6 +14,10 @@ use Drupal\simpletest\WebTestBase;
|
|||
/**
|
||||
* Ensures that node types translation work correctly.
|
||||
*
|
||||
* Note that the child site is installed in French; therefore, when making
|
||||
* assertions on translated text it is important to provide a langcode. This
|
||||
* ensures the asserts pass regardless of the Drupal version.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTypeTranslationTest extends WebTestBase {
|
||||
|
@ -105,12 +109,16 @@ class NodeTypeTranslationTest extends WebTestBase {
|
|||
// Check the name is translated without admin theme for editing.
|
||||
$this->drupalPostForm('admin/appearance', array('use_admin_theme' => '0'), t('Save configuration'));
|
||||
$this->drupalGet("$langcode/node/add/$type");
|
||||
$this->assertRaw(t('Create @name', array('@name' => $translated_name)));
|
||||
// This is a Spanish page, so ensure the text asserted is translated in
|
||||
// Spanish and not French by adding the langcode option.
|
||||
$this->assertRaw(t('Create @name', array('@name' => $translated_name), array('langcode' => $langcode)));
|
||||
|
||||
// Check the name is translated with admin theme for editing.
|
||||
$this->drupalPostForm('admin/appearance', array('use_admin_theme' => '1'), t('Save configuration'));
|
||||
$this->drupalGet("$langcode/node/add/$type");
|
||||
$this->assertRaw(t('Create @name', array('@name' => $translated_name)));
|
||||
// This is a Spanish page, so ensure the text asserted is translated in
|
||||
// Spanish and not French by adding the langcode option.
|
||||
$this->assertRaw(t('Create @name', array('@name' => $translated_name), array('langcode' => $langcode)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,17 +136,19 @@ class NodeTypeTranslationTest extends WebTestBase {
|
|||
|
||||
// Assert that the title label is displayed on the translation form with the right value.
|
||||
$this->drupalGet("admin/structure/types/manage/$type/translate/$langcode/add");
|
||||
$this->assertRaw(t('Label'));
|
||||
$this->assertRaw(t('Edited title'));
|
||||
$this->assertText('Edited title');
|
||||
|
||||
// Translate the title label.
|
||||
$this->drupalPostForm(NULL, array("translation[config_names][core.base_field_override.node.$type.title][label]" => 'Translated title'), t('Save translation'));
|
||||
|
||||
// Assert that the right title label is displayed on the node add form.
|
||||
// Assert that the right title label is displayed on the node add form. The
|
||||
// translations are created in this test; therefore, the assertions do not
|
||||
// use t(). If t() were used then the correct langcodes would need to be
|
||||
// provided.
|
||||
$this->drupalGet("node/add/$type");
|
||||
$this->assertRaw(t('Edited title'));
|
||||
$this->assertText('Edited title');
|
||||
$this->drupalGet("$langcode/node/add/$type");
|
||||
$this->assertRaw(t('Translated title'));
|
||||
$this->assertText('Translated title');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
|
|||
/**
|
||||
* Represents entities as resources.
|
||||
*
|
||||
* @see \Drupal\rest\Plugin\Deriver\EntityDeriver
|
||||
*
|
||||
* @RestResource(
|
||||
* id = "entity",
|
||||
* label = @Translation("Entity"),
|
||||
|
@ -28,8 +30,6 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
|
|||
* "https://www.drupal.org/link-relations/create" = "/entity/{entity_type}"
|
||||
* }
|
||||
* )
|
||||
*
|
||||
* @see \Drupal\rest\Plugin\Deriver\EntityDeriver
|
||||
*/
|
||||
class EntityResource extends ResourceBase {
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ abstract class RESTTestBase extends WebTestBase {
|
|||
|
||||
$url = $this->buildUrl($url);
|
||||
|
||||
$curl_options = array();
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
// Set query if there are additional GET parameters.
|
||||
|
@ -105,6 +106,16 @@ abstract class RESTTestBase extends WebTestBase {
|
|||
);
|
||||
break;
|
||||
|
||||
case 'HEAD':
|
||||
$curl_options = array(
|
||||
CURLOPT_HTTPGET => FALSE,
|
||||
CURLOPT_CUSTOMREQUEST => 'HEAD',
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_NOBODY => TRUE,
|
||||
CURLOPT_HTTPHEADER => array('Accept: ' . $mime_type),
|
||||
);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$curl_options = array(
|
||||
CURLOPT_HTTPGET => FALSE,
|
||||
|
|
79
core/modules/search/src/Tests/SearchDateIntervalTest.php
Normal file
79
core/modules/search/src/Tests/SearchDateIntervalTest.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\search\Tests\SearchDateIntervalTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests searching with date filters that exclude some translations.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchDateIntervalTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public static $modules = ['language', 'search_date_query_alter'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create and log in user.
|
||||
$test_user = $this->drupalCreateUser(['access content', 'search content', 'use advanced search', 'administer nodes', 'administer languages', 'access administration pages', 'administer site configuration']);
|
||||
$this->drupalLogin($test_user);
|
||||
|
||||
// Add a new language.
|
||||
ConfigurableLanguage::createFromLangcode('es')->save();
|
||||
|
||||
// Set up times to be applied to the English and Spanish translations of the
|
||||
// node create time, so that they are filtered in/out in the
|
||||
// search_date_query_alter test module.
|
||||
$created_time_en = new \DateTime('February 10 2016 10PM');
|
||||
$created_time_es = new \DateTime('March 19 2016 10PM');
|
||||
$default_format = filter_default_format();
|
||||
|
||||
$node = $this->drupalCreateNode([
|
||||
'title' => 'Node EN',
|
||||
'type' => 'page',
|
||||
'body' => [
|
||||
'value' => $this->randomMachineName(32),
|
||||
'format' => $default_format,
|
||||
],
|
||||
'langcode' => 'en',
|
||||
'created' => $created_time_en->format('U'),
|
||||
]);
|
||||
|
||||
// Add Spanish translation to the node.
|
||||
$translation = $node->addTranslation('es', ['title' => 'Node ES']);
|
||||
$translation->body->value = $this->randomMachineName(32);
|
||||
$translation->created->value = $created_time_es->format('U');
|
||||
$node->save();
|
||||
|
||||
// Update the index.
|
||||
$plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
|
||||
$plugin->updateIndex();
|
||||
search_update_totals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests searching with date filters that exclude some translations.
|
||||
*/
|
||||
public function testDateIntervalQueryAlter() {
|
||||
// Search for keyword node.
|
||||
$edit = ['keys' => 'node'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
// The nodes must have the same node ID but the created date is different.
|
||||
// So only the Spanish translation must appear.
|
||||
$this->assertLink('Node ES', 0, 'Spanish translation found in search results');
|
||||
$this->assertNoLink('Node EN', 'Search results do not contain English node');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Search Date Query Alter'
|
||||
type: module
|
||||
description: 'Test module that adds date conditions to node searches.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Adds date conditions to node searches.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Query\AlterableInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_query_TAG_alter(): tag search_$type with $type node_search.
|
||||
*/
|
||||
function search_date_query_alter_query_search_node_search_alter(AlterableInterface $query) {
|
||||
// Start date Sat, 19 Mar 2016 00:00:00 GMT.
|
||||
$query->condition('n.created', 1458345600, '>=');
|
||||
// End date Sun, 20 Mar 2016 00:00:00 GMT.
|
||||
$query->condition('n.created', 1458432000, '<');
|
||||
}
|
|
@ -11,7 +11,7 @@ use Drupal\Core\Entity\ContentEntityForm;
|
|||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form controller for the shortcut entity forms.
|
||||
* Form handler for the shortcut entity forms.
|
||||
*/
|
||||
class ShortcutForm extends ContentEntityForm {
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use Drupal\Core\Entity\BundleEntityFormBase;
|
|||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Form controller for the shortcut set entity edit forms.
|
||||
* Form handler for the shortcut set entity edit forms.
|
||||
*/
|
||||
class ShortcutSetForm extends BundleEntityFormBase {
|
||||
|
||||
|
|
|
@ -489,9 +489,10 @@ function simpletest_log_read($test_id, $database_prefix, $test_class) {
|
|||
* each module for files matching the PSR-0 standard. Once loaded the test list
|
||||
* is cached and stored in a static variable.
|
||||
*
|
||||
* @param string $module
|
||||
* Name of a module. If set then only tests belonging to this module are
|
||||
* returned.
|
||||
* @param string $extension
|
||||
* (optional) The name of an extension to limit discovery to; e.g., 'node'.
|
||||
* @param string[] $types
|
||||
* An array of included test types.
|
||||
*
|
||||
* @return array[]
|
||||
* An array of tests keyed with the groups, and then keyed by test classes.
|
||||
|
@ -506,8 +507,8 @@ function simpletest_log_read($test_id, $database_prefix, $test_class) {
|
|||
* );
|
||||
* @endcode
|
||||
*/
|
||||
function simpletest_test_get_all($module = NULL) {
|
||||
return \Drupal::service('test_discovery')->getTestClasses($module);
|
||||
function simpletest_test_get_all($extension = NULL, array $types = []) {
|
||||
return \Drupal::service('test_discovery')->getTestClasses($extension, $types);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
services:
|
||||
test_discovery:
|
||||
class: Drupal\simpletest\TestDiscovery
|
||||
arguments: ['@class_loader', '@?cache.discovery']
|
||||
arguments: ['@app.root', '@class_loader', '@module_handler', '@?cache.discovery']
|
||||
|
|
|
@ -23,7 +23,7 @@ trait AssertHelperTrait {
|
|||
* @return mixed
|
||||
* The input value, with MarkupInterface objects casted to string.
|
||||
*/
|
||||
protected function castSafeStrings($value) {
|
||||
protected static function castSafeStrings($value) {
|
||||
if ($value instanceof MarkupInterface) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
|
|
@ -229,11 +229,17 @@ abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
protected function initMink() {
|
||||
$driver = $this->getDefaultDriverInstance();
|
||||
|
||||
if ($driver instanceof GoutteDriver) {
|
||||
$driver->getClient()->setClient(\Drupal::httpClient());
|
||||
}
|
||||
|
||||
$session = new Session($driver);
|
||||
$this->mink = new Mink();
|
||||
$this->mink->registerSession('default', $session);
|
||||
$this->mink->setDefaultSessionName('default');
|
||||
$this->registerSessions();
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
|
|
|
@ -271,6 +271,12 @@ EOD;
|
|||
// The temporary stream wrapper is able to operate both with and without
|
||||
// configuration.
|
||||
$this->registerStreamWrapper('temporary', 'Drupal\Core\StreamWrapper\TemporaryStream');
|
||||
|
||||
// Manually configure the test mail collector implementation to prevent
|
||||
// tests from sending out emails and collect them in state instead.
|
||||
// While this should be enforced via settings.php prior to installation,
|
||||
// some tests expect to be able to test mail system implementations.
|
||||
$GLOBALS['config']['system.mail']['interface']['default'] = 'test_mail_collector';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,9 +10,11 @@ namespace Drupal\simpletest;
|
|||
use Doctrine\Common\Annotations\SimpleAnnotationReader;
|
||||
use Doctrine\Common\Reflection\StaticReflectionParser;
|
||||
use Drupal\Component\Annotation\Reflection\MockFileFinder;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Extension\ExtensionDiscovery;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\simpletest\Exception\MissingGroupException;
|
||||
use PHPUnit_Util_Test;
|
||||
|
||||
|
@ -49,18 +51,38 @@ class TestDiscovery {
|
|||
*/
|
||||
protected $availableExtensions;
|
||||
|
||||
/**
|
||||
* The app root.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $root;
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Constructs a new test discovery.
|
||||
*
|
||||
* @param string $root
|
||||
* The app root.
|
||||
* @param $class_loader
|
||||
* The class loader. Normally Composer's ClassLoader, as included by the
|
||||
* front controller, but may also be decorated; e.g.,
|
||||
* \Symfony\Component\ClassLoader\ApcClassLoader.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
|
||||
* (optional) Backend for caching discovery results.
|
||||
*/
|
||||
public function __construct($class_loader, CacheBackendInterface $cache_backend = NULL) {
|
||||
public function __construct($root, $class_loader, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend = NULL) {
|
||||
$this->root = $root;
|
||||
$this->classLoader = $class_loader;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->cacheBackend = $cache_backend;
|
||||
}
|
||||
|
||||
|
@ -80,15 +102,16 @@ class TestDiscovery {
|
|||
$existing = $this->classLoader->getPrefixesPsr4();
|
||||
|
||||
// Add PHPUnit test namespaces of Drupal core.
|
||||
$this->testNamespaces['Drupal\\Tests\\'] = [DRUPAL_ROOT . '/core/tests/Drupal/Tests'];
|
||||
$this->testNamespaces['Drupal\\KernelTests\\'] = [DRUPAL_ROOT . '/core/tests/Drupal/KernelTests'];
|
||||
$this->testNamespaces['Drupal\\FunctionalTests\\'] = [DRUPAL_ROOT . '/core/tests/Drupal/FunctionalTests'];
|
||||
$this->testNamespaces['Drupal\\Tests\\'] = [$this->root . '/core/tests/Drupal/Tests'];
|
||||
$this->testNamespaces['Drupal\\KernelTests\\'] = [$this->root . '/core/tests/Drupal/KernelTests'];
|
||||
$this->testNamespaces['Drupal\\FunctionalTests\\'] = [$this->root . '/core/tests/Drupal/FunctionalTests'];
|
||||
$this->testNamespaces['Drupal\\FunctionalJavascriptTests\\'] = [$this->root . '/core/tests/Drupal/FunctionalJavascriptTests'];
|
||||
|
||||
$this->availableExtensions = array();
|
||||
foreach ($this->getExtensions() as $name => $extension) {
|
||||
$this->availableExtensions[$extension->getType()][$name] = $name;
|
||||
|
||||
$base_path = DRUPAL_ROOT . '/' . $extension->getPath();
|
||||
$base_path = $this->root . '/' . $extension->getPath();
|
||||
|
||||
// Add namespace of disabled/uninstalled extensions.
|
||||
if (!isset($existing["Drupal\\$name\\"])) {
|
||||
|
@ -115,11 +138,12 @@ class TestDiscovery {
|
|||
*
|
||||
* @param string $extension
|
||||
* (optional) The name of an extension to limit discovery to; e.g., 'node'.
|
||||
* @param string[] $types
|
||||
* An array of included test types.
|
||||
*
|
||||
* @return array
|
||||
* An array of tests keyed by the first @group specified in each test's
|
||||
* PHPDoc comment block, and then keyed by class names. For example:
|
||||
* @code
|
||||
* An array of tests keyed by the the group name.
|
||||
* @code
|
||||
* $groups['block'] => array(
|
||||
* 'Drupal\block\Tests\BlockTest' => array(
|
||||
* 'name' => 'Drupal\block\Tests\BlockTest',
|
||||
|
@ -127,15 +151,12 @@ class TestDiscovery {
|
|||
* 'group' => 'block',
|
||||
* ),
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* If a discovered test class does not match the expected class name.
|
||||
* @endcode
|
||||
*
|
||||
* @todo Remove singular grouping; retain list of groups in 'group' key.
|
||||
* @see https://www.drupal.org/node/2296615
|
||||
*/
|
||||
public function getTestClasses($extension = NULL) {
|
||||
public function getTestClasses($extension = NULL, array $types = []) {
|
||||
$reader = new SimpleAnnotationReader();
|
||||
$reader->addNamespace('Drupal\\simpletest\\Annotation');
|
||||
|
||||
|
@ -190,13 +211,20 @@ class TestDiscovery {
|
|||
}
|
||||
|
||||
// Allow modules extending core tests to disable originals.
|
||||
\Drupal::moduleHandler()->alter('simpletest', $list);
|
||||
$this->moduleHandler->alter('simpletest', $list);
|
||||
|
||||
if (!isset($extension)) {
|
||||
if ($this->cacheBackend) {
|
||||
$this->cacheBackend->set('simpletest:discovery:classes', $list);
|
||||
}
|
||||
}
|
||||
|
||||
if ($types) {
|
||||
$list = NestedArray::filter($list, function ($element) use ($types) {
|
||||
return !(is_array($element) && isset($element['type']) && !in_array($element['type'], $types));
|
||||
});
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
@ -450,7 +478,7 @@ class TestDiscovery {
|
|||
* An array of Extension objects, keyed by extension name.
|
||||
*/
|
||||
protected function getExtensions() {
|
||||
$listing = new ExtensionDiscovery(DRUPAL_ROOT);
|
||||
$listing = new ExtensionDiscovery($this->root);
|
||||
// Ensure that tests in all profiles are discovered.
|
||||
$listing->setProfileDirectories(array());
|
||||
$extensions = $listing->scan('module', TRUE);
|
||||
|
|
|
@ -28,6 +28,7 @@ use Drupal\Core\Session\AnonymousUserSession;
|
|||
use Drupal\Core\Session\UserSession;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\StreamWrapper\PublicStream;
|
||||
use Drupal\Core\Test\AssertMailTrait;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -47,6 +48,9 @@ abstract class WebTestBase extends TestBase {
|
|||
use ContentTypeCreationTrait {
|
||||
createContentType as drupalCreateContentType;
|
||||
}
|
||||
use AssertMailTrait {
|
||||
getMails as drupalGetMails;
|
||||
}
|
||||
use NodeCreationTrait {
|
||||
getNodeByTitle as drupalGetNodeByTitle;
|
||||
createNode as drupalCreateNode;
|
||||
|
@ -2518,32 +2522,6 @@ abstract class WebTestBase extends TestBase {
|
|||
return $this->assertTrue($header_value == $value, $message ? $message : 'HTTP response header ' . $header . ' with value ' . $value . ' found, actual value: ' . $header_value, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array containing all emails sent during this test case.
|
||||
*
|
||||
* @param $filter
|
||||
* An array containing key/value pairs used to filter the emails that are
|
||||
* returned.
|
||||
*
|
||||
* @return
|
||||
* An array containing email messages captured during the current test.
|
||||
*/
|
||||
protected function drupalGetMails($filter = array()) {
|
||||
$captured_emails = \Drupal::state()->get('system.test_mail_collector') ?: array();
|
||||
$filtered_emails = array();
|
||||
|
||||
foreach ($captured_emails as $message) {
|
||||
foreach ($filter as $key => $value) {
|
||||
if (!isset($message[$key]) || $message[$key] != $value) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
$filtered_emails[] = $message;
|
||||
}
|
||||
|
||||
return $filtered_emails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes if the internal browser's URL matches the given path.
|
||||
*
|
||||
|
@ -2644,126 +2622,6 @@ abstract class WebTestBase extends TestBase {
|
|||
return $this->assertFalse($match, $message ? $message : SafeMarkup::format('HTTP response not expected @code, actual @curl_code', array('@code' => $code, '@curl_code' => $curl_code)), $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the most recently sent email message has the given value.
|
||||
*
|
||||
* The field in $name must have the content described in $value.
|
||||
*
|
||||
* @param $name
|
||||
* Name of field or message property to assert. Examples: subject, body,
|
||||
* id, ...
|
||||
* @param $value
|
||||
* Value of the field to assert.
|
||||
* @param $message
|
||||
* (optional) A message to display with the assertion. Do not translate
|
||||
* messages: use \Drupal\Component\Utility\SafeMarkup::format() to embed
|
||||
* variables in the message text, not t(). If left blank, a default message
|
||||
* will be displayed.
|
||||
* @param $group
|
||||
* (optional) The group this message is in, which is displayed in a column
|
||||
* in test output. Use 'Debug' to indicate this is debugging output. Do not
|
||||
* translate this string. Defaults to 'Email'; most tests do not override
|
||||
* this default.
|
||||
*
|
||||
* @return
|
||||
* TRUE on pass, FALSE on fail.
|
||||
*/
|
||||
protected function assertMail($name, $value = '', $message = '', $group = 'Email') {
|
||||
$captured_emails = \Drupal::state()->get('system.test_mail_collector') ?: array();
|
||||
$email = end($captured_emails);
|
||||
return $this->assertTrue($email && isset($email[$name]) && $email[$name] == $value, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the most recently sent email message has the string in it.
|
||||
*
|
||||
* @param $field_name
|
||||
* Name of field or message property to assert: subject, body, id, ...
|
||||
* @param $string
|
||||
* String to search for.
|
||||
* @param $email_depth
|
||||
* Number of emails to search for string, starting with most recent.
|
||||
* @param $message
|
||||
* (optional) A message to display with the assertion. Do not translate
|
||||
* messages: use \Drupal\Component\Utility\SafeMarkup::format() to embed
|
||||
* variables in the message text, not t(). If left blank, a default message
|
||||
* will be displayed.
|
||||
* @param $group
|
||||
* (optional) The group this message is in, which is displayed in a column
|
||||
* in test output. Use 'Debug' to indicate this is debugging output. Do not
|
||||
* translate this string. Defaults to 'Other'; most tests do not override
|
||||
* this default.
|
||||
*
|
||||
* @return
|
||||
* TRUE on pass, FALSE on fail.
|
||||
*/
|
||||
protected function assertMailString($field_name, $string, $email_depth, $message = '', $group = 'Other') {
|
||||
$mails = $this->drupalGetMails();
|
||||
$string_found = FALSE;
|
||||
// Cast MarkupInterface objects to string.
|
||||
$string = (string) $string;
|
||||
for ($i = count($mails) -1; $i >= count($mails) - $email_depth && $i >= 0; $i--) {
|
||||
$mail = $mails[$i];
|
||||
// Normalize whitespace, as we don't know what the mail system might have
|
||||
// done. Any run of whitespace becomes a single space.
|
||||
$normalized_mail = preg_replace('/\s+/', ' ', $mail[$field_name]);
|
||||
$normalized_string = preg_replace('/\s+/', ' ', $string);
|
||||
$string_found = (FALSE !== strpos($normalized_mail, $normalized_string));
|
||||
if ($string_found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$message) {
|
||||
$message = format_string('Expected text found in @field of email message: "@expected".', array('@field' => $field_name, '@expected' => $string));
|
||||
}
|
||||
return $this->assertTrue($string_found, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the most recently sent email message has the pattern in it.
|
||||
*
|
||||
* @param $field_name
|
||||
* Name of field or message property to assert: subject, body, id, ...
|
||||
* @param $regex
|
||||
* Pattern to search for.
|
||||
* @param $message
|
||||
* (optional) A message to display with the assertion. Do not translate
|
||||
* messages: use \Drupal\Component\Utility\SafeMarkup::format() to embed
|
||||
* variables in the message text, not t(). If left blank, a default message
|
||||
* will be displayed.
|
||||
* @param $group
|
||||
* (optional) The group this message is in, which is displayed in a column
|
||||
* in test output. Use 'Debug' to indicate this is debugging output. Do not
|
||||
* translate this string. Defaults to 'Other'; most tests do not override
|
||||
* this default.
|
||||
*
|
||||
* @return
|
||||
* TRUE on pass, FALSE on fail.
|
||||
*/
|
||||
protected function assertMailPattern($field_name, $regex, $message = '', $group = 'Other') {
|
||||
$mails = $this->drupalGetMails();
|
||||
$mail = end($mails);
|
||||
$regex_found = preg_match("/$regex/", $mail[$field_name]);
|
||||
if (!$message) {
|
||||
$message = format_string('Expected text found in @field of email message: "@expected".', array('@field' => $field_name, '@expected' => $regex));
|
||||
}
|
||||
return $this->assertTrue($regex_found, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs to verbose the most recent $count emails sent.
|
||||
*
|
||||
* @param $count
|
||||
* Optional number of emails to output.
|
||||
*/
|
||||
protected function verboseEmail($count = 1) {
|
||||
$mails = $this->drupalGetMails();
|
||||
for ($i = count($mails) -1; $i >= count($mails) - $count && $i >= 0; $i--) {
|
||||
$mail = $mails[$i];
|
||||
$this->verbose('Email:<pre>' . print_r($mail, TRUE) . '</pre>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock request and sets it on the generator.
|
||||
*
|
||||
|
|
|
@ -58,4 +58,9 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
|||
$this->assertSame('green', $value);
|
||||
}
|
||||
|
||||
public function testError() {
|
||||
$this->setExpectedException('\Exception', 'User notice: foo');
|
||||
$this->drupalGet('test-error');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,8 +7,12 @@
|
|||
|
||||
namespace Drupal\Tests\simpletest\Unit;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Drupal\Core\Extension\Extension;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\simpletest\TestDiscovery;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\simpletest\TestDiscovery
|
||||
|
@ -256,6 +260,130 @@ EOT;
|
|||
$this->assertEmpty($info['description']);
|
||||
}
|
||||
|
||||
protected function setupVfsWithTestClasses() {
|
||||
vfsStream::setup('drupal');
|
||||
|
||||
$test_file = <<<EOF
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test description
|
||||
* @group example
|
||||
*/
|
||||
class FunctionalExampleTest {}
|
||||
EOF;
|
||||
|
||||
vfsStream::create([
|
||||
'modules' => [
|
||||
'test_module' => [
|
||||
'tests' => [
|
||||
'src' => [
|
||||
'Functional' => [
|
||||
'FunctionalExampleTest.php' => $test_file,
|
||||
'FunctionalExampleTest2.php' => str_replace(['FunctionalExampleTest', '@group example'], ['FunctionalExampleTest2', '@group example2'], $test_file),
|
||||
],
|
||||
'Kernel' => [
|
||||
'KernelExampleTest3.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTest3', '@group example2'], $test_file),
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getTestClasses
|
||||
*/
|
||||
public function testGetTestClasses() {
|
||||
$this->setupVfsWithTestClasses();
|
||||
$class_loader = $this->prophesize(ClassLoader::class);
|
||||
$module_handler = $this->prophesize(ModuleHandlerInterface::class);
|
||||
|
||||
$test_discovery = new TestTestDiscovery('vfs://drupal', $class_loader->reveal(), $module_handler->reveal());
|
||||
|
||||
$extensions = [
|
||||
'test_module' => new Extension('vfs://drupal', 'module', 'modules/test_module/test_module.info.yml'),
|
||||
];
|
||||
$test_discovery->setExtensions($extensions);
|
||||
$result = $test_discovery->getTestClasses();
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertEquals([
|
||||
'example' => [
|
||||
'Drupal\Tests\test_module\Functional\FunctionalExampleTest' => [
|
||||
'name' => 'Drupal\Tests\test_module\Functional\FunctionalExampleTest',
|
||||
'description' => 'Test description',
|
||||
'group' => 'example',
|
||||
'type' => 'PHPUnit-Functional',
|
||||
],
|
||||
],
|
||||
'example2' => [
|
||||
'Drupal\Tests\test_module\Functional\FunctionalExampleTest2' => [
|
||||
'name' => 'Drupal\Tests\test_module\Functional\FunctionalExampleTest2',
|
||||
'description' => 'Test description',
|
||||
'group' => 'example2',
|
||||
'type' => 'PHPUnit-Functional',
|
||||
],
|
||||
'Drupal\Tests\test_module\Kernel\KernelExampleTest3' => [
|
||||
'name' => 'Drupal\Tests\test_module\Kernel\KernelExampleTest3',
|
||||
'description' => 'Test description',
|
||||
'group' => 'example2',
|
||||
'type' => 'PHPUnit-Kernel',
|
||||
],
|
||||
],
|
||||
], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getTestClasses
|
||||
*/
|
||||
public function testGetTestClassesWithSelectedTypes() {
|
||||
$this->setupVfsWithTestClasses();
|
||||
$class_loader = $this->prophesize(ClassLoader::class);
|
||||
$module_handler = $this->prophesize(ModuleHandlerInterface::class);
|
||||
|
||||
$test_discovery = new TestTestDiscovery('vfs://drupal', $class_loader->reveal(), $module_handler->reveal());
|
||||
|
||||
$extensions = [
|
||||
'test_module' => new Extension('vfs://drupal', 'module', 'modules/test_module/test_module.info.yml'),
|
||||
];
|
||||
$test_discovery->setExtensions($extensions);
|
||||
$result = $test_discovery->getTestClasses(NULL, ['PHPUnit-Kernel']);
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertEquals([
|
||||
'example' => [
|
||||
],
|
||||
'example2' => [
|
||||
'Drupal\Tests\test_module\Kernel\KernelExampleTest3' => [
|
||||
'name' => 'Drupal\Tests\test_module\Kernel\KernelExampleTest3',
|
||||
'description' => 'Test description',
|
||||
'group' => 'example2',
|
||||
'type' => 'PHPUnit-Kernel',
|
||||
],
|
||||
],
|
||||
], $result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestTestDiscovery extends TestDiscovery {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Extension\Extension[]
|
||||
*/
|
||||
protected $extensions = [];
|
||||
|
||||
public function setExtensions(array $extensions) {
|
||||
$this->extensions = $extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExtensions() {
|
||||
return $this->extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getPhpunitTestSuite
|
||||
* @dataProvider providerTestGetPhpunitTestSuite
|
||||
|
|
|
@ -33,10 +33,9 @@ class AdminRouteSubscriber extends RouteSubscriberBase {
|
|||
public static function getSubscribedEvents() {
|
||||
$events = parent::getSubscribedEvents();
|
||||
|
||||
// Use a higher priority than \Drupal\field_ui\Routing\RouteSubscriber or
|
||||
// \Drupal\views\EventSubscriber\RouteSubscriber to ensure we add the
|
||||
// option to their routes.
|
||||
// @todo https://www.drupal.org/node/2158571
|
||||
// Use a lower priority than \Drupal\field_ui\Routing\RouteSubscriber or
|
||||
// \Drupal\views\EventSubscriber\RouteSubscriber to ensure we add the option
|
||||
// to their routes.
|
||||
$events[RoutingEvents::ALTER] = array('onAlterRoutes', -200);
|
||||
|
||||
return $events;
|
||||
|
|
|
@ -12,6 +12,9 @@ use Drupal\Core\Entity\EntityInterface;
|
|||
|
||||
/**
|
||||
* Defines an abstract test base for entity unit tests.
|
||||
*
|
||||
* @deprecated in Drupal 8.1.x, will be removed before Drupal 8.2.x. Use
|
||||
* \Drupal\KernelTests\Core\Entity\EntityKernelTestBase instead.
|
||||
*/
|
||||
abstract class EntityUnitTestBase extends KernelTestBase {
|
||||
|
||||
|
|
|
@ -42,6 +42,27 @@ class ElementsTableSelectTest extends WebTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the presence of ajax functionality for all options.
|
||||
*/
|
||||
function testAjax() {
|
||||
$rows = array('row1', 'row2', 'row3');
|
||||
// Test checkboxes (#multiple == TRUE).
|
||||
foreach ($rows as $row) {
|
||||
$element = 'tableselect[' . $row . ']';
|
||||
$edit = array($element => TRUE);
|
||||
$result = $this->drupalPostAjaxForm('form_test/tableselect/multiple-true', $edit, $element);
|
||||
$this->assertFalse(empty($result), t('Ajax triggers on checkbox for @row.', array('@row' => $row)));
|
||||
}
|
||||
// Test radios (#multiple == FALSE).
|
||||
$element = 'tableselect';
|
||||
foreach ($rows as $row) {
|
||||
$edit = array($element => $row);
|
||||
$result = $this->drupalPostAjaxForm('form_test/tableselect/multiple-false', $edit, $element);
|
||||
$this->assertFalse(empty($result), t('Ajax triggers on radio for @row.', array('@row' => $row)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the display of radios when #multiple is FALSE.
|
||||
*/
|
||||
|
|
|
@ -412,7 +412,7 @@ function system_authorized_init($callback, $file, $arguments = array(), $page_ti
|
|||
* Return the URL for the authorize.php script.
|
||||
*
|
||||
* @param array $options
|
||||
* Optional array of options to pass to url().
|
||||
* Optional array of options to set on the \Drupal\Core\Url object.
|
||||
* @return \Drupal\Core\Url
|
||||
* The full URL to authorize.php, using HTTPS if available.
|
||||
*
|
||||
|
@ -431,7 +431,7 @@ function system_authorized_get_url(array $options = array()) {
|
|||
* Returns the URL for the authorize.php script when it is processing a batch.
|
||||
*
|
||||
* @param array $options
|
||||
* Optional array of options to pass to url().
|
||||
* Optional array of options to set on the \Drupal\Core\Url object.
|
||||
*
|
||||
* @return \Drupal\Core\Url
|
||||
*/
|
||||
|
|
|
@ -104,3 +104,10 @@ function form_test_form_form_test_vertical_tabs_access_form_alter(&$form, &$form
|
|||
$form['fieldset1']['#access'] = FALSE;
|
||||
$form['container']['#access'] = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback that returns the form element.
|
||||
*/
|
||||
function form_test_tableselect_ajax_callback($form, FormStateInterface $form_state) {
|
||||
return $form['tableselect'];
|
||||
}
|
||||
|
|
|
@ -34,11 +34,17 @@ abstract class FormTestTableSelectFormBase extends FormBase {
|
|||
$form['tableselect'] = $element_properties;
|
||||
|
||||
$form['tableselect'] += array(
|
||||
'#prefix' => '<div id="tableselect-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
'#type' => 'tableselect',
|
||||
'#header' => $header,
|
||||
'#options' => $options,
|
||||
'#multiple' => FALSE,
|
||||
'#empty' => t('Empty text.'),
|
||||
'#ajax' => array(
|
||||
'callback' => 'form_test_tableselect_ajax_callback',
|
||||
'wrapper' => 'tableselect-wrapper',
|
||||
),
|
||||
);
|
||||
|
||||
$form['submit'] = array(
|
||||
|
|
|
@ -86,4 +86,11 @@ class Test {
|
|||
throw new HttpException($code);
|
||||
}
|
||||
|
||||
public function error() {
|
||||
trigger_error('foo', E_USER_NOTICE);
|
||||
return [
|
||||
'#markup' => 'Content',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,3 +50,11 @@ test_page_test.http_response_exception:
|
|||
code: 200
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
test_page_test.error:
|
||||
path: '/test-error'
|
||||
defaults:
|
||||
_controller: '\Drupal\test_page_test\Controller\Test::error'
|
||||
code: 200
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
services:
|
||||
theme_test.subscriber:
|
||||
class: Drupal\theme_test\EventSubscriber\ThemeTestSubscriber
|
||||
arguments: [@current_route_match, @renderer]
|
||||
arguments: ['@current_route_match', '@renderer']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
|
||||
|
|
|
@ -65,18 +65,28 @@ class PhpStorageFactoryTest extends KernelTestBase {
|
|||
$this->setSettings('test', array('bin' => NULL));
|
||||
$php = PhpStorageFactory::get('test');
|
||||
$this->assertTrue($php instanceof MockPhpStorage, 'An MockPhpStorage instance was returned from overridden settings.');
|
||||
$this->assertIdentical('test', $php->getConfigurationValue('bin'), 'Name value was used for bin.');
|
||||
$this->assertSame('test', $php->getConfigurationValue('bin'), 'Name value was used for bin.');
|
||||
|
||||
// Test that a default directory is set if it's empty.
|
||||
$this->setSettings('test', array('directory' => NULL));
|
||||
$php = PhpStorageFactory::get('test');
|
||||
$this->assertTrue($php instanceof MockPhpStorage, 'An MockPhpStorage instance was returned from overridden settings.');
|
||||
$this->assertIdentical(PublicStream::basePath() . '/php', $php->getConfigurationValue('directory'), 'Default file directory was used.');
|
||||
$this->assertSame(PublicStream::basePath() . '/php', $php->getConfigurationValue('directory'), 'Default file directory was used.');
|
||||
|
||||
// Test that a default storage class is set if it's empty.
|
||||
$this->setSettings('test', array('class' => NULL));
|
||||
$php = PhpStorageFactory::get('test');
|
||||
$this->assertTrue($php instanceof MTimeProtectedFileStorage, 'An MTimeProtectedFileStorage instance was returned from overridden settings with no class.');
|
||||
|
||||
// Test that a default secret is not returned if it's set in the override.
|
||||
$this->setSettings('test');
|
||||
$php = PhpStorageFactory::get('test');
|
||||
$this->assertNotEquals('mock hash salt', $php->getConfigurationValue('secret'), 'The default secret is not used if a secret is set in the overridden settings.');
|
||||
|
||||
// Test that a default secret is set if it's empty.
|
||||
$this->setSettings('test', array('secret' => NULL));
|
||||
$php = PhpStorageFactory::get('test');
|
||||
$this->assertSame('mock hash salt', $php->getConfigurationValue('secret'), 'The default secret is used if one is not set in the overridden settings.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,6 +104,7 @@ class PhpStorageFactoryTest extends KernelTestBase {
|
|||
'secret' => $this->randomString(),
|
||||
'bin' => 'test',
|
||||
);
|
||||
$settings['hash_salt'] = 'mock hash salt';
|
||||
new Settings($settings);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ source:
|
|||
entity_type: node
|
||||
type: entity_reference
|
||||
target_entity_type: taxonomy_term
|
||||
cardinality: -1
|
||||
process:
|
||||
entity_type: 'constants/entity_type'
|
||||
type: 'constants/type'
|
||||
|
@ -21,7 +20,7 @@ process:
|
|||
plugin: skip_on_empty
|
||||
method: row
|
||||
'settings/target_type': 'constants/target_entity_type'
|
||||
cardinality: 'constants/cardinality'
|
||||
cardinality: cardinality
|
||||
destination:
|
||||
plugin: md_entity:field_storage_config
|
||||
migration_dependencies:
|
||||
|
|
|
@ -27,7 +27,7 @@ class OverviewTerms extends FormBase {
|
|||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The term storage controller.
|
||||
* The term storage handler.
|
||||
*
|
||||
* @var \Drupal\taxonomy\TermStorageInterface
|
||||
*/
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\taxonomy\Plugin\migrate\source\d6;
|
|||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Drupal 6 vocabularies source from database.
|
||||
|
@ -72,6 +73,7 @@ class Vocabulary extends DrupalSqlBase {
|
|||
->execute()
|
||||
->fetchCol();
|
||||
$row->setSourceProperty('node_types', $node_types);
|
||||
$row->setSourceProperty('cardinality', ($row->getSourceProperty('tags') == 1 || $row->getSourceProperty('multiple') == 1) ? FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED : 1);
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use Drupal\Core\Entity\ContentEntityForm;
|
|||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Base for controller for taxonomy term edit forms.
|
||||
* Base for handler for taxonomy term edit forms.
|
||||
*/
|
||||
class TermForm extends ContentEntityForm {
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use Drupal\Core\Entity\EntityInterface;
|
|||
use Drupal\Core\Entity\EntityViewBuilder;
|
||||
|
||||
/**
|
||||
* Render controller for taxonomy terms.
|
||||
* View builder handler for taxonomy terms.
|
||||
*/
|
||||
class TermViewBuilder extends EntityViewBuilder {
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Drupal\taxonomy\Tests\Migrate\d6;
|
|||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\migrate\Entity\Migration;
|
||||
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
|
||||
/**
|
||||
* Vocabulary field instance migration.
|
||||
|
|
|
@ -37,11 +37,13 @@ class MigrateVocabularyFieldTest extends MigrateDrupal6TestBase {
|
|||
public function testVocabularyField() {
|
||||
// Test that the field exists.
|
||||
$field_storage_id = 'node.tags';
|
||||
/** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
|
||||
$field_storage = FieldStorageConfig::load($field_storage_id);
|
||||
$this->assertIdentical($field_storage_id, $field_storage->id());
|
||||
|
||||
$settings = $field_storage->getSettings();
|
||||
$this->assertIdentical('taxonomy_term', $settings['target_type'], "Target type is correct.");
|
||||
$this->assertIdentical(1, $field_storage->getCardinality(), "Field cardinality in 1.");
|
||||
|
||||
$this->assertIdentical(array('node', 'tags'), Migration::load('d6_vocabulary_field')->getIdMap()->lookupDestinationID(array(4)), "Test IdMap");
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Drupal\taxonomy;
|
|||
use Drupal\Core\Config\Entity\ConfigEntityStorage;
|
||||
|
||||
/**
|
||||
* Defines a controller class for taxonomy vocabularies.
|
||||
* Defines a storage handler class for taxonomy vocabularies.
|
||||
*/
|
||||
class VocabularyStorage extends ConfigEntityStorage implements VocabularyStorageInterface {
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\Tests\taxonomy\Unit\Migrate\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Tests D6 vocabulary source plugin.
|
||||
|
@ -39,6 +40,7 @@ class VocabularyTest extends MigrateSqlSourceTestCase {
|
|||
'module' => 'taxonomy',
|
||||
'weight' => 0,
|
||||
'node_types' => ['page', 'article'],
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
],
|
||||
[
|
||||
'vid' => 2,
|
||||
|
@ -53,6 +55,7 @@ class VocabularyTest extends MigrateSqlSourceTestCase {
|
|||
'module' => 'taxonomy',
|
||||
'weight' => 0,
|
||||
'node_types' => ['article'],
|
||||
'cardinality' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
|
||||
/**
|
||||
* Form controller for the profile forms.
|
||||
* Form handler for the profile forms.
|
||||
*/
|
||||
class ProfileForm extends AccountForm {
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
|
||||
/**
|
||||
* Form controller for the user register forms.
|
||||
* Form handler for the user register forms.
|
||||
*/
|
||||
class RegisterForm extends AccountForm {
|
||||
|
||||
|
|
|
@ -54,6 +54,11 @@ EOT;
|
|||
$this->assertIdentical('Queen', $user->profile_bands[5]->value);
|
||||
$this->assertIdentical('The White Stripes', $user->profile_bands[6]->value);
|
||||
$this->assertIdentical('1974-06-02', $user->profile_birthdate->value);
|
||||
$this->assertIdentical('http://example.com/blog', $user->profile_blog->uri);
|
||||
$this->assertNull($user->profile_blog->title);
|
||||
$this->assertIdentical([], $user->profile_blog->options);
|
||||
$this->assertIdentical('http://example.com/blog', $user->profile_blog->uri);
|
||||
$this->assertNull($user->profile_love_migrations->value);
|
||||
|
||||
$user = User::load(8);
|
||||
$this->assertIdentical('Forward/slash', $user->profile_sold_to->value);
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
* - extra: Additional text to append to the user's name, sanitized.
|
||||
* - link_path: The path or URL of the user's profile page, home page,
|
||||
* or other desired page to link to for more information about the user.
|
||||
* - link_options: Options to pass to the url() function's $options parameter if
|
||||
* linking the user's name to the user's page.
|
||||
* - link_options: Options to set on the \Drupal\Core\Url object if linking the
|
||||
* user's name to the user's page.
|
||||
* - attributes: HTML attributes for the containing element.
|
||||
*
|
||||
* @see template_preprocess_username()
|
||||
|
|
|
@ -28,7 +28,7 @@ class EntityViewsData implements EntityHandlerInterface, EntityViewsDataInterfac
|
|||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* Entity type for this views controller instance.
|
||||
* Entity type for this views data handler instance.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface
|
||||
*/
|
||||
|
@ -68,7 +68,7 @@ class EntityViewsData implements EntityHandlerInterface, EntityViewsDataInterfac
|
|||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type to provide views integration for.
|
||||
* @param \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage_controller
|
||||
* The storage controller used for this entity type.
|
||||
* The storage handler used for this entity type.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
|
|
|
@ -735,12 +735,12 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface {
|
|||
|
||||
// Determine if the string has 'or' operators (plus signs) or 'and'
|
||||
// operators (commas) and split the string accordingly.
|
||||
if (preg_match('/^([\w0-9-_]+[+ ]+)+[\w0-9-_]+$/u', $str)) {
|
||||
if (preg_match('/^([\w0-9-_\.]+[+ ]+)+[\w0-9-_\.]+$/u', $str)) {
|
||||
// The '+' character in a query string may be parsed as ' '.
|
||||
$operator = 'or';
|
||||
$value = preg_split('/[+ ]/', $str);
|
||||
}
|
||||
elseif (preg_match('/^([\w0-9-_]+[, ]+)*[\w0-9-_]+$/u', $str)) {
|
||||
elseif (preg_match('/^([\w0-9-_\.]+[, ]+)*[\w0-9-_\.]+$/u', $str)) {
|
||||
$operator = 'and';
|
||||
$value = explode(',', $str);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ class NumericArgument extends ArgumentPluginBase {
|
|||
}
|
||||
|
||||
if (!empty($this->options['break_phrase'])) {
|
||||
$break = static::breakString($this->argument, TRUE);
|
||||
$break = static::breakString($this->argument, FALSE);
|
||||
$this->value = $break->value;
|
||||
$this->operator = $break->operator;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ class NumericArgument extends ArgumentPluginBase {
|
|||
$this->ensureMyTable();
|
||||
|
||||
if (!empty($this->options['break_phrase'])) {
|
||||
$break = static::breakString($this->argument, TRUE);
|
||||
$break = static::breakString($this->argument, FALSE);
|
||||
$this->value = $break->value;
|
||||
$this->operator = $break->operator;
|
||||
}
|
||||
|
|
|
@ -119,7 +119,8 @@ class EntityReference extends DisplayPluginBase {
|
|||
|
||||
// Make sure the id field is included in the results.
|
||||
$id_field = $this->view->storage->get('base_field');
|
||||
$this->id_field_alias = $this->view->query->addField($this->view->storage->get('base_table'), $id_field);
|
||||
$id_table = $this->view->storage->get('base_table');
|
||||
$this->id_field_alias = $this->view->query->addField($id_table, $id_field);
|
||||
|
||||
$options = $this->getOption('entity_reference_options');
|
||||
|
||||
|
@ -139,7 +140,8 @@ class EntityReference extends DisplayPluginBase {
|
|||
if (!empty($field_id)) {
|
||||
// Get the table and field names for the checked field.
|
||||
$field_handler = $this->view->field[$field_id];
|
||||
$field_alias = $this->view->query->addField($field_handler->table, $field_handler->realField);
|
||||
$table_alias = $this->view->query->ensureTable($field_handler->table, $field_handler->relationship);
|
||||
$field_alias = $this->view->query->addField($table_alias, $field_handler->realField);
|
||||
$field = $this->view->query->fields[$field_alias];
|
||||
// Add an OR condition for the field.
|
||||
$conditions->condition($field['table'] . '.' . $field['field'], $value, 'LIKE');
|
||||
|
@ -151,7 +153,7 @@ class EntityReference extends DisplayPluginBase {
|
|||
|
||||
// Add an IN condition for validation.
|
||||
if (!empty($options['ids'])) {
|
||||
$this->view->query->addWhere(0, $id_field, $options['ids'], 'IN');
|
||||
$this->view->query->addWhere(0, $id_table . '.' . $id_field, $options['ids'], 'IN');
|
||||
}
|
||||
|
||||
$this->view->setItemsPerPage($options['limit']);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue