jsonapi.services.yml | 3 - src/Annotation/JsonApiResource.php | 54 -------------- src/Plugin/Deriver/ResourceDeriver.php | 79 -------------------- src/Plugin/JsonApiResourceInterface.php | 14 ---- src/Plugin/JsonApiResourceManager.php | 43 ----------- src/Plugin/jsonapi/BundleJsonApiResource.php | 24 ------- src/Routing/Routes.php | 83 ++++++++++------------ .../Unit/Plugin/Deriver/ResourceDeriverTest.php | 72 ------------------- tests/src/Unit/Routing/RoutesTest.php | 48 +++++-------- 9 files changed, 55 insertions(+), 365 deletions(-) diff --git a/jsonapi.services.yml b/jsonapi.services.yml index 7225840..9f478ab 100644 --- a/jsonapi.services.yml +++ b/jsonapi.services.yml @@ -91,9 +91,6 @@ services: arguments: ['@entity.manager'] jsonapi.error_handler: class: Drupal\jsonapi\Error\ErrorHandler - plugin.manager.resource.processor: - class: Drupal\jsonapi\Plugin\JsonApiResourceManager - parent: default_plugin_manager jsonapi.exception_subscriber: class: Drupal\jsonapi\EventSubscriber\DefaultExceptionSubscriber tags: diff --git a/src/Annotation/JsonApiResource.php b/src/Annotation/JsonApiResource.php deleted file mode 100644 index 3c69525..0000000 --- a/src/Annotation/JsonApiResource.php +++ /dev/null @@ -1,54 +0,0 @@ -resourceManager = $resource_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, $base_plugin_id) { - /* @var \Drupal\jsonapi\Configuration\ResourceManagerInterface $resource_manager */ - $resource_manager = $container->get('jsonapi.resource.manager'); - return new static($resource_manager); - } - - /** - * {@inheritdoc} - */ - public function getDerivativeDefinitions($base_definition) { - if (isset($this->derivatives)) { - return $this->derivatives; - } - $this->derivatives = []; - // Add in the default plugin configuration and the resource type. - /* @var \Drupal\jsonapi\Configuration\ResourceConfigInterface[] $resource_configs */ - $resource_configs = $this->resourceManager->all(); - foreach ($resource_configs as $resource) { - $id = sprintf('jsonapi.%s', $resource->getTypeName()); - $this->derivatives[$id] = [ - 'id' => $id, - 'entityType' => $resource->getEntityTypeId(), - 'bundle' => $resource->getBundleId(), - 'hasBundle' => $this->resourceManager->hasBundle($resource->getEntityTypeId()), - 'type' => $resource->getTypeName(), - 'data' => [ - 'partialPath' => $resource->getPath() - ] - ]; - - $this->derivatives[$id] += $base_definition; - } - return $this->derivatives; - } - -} diff --git a/src/Plugin/JsonApiResourceInterface.php b/src/Plugin/JsonApiResourceInterface.php deleted file mode 100644 index 560b703..0000000 --- a/src/Plugin/JsonApiResourceInterface.php +++ /dev/null @@ -1,14 +0,0 @@ - 'access content', - 'controller' => Routes::FRONT_CONTROLLER, - ]; - - /** - * Constructor for JsonApiResourceManager objects. - * - * @param \Traversable $namespaces - * An object that implements \Traversable which contains the root paths - * keyed by the corresponding namespace to look for plugin implementations. - * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend - * Cache backend instance to use. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler to invoke the alter hook with. - */ - public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/jsonapi', $namespaces, $module_handler, 'Drupal\jsonapi\Plugin\JsonApiResourceInterface', 'Drupal\jsonapi\Annotation\JsonApiResource'); - - $this->alterInfo('jsonapi_resource_info'); - $this->setCacheBackend($cache_backend, 'jsonapi_resource_plugins'); - } - -} diff --git a/src/Plugin/jsonapi/BundleJsonApiResource.php b/src/Plugin/jsonapi/BundleJsonApiResource.php deleted file mode 100644 index bf97da3..0000000 --- a/src/Plugin/jsonapi/BundleJsonApiResource.php +++ /dev/null @@ -1,24 +0,0 @@ -resourcePluginManager = $resource_plugin_manager; + public function __construct(ResourceManagerInterface $resource_manager, AuthenticationCollectorInterface $auth_collector) { + $this->resourceManager = $resource_manager; $this->authCollector = $auth_collector; } @@ -66,12 +66,12 @@ class Routes implements ContainerInjectionInterface { * {@inheritdoc} */ public static function create(ContainerInterface $container) { - /* @var \Drupal\jsonapi\Plugin\JsonApiResourceManager $resource_plugin_manager */ - $resource_plugin_manager = $container->get('plugin.manager.resource.processor'); + /* @var \Drupal\jsonapi\Configuration\ResourceManagerInterface $resource_manager */ + $resource_manager = $container->get('jsonapi.resource.manager'); /* @var \Drupal\Core\Authentication\AuthenticationCollectorInterface $auth_collector */ $auth_collector = $container->get('authentication_collector'); - return new static($resource_plugin_manager, $auth_collector); + return new static($resource_manager, $auth_collector); } /** @@ -79,16 +79,13 @@ class Routes implements ContainerInjectionInterface { */ public function routes() { $collection = new RouteCollection(); - foreach ($this->resourcePluginManager->getDefinitions() as $plugin_id => $plugin_definition) { - $entity_type = $plugin_definition['entityType']; - // For the entity type resources the bundle is NULL. - $bundle = $plugin_definition['bundle']; - $partial_path = $plugin_definition['data']['partialPath']; - $route_keys = explode(':', $plugin_id); - $route_key = end($route_keys) . '.'; - // Add the collection route. + foreach ($this->resourceManager->all() as $resource_config) { + $build_route_name = function ($key) use ($resource_config) { + return sprintf('jsonapi.%s.%s', $resource_config->getTypeName(), $key); + }; + $defaults = [ - RouteObjectInterface::CONTROLLER_NAME => $plugin_definition['controller'], + RouteObjectInterface::CONTROLLER_NAME => static::FRONT_CONTROLLER, ]; // Options that apply to all routes. $options = [ @@ -97,70 +94,62 @@ class Routes implements ContainerInjectionInterface { ]; // Collection endpoint, like /jsonapi/file/photo. - $route_collection = (new Route('/jsonapi' . $partial_path)) + $route_collection = (new Route('/jsonapi' . $resource_config->getPath())) ->addDefaults($defaults) - ->setRequirement('_entity_type', $entity_type) - ->setRequirement('_permission', $plugin_definition['permission']) + ->setRequirement('_entity_type', $resource_config->getEntityTypeId()) + ->setRequirement('_bundle', $resource_config->getBundleId()) + ->setRequirement('_permission', 'access content') ->setRequirement('_format', 'api_json') ->setRequirement('_custom_parameter_names', 'TRUE') ->setOption('serialization_class', JsonApiDocumentTopLevel::class) ->setMethods(['GET', 'POST']); - if ($bundle) { - $route_collection->setRequirement('_bundle', $bundle); - } $route_collection->addOptions($options); - $collection->add($route_key . 'collection', $route_collection); + $collection->add($build_route_name('collection'), $route_collection); // Individual endpoint, like /jsonapi/file/photo/123. - $parameters = [$entity_type => ['type' => 'entity:' . $entity_type]]; - $route_individual = (new Route('/jsonapi' . sprintf('%s/{%s}', $partial_path, $entity_type))) + $parameters = [$resource_config->getEntityTypeId() => ['type' => 'entity:' . $resource_config->getEntityTypeId()]]; + $route_individual = (new Route('/jsonapi' . sprintf('%s/{%s}', $resource_config->getPath(), $resource_config->getEntityTypeId()))) ->addDefaults($defaults) - ->setRequirement('_entity_type', $entity_type) - ->setRequirement('_permission', $plugin_definition['permission']) + ->setRequirement('_entity_type', $resource_config->getEntityTypeId()) + ->setRequirement('_bundle', $resource_config->getBundleId()) + ->setRequirement('_permission', 'access content') ->setRequirement('_format', 'api_json') ->setRequirement('_custom_parameter_names', 'TRUE') ->setOption('parameters', $parameters) ->setOption('_auth', $this->authProviderList()) ->setOption('serialization_class', JsonApiDocumentTopLevel::class) ->setMethods(['GET', 'PATCH', 'DELETE']); - if ($bundle) { - $route_individual->setRequirement('_bundle', $bundle); - } $route_individual->addOptions($options); - $collection->add($route_key . 'individual', $route_individual); + $collection->add($build_route_name('individual'), $route_individual); // Related resource, like /jsonapi/file/photo/123/comments. - $route_related = (new Route('/jsonapi' . sprintf('%s/{%s}/{related}', $partial_path, $entity_type))) + $route_related = (new Route('/jsonapi' . sprintf('%s/{%s}/{related}', $resource_config->getPath(), $resource_config->getEntityTypeId()))) ->addDefaults($defaults) - ->setRequirement('_entity_type', $entity_type) - ->setRequirement('_permission', $plugin_definition['permission']) + ->setRequirement('_entity_type', $resource_config->getEntityTypeId()) + ->setRequirement('_bundle', $resource_config->getBundleId()) + ->setRequirement('_permission', 'access content') ->setRequirement('_format', 'api_json') ->setRequirement('_custom_parameter_names', 'TRUE') ->setOption('parameters', $parameters) ->setOption('_auth', $this->authProviderList()) ->setMethods(['GET']); - if ($bundle) { - $route_related->setRequirement('_bundle', $bundle); - } $route_related->addOptions($options); - $collection->add($route_key . 'related', $route_related); + $collection->add($build_route_name('related'), $route_related); // Related endpoint, like /jsonapi/file/photo/123/relationships/comments. - $route_relationship = (new Route('/jsonapi' . sprintf('%s/{%s}/relationships/{related}', $partial_path, $entity_type))) + $route_relationship = (new Route('/jsonapi' . sprintf('%s/{%s}/relationships/{related}', $resource_config->getPath(), $resource_config->getEntityTypeId()))) ->addDefaults($defaults + ['_on_relationship' => TRUE]) - ->setRequirement('_entity_type', $entity_type) - ->setRequirement('_permission', $plugin_definition['permission']) + ->setRequirement('_entity_type', $resource_config->getEntityTypeId()) + ->setRequirement('_bundle', $resource_config->getBundleId()) + ->setRequirement('_permission', 'access content') ->setRequirement('_format', 'api_json') ->setRequirement('_custom_parameter_names', 'TRUE') ->setOption('parameters', $parameters) ->setOption('_auth', $this->authProviderList()) ->setOption('serialization_class', EntityReferenceFieldItemList::class) ->setMethods(['GET', 'POST', 'PATCH', 'DELETE']); - if ($bundle) { - $route_relationship->setRequirement('_bundle', $bundle); - } $route_relationship->addOptions($options); - $collection->add($route_key . 'relationship', $route_relationship); + $collection->add($build_route_name('relationship'), $route_relationship); } return $collection; diff --git a/tests/src/Unit/Plugin/Deriver/ResourceDeriverTest.php b/tests/src/Unit/Plugin/Deriver/ResourceDeriverTest.php deleted file mode 100644 index d52530b..0000000 --- a/tests/src/Unit/Plugin/Deriver/ResourceDeriverTest.php +++ /dev/null @@ -1,72 +0,0 @@ -prophesize(ResourceManagerInterface::class); - - // Create some resource mocks for the manager. - $resource_manager->all()->willReturn([new ResourceConfig('entity_type_1', 'bundle_1_1', EntityInterface::class)]); - $resource_manager->hasBundle(Argument::type('string'))->willReturn(FALSE); - - $container = $this->prophesize(ContainerInterface::class); - $container->get('jsonapi.resource.manager')->willReturn($resource_manager->reveal()); - $this->deriver = ResourceDeriver::create($container->reveal(), 'bundle'); - } - - - /** - * @covers ::getDerivativeDefinitions - */ - public function testGetDerivativeDefinitions() { - $expected = ['jsonapi.entity_type_1--bundle_1_1' => [ - 'id' => 'jsonapi.entity_type_1--bundle_1_1', - 'entityType' => 'entity_type_1', - 'bundle' => 'bundle_1_1', - 'hasBundle' => FALSE, - 'type' => 'entity_type_1--bundle_1_1', - 'data' => [ - 'partialPath' => '/entity_type_1/bundle_1_1', - ], - 'permission' => 'access content', - 'controller' => '\\Drupal\\jsonapi\\RequestHandler::handle', - ]]; - $actual = $this->deriver->getDerivativeDefinitions([ - 'permission' => 'access content', - 'controller' => '\Drupal\jsonapi\RequestHandler::handle', - ]); - $this->assertArrayEquals($expected, $actual); - } - -} diff --git a/tests/src/Unit/Routing/RoutesTest.php b/tests/src/Unit/Routing/RoutesTest.php index 3327c69..0d0b1cb 100644 --- a/tests/src/Unit/Routing/RoutesTest.php +++ b/tests/src/Unit/Routing/RoutesTest.php @@ -3,7 +3,9 @@ namespace Drupal\Tests\jsonapi\Unit\Routing; use Drupal\Core\Authentication\AuthenticationCollectorInterface; -use Drupal\jsonapi\Plugin\JsonApiResourceManager; +use Drupal\Core\Entity\EntityInterface; +use Drupal\jsonapi\Configuration\ResourceConfig; +use Drupal\jsonapi\Configuration\ResourceManagerInterface; use Drupal\jsonapi\Routing\Routes; use Drupal\Tests\UnitTestCase; use Symfony\Cmf\Component\Routing\RouteObjectInterface; @@ -33,23 +35,11 @@ class RoutesTest extends UnitTestCase { protected function setUp() { parent::setUp(); // Mock the resource manager to have some resources available. - $resource_plugin_manager = $this->prophesize(JsonApiResourceManager::class); - $resource_plugin_manager->getDefinitions()->willReturn([ - 'bundle:jsonapi.resource_type_1' => [ - 'id' => 'bundle:jsonapi.resource_type_1', - 'entityType' => 'entity_type_1', - 'bundle' => 'bundle_1_1', - 'hasBundle' => TRUE, - 'type' => 'resource_type_1', - 'data' => [ - 'partialPath' => '/entity_type_1/bundle_path_1', - ], - 'controller' => 'MyCustomController', - 'permission' => 'access content', - ], - ]); + $resource_manager = $this->prophesize(ResourceManagerInterface::class); + $resource_manager->hasBundle('entity_type_1')->willReturn(TRUE); + $resource_manager->all()->willReturn([new ResourceConfig('entity_type_1', 'bundle_1_1', EntityInterface::class)]); $container = $this->prophesize(ContainerInterface::class); - $container->get('plugin.manager.resource.processor')->willReturn($resource_plugin_manager->reveal()); + $container->get('jsonapi.resource.manager')->willReturn($resource_manager->reveal()); $auth_collector = $this->prophesize(AuthenticationCollectorInterface::class); $auth_collector->getSortedProviders()->willReturn([ 'lorem' => [], @@ -74,13 +64,13 @@ class RoutesTest extends UnitTestCase { $iterator = $routes->getIterator(); // Check the collection route. /** @var \Symfony\Component\Routing\Route $route */ - $route = $iterator->offsetGet('jsonapi.resource_type_1.collection'); - $this->assertSame('/jsonapi/entity_type_1/bundle_path_1', $route->getPath()); + $route = $iterator->offsetGet('jsonapi.entity_type_1--bundle_1_1.collection'); + $this->assertSame('/jsonapi/entity_type_1/bundle_1_1', $route->getPath()); $this->assertSame('entity_type_1', $route->getRequirement('_entity_type')); $this->assertSame('bundle_1_1', $route->getRequirement('_bundle')); $this->assertSame(['lorem', 'ipsum'], $route->getOption('_auth')); $this->assertEquals(['GET', 'POST'], $route->getMethods()); - $this->assertSame('MyCustomController', $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)); + $this->assertSame(Routes::FRONT_CONTROLLER, $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)); $this->assertSame('Drupal\jsonapi\Resource\JsonApiDocumentTopLevel', $route->getOption('serialization_class')); } @@ -93,12 +83,12 @@ class RoutesTest extends UnitTestCase { // Check the individual route. /** @var \Symfony\Component\Routing\Route $route */ - $route = $iterator->offsetGet('jsonapi.resource_type_1.individual'); - $this->assertSame('/jsonapi/entity_type_1/bundle_path_1/{entity_type_1}', $route->getPath()); + $route = $iterator->offsetGet('jsonapi.entity_type_1--bundle_1_1.individual'); + $this->assertSame('/jsonapi/entity_type_1/bundle_1_1/{entity_type_1}', $route->getPath()); $this->assertSame('entity_type_1', $route->getRequirement('_entity_type')); $this->assertSame('bundle_1_1', $route->getRequirement('_bundle')); $this->assertEquals(['GET', 'PATCH', 'DELETE'], $route->getMethods()); - $this->assertSame('MyCustomController', $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)); + $this->assertSame(Routes::FRONT_CONTROLLER, $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)); $this->assertSame('Drupal\jsonapi\Resource\JsonApiDocumentTopLevel', $route->getOption('serialization_class')); $this->assertSame(['lorem', 'ipsum'], $route->getOption('_auth')); $this->assertEquals(['entity_type_1' => ['type' => 'entity:entity_type_1']], $route->getOption('parameters')); @@ -113,12 +103,12 @@ class RoutesTest extends UnitTestCase { // Check the related route. /** @var \Symfony\Component\Routing\Route $route */ - $route = $iterator->offsetGet('jsonapi.resource_type_1.related'); - $this->assertSame('/jsonapi/entity_type_1/bundle_path_1/{entity_type_1}/{related}', $route->getPath()); + $route = $iterator->offsetGet('jsonapi.entity_type_1--bundle_1_1.related'); + $this->assertSame('/jsonapi/entity_type_1/bundle_1_1/{entity_type_1}/{related}', $route->getPath()); $this->assertSame('entity_type_1', $route->getRequirement('_entity_type')); $this->assertSame('bundle_1_1', $route->getRequirement('_bundle')); $this->assertEquals(['GET'], $route->getMethods()); - $this->assertSame('MyCustomController', $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)); + $this->assertSame(Routes::FRONT_CONTROLLER, $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)); $this->assertSame(['lorem', 'ipsum'], $route->getOption('_auth')); $this->assertEquals(['entity_type_1' => ['type' => 'entity:entity_type_1']], $route->getOption('parameters')); } @@ -132,12 +122,12 @@ class RoutesTest extends UnitTestCase { // Check the relationships route. /** @var \Symfony\Component\Routing\Route $route */ - $route = $iterator->offsetGet('jsonapi.resource_type_1.relationship'); - $this->assertSame('/jsonapi/entity_type_1/bundle_path_1/{entity_type_1}/relationships/{related}', $route->getPath()); + $route = $iterator->offsetGet('jsonapi.entity_type_1--bundle_1_1.relationship'); + $this->assertSame('/jsonapi/entity_type_1/bundle_1_1/{entity_type_1}/relationships/{related}', $route->getPath()); $this->assertSame('entity_type_1', $route->getRequirement('_entity_type')); $this->assertSame('bundle_1_1', $route->getRequirement('_bundle')); $this->assertEquals(['GET', 'POST', 'PATCH', 'DELETE'], $route->getMethods()); - $this->assertSame('MyCustomController', $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)); + $this->assertSame(Routes::FRONT_CONTROLLER, $route->getDefault(RouteObjectInterface::CONTROLLER_NAME)); $this->assertSame(['lorem', 'ipsum'], $route->getOption('_auth')); $this->assertEquals(['entity_type_1' => ['type' => 'entity:entity_type_1']], $route->getOption('parameters')); $this->assertSame('Drupal\Core\Field\EntityReferenceFieldItemList', $route->getOption('serialization_class'));