Commit 1903e50f authored by alexpott's avatar alexpott

Issue #2068287 by Berdir, andypost: Support bundle names provided in the...

Issue #2068287 by Berdir, andypost: Support bundle names provided in the request arguments in EntityCreateAccessCheck.
parent 36a898eb
......@@ -52,6 +52,19 @@ public function appliesTo() {
*/
public function access(Route $route, Request $request) {
list($entity_type, $bundle) = explode(':', $route->getRequirement($this->requirementsKey) . ':');
// The bundle argument can contain request argument placeholders like
// {name}, loop over the raw variables and attempt to replace them in the
// bundle name. If a placeholder does not exist, it won't get replaced.
if ($bundle && strpos($bundle, '{') !== FALSE) {
foreach ($request->get('_raw_variables')->all() as $name => $value) {
$bundle = str_replace('{' . $name . '}', $value, $bundle);
}
// If we were unable to replace all placeholders, deny access.
if (strpos($bundle, '{') !== FALSE) {
return static::DENY;
}
}
return $this->entityManager->getAccessController($entity_type)->createAccess($bundle) ? static::ALLOW : static::DENY;
}
......
<?php
/**
* @file
* Contains \Drupal\taxonomy\Access\TaxonomyTermCreateAccess.
*/
namespace Drupal\taxonomy\Access;
use Drupal\Core\Entity\EntityCreateAccessCheck;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
/**
* Provides an access check for taxonomy term creation.
*/
class TaxonomyTermCreateAccess extends EntityCreateAccessCheck {
/**
* {@inheritdoc}
*/
protected $requirementsKey = '_access_taxonomy_term_create';
/**
* {@inheritdoc}
*/
public function access(Route $route, Request $request) {
$entity_type = $route->getRequirement($this->requirementsKey);
if ($vocabulary = $request->attributes->get('taxonomy_vocabulary')) {
return $this->entityManager->getAccessController($entity_type)->createAccess($vocabulary->id()) ? static::ALLOW : static::DENY;
}
return parent::access($route, $request);
}
}
......@@ -10,7 +10,7 @@ taxonomy_term_add:
defaults:
_content: '\Drupal\taxonomy\Controller\TaxonomyController::addForm'
requirements:
_access_taxonomy_term_create: 'taxonomy_term'
_entity_create_access: 'taxonomy_term:{taxonomy_vocabulary}'
taxonomy_term_edit:
pattern: '/taxonomy/term/{taxonomy_term}/edit'
......
services:
access_check.taxonomy_term.create:
class: Drupal\taxonomy\Access\TaxonomyTermCreateAccess
arguments: ['@entity.manager']
tags:
- { name: access_check }
......@@ -10,6 +10,7 @@
use Drupal\Core\Access\AccessCheckInterface;
use Drupal\Core\Entity\EntityCreateAccessCheck;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
/**
......@@ -65,6 +66,12 @@ public function providerTestAccess() {
array('', 'entity_test',TRUE, AccessCheckInterface::ALLOW),
array('test_entity', 'entity_test:test_entity', TRUE, AccessCheckInterface::ALLOW),
array('test_entity', 'entity_test:test_entity', FALSE, AccessCheckInterface::DENY),
array('test_entity', 'entity_test:{bundle_argument}', TRUE, AccessCheckInterface::ALLOW),
array('test_entity', 'entity_test:{bundle_argument}', FALSE, AccessCheckInterface::DENY),
array('', 'entity_test:{bundle_argument}', FALSE, AccessCheckInterface::DENY),
// When the bundle is not provided, access should be denied even if the
// access controller would allow access.
array('', 'entity_test:{bundle_argument}', TRUE, AccessCheckInterface::DENY),
);
}
......@@ -74,23 +81,23 @@ public function providerTestAccess() {
* @dataProvider providerTestAccess
*/
public function testAccess($entity_bundle, $requirement, $access, $expected) {
$entity = $this->getMockBuilder('Drupal\Core\Entity\Entity')
->disableOriginalConstructor()
->getMock();
$entity_manager = $this->getMockBuilder('Drupal\Core\Entity\EntityManager')
->disableOriginalConstructor()
->getMock();
$access_controller = $this->getMock('Drupal\Core\Entity\EntityAccessControllerInterface');
$access_controller->expects($this->once())
->method('createAccess')
->with($entity_bundle)
->will($this->returnValue($access));
// Don't expect a call to the access controller when we have a bundle
// argument requirement but no bundle is provided.
if ($entity_bundle || strpos($requirement, '{') === FALSE) {
$access_controller = $this->getMock('Drupal\Core\Entity\EntityAccessControllerInterface');
$access_controller->expects($this->once())
->method('createAccess')
->with($entity_bundle)
->will($this->returnValue($access));
$entity_manager->expects($this->any())
->method('getAccessController')
->will($this->returnValue($access_controller));
$entity_manager->expects($this->any())
->method('getAccessController')
->will($this->returnValue($access_controller));
}
$applies_check = new EntityCreateAccessCheck($entity_manager);
......@@ -103,6 +110,13 @@ public function testAccess($entity_bundle, $requirement, $access, $expected) {
->will($this->returnValue($requirement));
$request = new Request();
$raw_variables = new ParameterBag();
if ($entity_bundle) {
// Add the bundle as a raw variable and an upcasted attribute.
$request->attributes->set('bundle_argument', new \stdClass());
$raw_variables->set('bundle_argument', $entity_bundle);
}
$request->attributes->set('_raw_variables', $raw_variables);
$this->assertEquals($expected, $applies_check->access($route, $request));
}
......
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