Skip to content

Commit

Permalink
Merge pull request #11 from discoverygarden/feature/early-exit
Browse files Browse the repository at this point in the history
PER-42: Spec used fields explicitly.
  • Loading branch information
nchiasson-dgi authored Mar 7, 2024
2 parents 89581ea + 34d6b97 commit b6c001f
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 0 deletions.
6 changes: 6 additions & 0 deletions iiif_presentation_api.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ services:
arguments:
- '@current_user'
- '@event_dispatcher'
- '@iiif_presentation_api.v3.field_mapper'
serializer.normalizer.iiif_presentation_api.iiif_p_v3.field_item_list:
class: 'Drupal\iiif_presentation_api\Normalizer\V3\FieldItemListNormalizer'
tags:
Expand Down Expand Up @@ -48,3 +49,8 @@ services:
factory: [null, create]
arguments:
- '@service_container'

iiif_presentation_api.v3.field_mapper:
class: Drupal\iiif_presentation_api\FieldMapper
tags:
- { name: iiif_presentation_api_mapper, base: iiif_presentation_api_map, version: v3 }
53 changes: 53 additions & 0 deletions src/FieldMapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Drupal\iiif_presentation_api;

use Drupal\Core\DependencyInjection\DependencySerializationTrait;

/**
* Help passing around some service metadata.
*/
class FieldMapper implements FieldMapperInterface {

use DependencySerializationTrait;

/**
* The mapped fields for which the mapping is being built.
*
* @var \Drupal\iiif_presentation_api\MappedFieldInterface[]
*/
protected array $mappers = [];

/**
* Memoized mapping, mapping entity type IDs to arrays of field names.
*
* @var string[][]
*/
protected array $mapping = [];

/**
* {@inheritDoc}
*/
public function addMapper(MappedFieldInterface $mapping) : FieldMapperInterface {
$this->mappers[] = $mapping;
if (!$this->isInMapping($mapping->getTargetEntityTypeId(), $mapping->getTargetFieldName())) {
$this->mapping[$mapping->getTargetEntityTypeId()][] = $mapping->getTargetFieldName();
}
return $this;
}

/**
* {@inheritDoc}
*/
public function getMapping() : array {
return $this->mapping;
}

/**
* {@inheritDoc}
*/
public function isInMapping(string $entity_type_id, string $field_name) : bool {
return !empty($this->mapping[$entity_type_id]) && in_array($field_name, $this->mapping[$entity_type_id]);
}

}
42 changes: 42 additions & 0 deletions src/FieldMapperInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Drupal\iiif_presentation_api;

/**
* Generic service interface in which to build out a mapping.
*/
interface FieldMapperInterface {

/**
* Add a type/field pair to the mapping.
*
* @param \Drupal\iiif_presentation_api\MappedFieldInterface $mapping
* The item containing the type/field pair.
*
* @return self
* Fluent interface.
*/
public function addMapper(MappedFieldInterface $mapping) : self;

/**
* Get the mapping of types to field names.
*
* @return string[][]
* An associative array mapping entity type IDs to arrays of field names.
*/
public function getMapping() : array;

/**
* Test if the given item is present.
*
* @param string $entity_type_id
* The entity type for which to test.
* @param string $field_name
* The field name for which to test.
*
* @return bool
* TRUE if present; otherwise, FALSE.
*/
public function isInMapping(string $entity_type_id, string $field_name) : bool;

}
10 changes: 10 additions & 0 deletions src/IiifPresentationApiServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
use Symfony\Component\DependencyInjection\Reference;

/**
* Adds the iiif-p-v3 format to be available to be requested.
Expand All @@ -20,6 +21,15 @@ public function alter(ContainerBuilder $container) {
['application/json'],
]);
}

foreach ($container->findTaggedServiceIds('iiif_presentation_api_mapper') as $mapper_service_id => $mapper_attributes) {
$map_service = $container->getDefinition($mapper_service_id);
foreach ($mapper_attributes as $mapper_attributes_actual) {
foreach ($container->findTaggedServiceIds("{$mapper_attributes_actual['base']}.{$mapper_attributes_actual['version']}") as $map_service_id => $map_attributes) {
$map_service = $map_service->addMethodCall('addMapper', [new Reference($map_service_id)]);
}
}
}
}

}
26 changes: 26 additions & 0 deletions src/MappedFieldInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Drupal\iiif_presentation_api;

/**
* Field specific normalizer interface.
*/
interface MappedFieldInterface {

/**
* Get the target entity type.
*
* @return string
* The target entity type.
*/
public function getTargetEntityTypeId() : string;

/**
* Get the target field name.
*
* @return string
* The target field name.
*/
public function getTargetFieldName() : string;

}
5 changes: 5 additions & 0 deletions src/Normalizer/V3/ContentEntityNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\iiif_presentation_api\Event\V3\ContentEntityExtrasEvent;
use Drupal\iiif_presentation_api\FieldMapperInterface;
use Drupal\iiif_presentation_api\Normalizer\EntityUriTrait;
use Drupal\node\NodeInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
Expand All @@ -29,6 +30,7 @@ class ContentEntityNormalizer extends NormalizerBase {
public function __construct(
protected AccountInterface $user,
protected EventDispatcherInterface $eventDispatcher,
protected FieldMapperInterface $fieldMapper,
) {

}
Expand Down Expand Up @@ -126,6 +128,9 @@ public function normalize($object, $format = NULL, array $context = []) {
protected function normalizeEntityFields(ContentEntityInterface $object, string $format, array $context, array $normalized): array {
$this->addCacheableDependency($context, $object);
foreach ($object->getFields() as $field) {
if (!$this->fieldMapper->isInMapping($object->getEntityTypeId(), $field->getName())) {
continue;
}
$access = $field->access('view', $context['account'], TRUE);
$this->addCacheableDependency($context, $access);
if (!$access->isAllowed()) {
Expand Down

0 comments on commit b6c001f

Please sign in to comment.