diff --git a/core/modules/views/src/Tests/ViewExecutableTest.php b/core/modules/views/src/Tests/ViewExecutableTest.php index 5b0fe2b..4b0e73f 100644 --- a/core/modules/views/src/Tests/ViewExecutableTest.php +++ b/core/modules/views/src/Tests/ViewExecutableTest.php @@ -309,11 +309,6 @@ public function testPropertyMethods() { $view->setResponse($new_response); $this->assertIdentical(spl_object_hash($view->getResponse()), spl_object_hash($new_response), 'New response object correctly set.'); - // Test the generateHandlerId() method. - $test_ids = array('test' => 'test', 'test_1' => 'test_1'); - $this->assertEqual($view->generateHandlerId('new', $test_ids), 'new'); - $this->assertEqual($view->generateHandlerId('test', $test_ids), 'test_2'); - // Test the getPath() method. $path = $this->randomMachineName(); $view->displayHandlers->get('page_1')->overrideOption('path', $path); diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php index 629bd39..6d5e55c 100644 --- a/core/modules/views/src/ViewExecutable.php +++ b/core/modules/views/src/ViewExecutable.php @@ -418,18 +418,28 @@ class ViewExecutable { protected $showAdminLinks; /** + * The views data. + * + * @var \Drupal\views\ViewsData + */ + protected $viewsData; + + /** * Constructs a new ViewExecutable object. * * @param \Drupal\views\ViewStorageInterface $storage * The view config entity the actual information is stored on. * @param \Drupal\Core\Session\AccountInterface $user * The current user. + * @param \Drupal\views\ViewsData $views_data + * The views data. */ - public function __construct(ViewStorageInterface $storage, AccountInterface $user) { + public function __construct(ViewStorageInterface $storage, AccountInterface $user, ViewsData $views_data) { // Reference the storage and the executable to each other. $this->storage = $storage; $this->storage->set('executable', $this); $this->user = $user; + $this->viewsData = $views_data; // Add the default css for a view. $this->element['#attached']['library'][] = 'views/views.module'; @@ -1900,7 +1910,7 @@ public function addHandler($display_id, $type, $table, $field, $options = array( $types = $this::getHandlerTypes(); $this->setDisplay($display_id); - $data = Views::viewsData()->get($table); + $data = $this->viewsData->get($table); $fields = $this->displayHandlers->get($display_id)->getOption($types[$type]['plural']); if (empty($id)) { @@ -1920,7 +1930,7 @@ public function addHandler($display_id, $type, $table, $field, $options = array( $fields[$id]['entity_type'] = $data['table']['entity type']; } if (isset($data[$field]['entity field'])) { - $fields[$id]['entity_field'] = $data['table']['entity type']; + $fields[$id]['entity_field'] = $data[$field]['entity field']; } // Load the plugin ID if available. diff --git a/core/modules/views/src/ViewExecutableFactory.php b/core/modules/views/src/ViewExecutableFactory.php index 9ee217c..ed6bdd0 100644 --- a/core/modules/views/src/ViewExecutableFactory.php +++ b/core/modules/views/src/ViewExecutableFactory.php @@ -31,16 +31,26 @@ class ViewExecutableFactory { protected $requestStack; /** + * The views data. + * + * @var \Drupal\views\ViewsData + */ + protected $viewsData; + + /** * Constructs a new ViewExecutableFactory * * @param \Drupal\Core\Session\AccountInterface $user * The current user. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack * The request stack. + * @param \Drupal\views\ViewsData $views_data + * The views data. */ - public function __construct(AccountInterface $user, RequestStack $request_stack) { + public function __construct(AccountInterface $user, RequestStack $request_stack, ViewsData $views_data) { $this->user = $user; $this->requestStack = $request_stack; + $this->viewsData = $views_data; } /** @@ -53,7 +63,7 @@ public function __construct(AccountInterface $user, RequestStack $request_stack) * A ViewExecutable instance. */ public function get(ViewStorageInterface $view) { - $view = new ViewExecutable($view, $this->user); + $view = new ViewExecutable($view, $this->user, $this->viewsData); $view->setRequest($this->requestStack->getCurrentRequest()); return $view; } diff --git a/core/modules/views/tests/src/Unit/ViewExecutableFactoryTest.php b/core/modules/views/tests/src/Unit/ViewExecutableFactoryTest.php index d9130d5..730dd37 100644 --- a/core/modules/views/tests/src/Unit/ViewExecutableFactoryTest.php +++ b/core/modules/views/tests/src/Unit/ViewExecutableFactoryTest.php @@ -47,6 +47,13 @@ class ViewExecutableFactoryTest extends UnitTestCase { protected $viewExecutableFactory; /** + * The mocked views data. + * + * @var \Drupal\views\ViewsData|\PHPUnit_Framework_MockObject_MockObject + */ + protected $viewsData; + + /** * {@inheritdoc} */ protected function setUp() { @@ -55,7 +62,10 @@ protected function setUp() { $this->user = $this->getMock('Drupal\Core\Session\AccountInterface'); $this->requestStack = new RequestStack(); $this->view = $this->getMock('Drupal\views\ViewStorageInterface'); - $this->viewExecutableFactory = new ViewExecutableFactory($this->user, $this->requestStack); + $this->viewsData = $this->getMockBuilder('Drupal\views\ViewsData') + ->disableOriginalConstructor() + ->getMock(); + $this->viewExecutableFactory = new ViewExecutableFactory($this->user, $this->requestStack, $this->viewsData); } /** diff --git a/core/modules/views/tests/src/Unit/ViewExecutableUnitTest.php b/core/modules/views/tests/src/Unit/ViewExecutableUnitTest.php index 13042df..78e92dc 100644 --- a/core/modules/views/tests/src/Unit/ViewExecutableUnitTest.php +++ b/core/modules/views/tests/src/Unit/ViewExecutableUnitTest.php @@ -10,6 +10,7 @@ use Drupal\Tests\UnitTestCase; use Drupal\views\Entity\View; use Drupal\views\ViewExecutable; +use Symfony\Component\DependencyInjection\ContainerBuilder; /** * @coversDefaultClass \Drupal\views\ViewExecutable @@ -18,38 +19,63 @@ class ViewExecutableUnitTest extends UnitTestCase { /** + * The mocked views data. + * + * @var \Drupal\views\ViewsData|\PHPUnit_Framework_MockObject_MockObject + */ + protected $viewsData; + + /** + * The mocked user. + * + * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $user; + + /** + * A mocked display collection. + * + * @var \Drupal\views\DisplayPluginCollection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $displayCollection; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->viewsData = $this->getMockBuilder('Drupal\views\ViewsData') + ->disableOriginalConstructor() + ->getMock(); + $this->user = $this->getMock('Drupal\Core\Session\AccountInterface'); + + $this->displayCollection = $this->getMockBuilder('Drupal\views\DisplayPluginCollection') + ->disableOriginalConstructor() + ->getMock(); + + $translation = $this->getStringTranslationStub(); + $container = new ContainerBuilder(); + $container->set('string_translation', $translation); + \Drupal::setContainer($container); + } + + /** * Tests the buildThemeFunctions() method. */ public function testBuildThemeFunctions() { - $config = array( - 'id' => 'test_view', - 'tag' => 'OnE, TWO, and three', - 'display' => array( - 'default' => array( - 'id' => 'default', - 'display_plugin' => 'default', - 'display_title' => 'Default', - ), - ), - ); - - $storage = new View($config, 'view'); - $user = $this->getMock('Drupal\Core\Session\AccountInterface'); - $view = new ViewExecutable($storage, $user); + /** @var \Drupal\views\ViewExecutable $view */ + /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase $display */ + list($view, $display) = $this->setupBaseViewAndDisplay(); + unset($view->display_handler); $expected = array( 'test_hook__test_view', 'test_hook' ); $this->assertEquals($expected, $view->buildThemeFunctions('test_hook')); - // Add a mock display. - $display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase') - ->disableOriginalConstructor() - ->getMock(); - $display->display = $config['display']['default']; $view->display_handler = $display; - $expected = array( 'test_hook__test_view__default', 'test_hook__default', @@ -78,4 +104,141 @@ public function testBuildThemeFunctions() { $this->assertEquals($expected, $view->buildThemeFunctions('test_hook')); } + /** + * Tests the generateHandlerId method(). + * + * @covers ::generateHandlerId() + */ + public function testGenerateHandlerId() { + // Test the generateHandlerId() method. + $test_ids = ['test' => 'test', 'test_1' => 'test_1']; + $this->assertEquals(ViewExecutable::generateHandlerId('new', $test_ids), 'new'); + $this->assertEquals(ViewExecutable::generateHandlerId('test', $test_ids), 'test_2'); + } + + /** + * Tests the addHandler method(). + * + * @covers ::addHandler() + */ + public function testAddHandler() { + /** @var \Drupal\views\ViewExecutable $view */ + /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase $display */ + list($view, $display) = $this->setupBaseViewAndDisplay(); + + $views_data = []; + $views_data['test_field'] = [ + 'field' => ['id' => 'standard'], + 'filter' => ['id' => 'standard'], + 'argument' => ['id' => 'standard'], + 'sort' => ['id' => 'standard'], + ]; + + $this->viewsData->expects($this->atLeastOnce()) + ->method('get') + ->with('test_entity') + ->willReturn($views_data); + + foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) { + $display->expects($this->atLeastOnce()) + ->method('setOption') + ->with($this->callback(function($argument) { + return $argument; + }), ['test_field' => [ + 'id' => 'test_field', + 'table' => 'test_entity', + 'field' => 'test_field', + 'plugin_id' => 'standard', + ]]); + } + + foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) { + $view->addHandler('default', $handler_type, 'test_entity', 'test_field'); + } + } + + /** + * Tests the addHandler method() with an entity field. + * + * @covers ::addHandler() + */ + public function testAddHandlerWithEntityField() { + /** @var \Drupal\views\ViewExecutable $view */ + /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase $display */ + list($view, $display) = $this->setupBaseViewAndDisplay(); + + $views_data = []; + $views_data['table']['entity type'] = 'test_entity_type'; + $views_data['test_field'] = [ + 'entity field' => 'test_field', + 'field' => ['id' => 'standard'], + 'filter' => ['id' => 'standard'], + 'argument' => ['id' => 'standard'], + 'sort' => ['id' => 'standard'], + ]; + + $this->viewsData->expects($this->atLeastOnce()) + ->method('get') + ->with('test_entity') + ->willReturn($views_data); + + foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) { + $display->expects($this->atLeastOnce()) + ->method('setOption') + ->with($this->callback(function($argument) { + return $argument; + }), ['test_field' => [ + 'id' => 'test_field', + 'table' => 'test_entity', + 'field' => 'test_field', + 'entity_type' => 'test_entity_type', + 'entity_field' => 'test_field', + 'plugin_id' => 'standard', + ]]); + } + + foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) { + $view->addHandler('default', $handler_type, 'test_entity', 'test_field'); + } + } + + /** + * Setups a view executable and default display. + * + * @return array + * Returns the view executable and default display. + */ + protected function setupBaseViewAndDisplay() { + $config = array( + 'id' => 'test_view', + 'tag' => 'OnE, TWO, and three', + 'display' => [ + 'default' => [ + 'id' => 'default', + 'display_plugin' => 'default', + 'display_title' => 'Default', + ], + ], + ); + + $storage = new View($config, 'view'); + $view = new ViewExecutable($storage, $this->user, $this->viewsData); + $display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase') + ->disableOriginalConstructor() + ->getMock(); + $display->display = $config['display']['default']; + + $view->current_display = 'default'; + $view->display_handler = $display; + $view->displayHandlers = $this->displayCollection; + $view->displayHandlers->expects($this->any()) + ->method('get') + ->with('default') + ->willReturn($display); + $view->displayHandlers->expects($this->any()) + ->method('has') + ->with('default') + ->willReturn(TRUE); + return array($view, $display); + } } diff --git a/core/modules/views/views.services.yml b/core/modules/views/views.services.yml index 343e0b3..9654432 100644 --- a/core/modules/views/views.services.yml +++ b/core/modules/views/views.services.yml @@ -64,7 +64,7 @@ services: arguments: ['@views.views_data'] views.executable: class: Drupal\views\ViewExecutableFactory - arguments: ['@current_user', '@request_stack'] + arguments: ['@current_user', '@request_stack', '@views.views_data'] views.analyzer: class: Drupal\views\Analyzer arguments: ['@module_handler']