Commit 5583e7d5 authored by catch's avatar catch

Issue #2551727 by quietone, Jo Fitzgerald, phenaproxima, neclimdul,...

Issue #2551727 by quietone, Jo Fitzgerald, phenaproxima, neclimdul, joelpittet, iMiksu, lostkangaroo, heddn, mikeryan, geste, alexpott, benjy: Menu link migrations should be defensive
parent 5ba1f0e1
......@@ -5,6 +5,7 @@
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Url;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
......@@ -80,6 +81,9 @@ public function transform($value, MigrateExecutableInterface $migrate_executable
}
}
}
else {
throw new MigrateException(sprintf('The path "%s" failed validation.', $path));
}
}
return $path;
}
......
......@@ -29,7 +29,7 @@ protected function setUp() {
$this->installEntitySchema('menu_link_content');
$this->installEntitySchema('node');
$node = Node::create([
'nid' => 3,
'nid' => 2,
'title' => 'node link test',
'type' => 'article',
]);
......@@ -90,8 +90,8 @@ public function testMenuLinks() {
// Tests migrating an external link with an undefined title attribute.
$this->assertEntity(470, 'Ask', static::MENU_NAME, NULL, TRUE, FALSE, [], 'http://ask.com', 0);
$this->assertEntity(245, 'Home', 'main', NULL, TRUE, FALSE, [], 'internal:/', 0);
$this->assertEntity(478, 'custom link test', 'admin', NULL, TRUE, FALSE, ['attributes' => ['title' => '']], 'internal:/admin/content/book', 0);
$this->assertEntity(479, 'node link test', 'tools', 'node 3', TRUE, FALSE, ['attributes' => ['title' => 'node 3']], 'entity:node/3', 3);
$this->assertEntity(478, 'custom link test', 'admin', NULL, TRUE, FALSE, ['attributes' => ['title' => '']], 'internal:/admin/content', 0);
$this->assertEntity(479, 'node link test', 'tools', 'node 2', TRUE, FALSE, ['attributes' => ['title' => 'node 2']], 'entity:node/2', 3);
$menu_link_tree_service = \Drupal::service('menu.link_tree');
$parameters = new MenuTreeParameters();
......
<?php
namespace Drupal\Tests\menu_link_content\Unit\Plugin\migrate\process;
namespace Drupal\Tests\menu_link_content\Kernel\Plugin\migrate\process;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Url;
use Drupal\menu_link_content\Plugin\migrate\process\LinkUri;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;
use Drupal\Tests\UnitTestCase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Path\PathValidator;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests \Drupal\menu_link_content\Plugin\migrate\process\LinkUri.
......@@ -18,83 +15,64 @@
*
* @coversDefaultClass \Drupal\menu_link_content\Plugin\migrate\process\LinkUri
*/
class LinkUriTest extends UnitTestCase {
class LinkUriTest extends KernelTestBase {
/**
* The entity type manager prophecy used in the test.
* Tests LinkUri::transform().
*
* @var \Prophecy\Prophecy\ProphecyInterface|\Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The 'link_uri' process plugin being tested.
* @param array $value
* The value to pass to LinkUri::transform().
* @param string $expected
* The expected return value of LinkUri::transform().
*
* @var \Drupal\menu_link_content\Plugin\migrate\process\LinkUri
*/
protected $processPlugin;
/**
* The path validator prophecy used in the test.
* @dataProvider providerTestRouted
*
* @var \Drupal\Core\Path\PathValidator
* @covers ::transform
*/
protected $pathValidator;
public function testRouted(array $value, $expected) {
$actual = $this->doTransform($value);
$this->assertSame($expected, $actual);
}
/**
* The fake entity type ID used in the test.
* Provides test cases for LinkUriTest::testTransform().
*
* @var string
* @return array
* An array of test cases, each which the following values:
* - The value array to pass to LinkUri::transform().
* - The expected path returned by LinkUri::transform().
*/
protected $entityTypeId = 'the_entity_type_id';
public function providerTestRouted() {
$tests = [];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
$this->entityTypeManager->getDefinitions()->willReturn([$this->entityTypeId => '']);
$this->processPlugin = new LinkUri([], 'link_uri', [], $this->entityTypeManager->reveal());
// Url::fromInternalUri() accesses the path validator from the global
// container.
// @see \Drupal\Core\Url::fromInternalUri()
$this->pathValidator = $this->prophesize(PathValidator::class);
$container = new ContainerBuilder();
$container->set('path.validator', $this->pathValidator->reveal());
\Drupal::setContainer($container);
$value = ['http://example.com'];
$expected = 'http://example.com';
$tests['with_scheme'] = [$value, $expected];
$value = ['<front>'];
$expected = 'internal:/';
$tests['front'] = [$value, $expected];
return $tests;
}
/**
* Tests LinkUri::transform().
* Tests that Non routed URLs throws an exception.
*
* @param array $value
* The value to pass to LinkUri::transform().
* @param string $expected
* The expected return value of LinkUri::transform().
* @param \Drupal\Core\Url $url
* (optional) The URL that the path validator prophecy will return.
*
* @dataProvider providerTestTransform
* @param string $exception_message
* The expected exception message.
*
* @covers ::transform
* @dataProvider providerTestNotRouted
*/
public function testTransform(array $value, $expected, Url $url = NULL) {
$migrate_executable = $this->prophesize(MigrateExecutableInterface::class);
$row = $this->prophesize(Row::class);
if ($url) {
$this->pathValidator->getUrlIfValidWithoutAccessCheck(reset($value))->willReturn($url);
}
$actual = $this->processPlugin->transform($value, $migrate_executable->reveal(), $row->reveal(), 'link/uri');
$this->assertEquals($expected, $actual);
public function testNotRouted(array $value, $exception_message) {
$this->setExpectedException(MigrateException::class, $exception_message);
$this->doTransform($value);
}
/**
* Provides test cases for LinkUriTest::testTransform().
* Provides test cases for LinkUriTest::testNotRouted().
*
* @return array
* An array of test cases, each which the following values:
......@@ -102,39 +80,43 @@ public function testTransform(array $value, $expected, Url $url = NULL) {
* - The expected path returned by LinkUri::transform().
* - (optional) A URL object that the path validator prophecy will return.
*/
public function providerTestTransform() {
public function providerTestNotRouted() {
$tests = [];
$value = ['http://example.com'];
$expected = 'http://example.com';
$tests['with_scheme'] = [$value, $expected];
$message = 'The path "%s" failed validation.';
$value = ['/test'];
$expected = 'internal:/test';
$tests['leading_slash'] = [$value, $expected];
$exception_message = sprintf($message, $expected);
$tests['leading_slash'] = [$value, $exception_message];
$value = ['test'];
$expected = 'internal:/test';
$tests['without_scheme'] = [$value, $expected];
$exception_message = sprintf($message, $expected);
$tests['without_scheme'] = [$value, $exception_message];
$value = ['<front>'];
$expected = 'internal:/';
$tests['front'] = [$value, $expected];
$url = Url::fromRoute('route_name');
$tests['with_route'] = [$value, $expected, $url];
$url = Url::fromRoute('entity.not_an_entity_type_id.canonical');
$tests['without_entity_type'] = [$value, $expected, $url];
return $tests;
}
$url = Url::fromRoute('entity.the_entity_type_id.canonical');
$tests['without_route_parameter'] = [$value, $expected, $url];
/**
* Transforms a link path into an 'internal:' or 'entity:' URI.
*
* @param array $value
* The value to pass to LinkUri::transform().
*
* @return string
* The transformed link.
*/
public function doTransform(array $value) {
$entityTypeManager = $this->container->get('entity_type.manager');
$routeBuilder = $this->container->get('router.builder');
$row = new Row();
$executable = $this->prophesize(MigrateExecutableInterface::class)->reveal();
$url = Url::fromRoute('entity.the_entity_type_id.canonical', ['the_entity_type_id' => 'the_entity_id']);
$expected = 'entity:the_entity_type_id/the_entity_id';
$tests['entity_path'] = [$value, $expected, $url];
$plugin = new LinkUri([], 'link_uri', [], $entityTypeManager, $routeBuilder);
$actual = $plugin->transform($value, $executable, $row, 'destinationproperty');
return $tests;
return $actual;
}
}
......@@ -20487,8 +20487,8 @@
'menu_name' => 'management',
'mlid' => '478',
'plid' => '20',
'link_path' => 'admin/content/book',
'router_path' => 'admin/content/book',
'link_path' => 'admin/content',
'router_path' => 'admin/content',
'link_title' => 'custom link test',
'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}}',
'module' => 'menu',
......@@ -20514,10 +20514,10 @@
'menu_name' => 'navigation',
'mlid' => '479',
'plid' => '0',
'link_path' => 'node/3',
'router_path' => 'node/3',
'link_path' => 'node/2',
'router_path' => 'node/2',
'link_title' => 'node link test',
'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:6:"node 3";}}',
'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:6:"node 2";}}',
'module' => 'menu',
'hidden' => '0',
'external' => '0',
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment