diff --git a/src/Entity/JsonapiResourceConfig.php b/src/Entity/JsonapiResourceConfig.php index 35fea3decf17ba86f25188faf05bc96a17f26782..54b829e7eecb3ab49cf0278ec61beab76135987a 100644 --- a/src/Entity/JsonapiResourceConfig.php +++ b/src/Entity/JsonapiResourceConfig.php @@ -24,6 +24,7 @@ use Drupal\Core\Entity\EntityStorageInterface; * }, * config_prefix = "jsonapi_resource_config", * admin_permission = "administer site configuration", + * static_cache = TRUE, * entity_keys = { * "id" = "id", * "label" = "label", diff --git a/src/Form/JsonapiResourceConfigForm.php b/src/Form/JsonapiResourceConfigForm.php index 9372d4e0989a4f01b80f951ff71aa65ae2559746..591026bf0f58e70c5ccdbc1fd87e29337bea6911 100644 --- a/src/Form/JsonapiResourceConfigForm.php +++ b/src/Form/JsonapiResourceConfigForm.php @@ -165,50 +165,15 @@ class JsonapiResourceConfigForm extends EntityForm { * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { - $form_values = $form_state->getValues(); - $resourceFields = $form_values['resourceFields']; - $overrides = []; - - // Get the field values - foreach ($resourceFields as $field => $data) { - // Only get the overridden fields. - if ($data['fieldName'] != $data['publicName']) { - // Store the publicName for comparison. - $overrides[$field] = $data['publicName']; - } - } - - // Compare the overrides and find any duplicate values. - $deduped_overrides = array_unique($overrides); - $dupes = array_diff_assoc($overrides, $deduped_overrides); - // Set an error if there are duplicates. - if ($dupes) { - foreach ($dupes as $field => $value) { - $form_state->setErrorbyName('resourceFields][' . $field . '][publicName', $this->t('The override must be unique.')); - } - } - // Now compare the overrides with the default names to validate no dupes exist. - foreach ($overrides as $field => $override) { - if (array_key_exists($override, $resourceFields)) { - $form_state->setErrorByName('resourceFields][' . $field . '][publicName', $this->t('The override must be unique.')); - } - } - - // Validate URL and resource type - $resource_types = $this->entityTypeManager - ->getStorage('jsonapi_resource_config') - ->loadByProperties(['disabled' => FALSE]); - foreach ($resource_types as $id => $resource_type) { - if ($this->entity->id() == $id) { - continue; - } - - if ($resource_type->get('resourceType') == $form_values['resourceType']) { - $form_state->setErrorByName('resourceType', $this->t('There is already resource (:name) with this override.', [':name' => $resource_type->id()])); - } - if ($resource_type->get('path') == $form_values['path']) { - $form_state->setErrorByName('path', $this->t('There is already resource (:name) with this path.', [':name' => $resource_type->id()])); - } + /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */ + $typed_config_manager = \Drupal::service('config.typed'); + $typed_config = $typed_config_manager->createFromNameAndData($this->entity->id(), $this->entity->toArray()); + $constraints = $typed_config->validate(); + + /** @var \Symfony\Component\Validator\ConstraintViolation $violation */ + foreach ($constraints as $violation) { + $form_path = str_replace('.', '][', $violation->getPropertyPath()); + $form_state->setErrorByName($form_path, $violation->getMessage()); } } diff --git a/src/Plugin/Validation/Constraint/DuplicateFieldConstraint.php b/src/Plugin/Validation/Constraint/DuplicateFieldConstraint.php new file mode 100644 index 0000000000000000000000000000000000000000..cb1cd9bbba43b1b93c6369fb6e1d477c7efdeed8 --- /dev/null +++ b/src/Plugin/Validation/Constraint/DuplicateFieldConstraint.php @@ -0,0 +1,17 @@ +entityTypeManager = $entityTypeManager ?: \Drupal::entityTypeManager(); + } + + /** + * {@inheritdoc} + */ + public function validate($entity_data, Constraint $constraint) { + $resourceFields = $entity_data['resourceFields']; + $overrides = []; + + // Get the field values + foreach ($resourceFields as $field => $data) { + // Only get the overridden fields. + if ($data['fieldName'] != $data['publicName']) { + // Store the publicName for comparison. + $overrides[$field] = $data['publicName']; + } + } + + // Compare the overrides and find any duplicate values. + $deduped_overrides = array_unique($overrides); + $dupes = array_diff_assoc($overrides, $deduped_overrides); + // Set an error if there are duplicates. + if ($dupes) { + foreach ($dupes as $field => $value) { + $this->context->buildViolation($constraint->message) + ->atPath("resourceFields.$field.publicName") + ->addViolation(); + } + } + // Now compare the overrides with the default names to validate no dupes exist. + foreach ($overrides as $field => $override) { + if (array_key_exists($override, $resourceFields)) { + $this->context->buildViolation($constraint->message) + ->atPath("resourceFields.$field.publicName") + ->addViolation(); + } + } + + // Validate URL and resource type + $resource_types = $this->entityTypeManager + ->getStorage('jsonapi_resource_config') + ->loadByProperties(['disabled' => FALSE]); + foreach ($resource_types as $id => $resource_type) { + if ($entity_data['id'] == $id) { + continue; + } + + if ($resource_type->get('resourceType') == $entity_data['resourceType']) { + $this->context->buildViolation('There is already resource (@name) with this resource type.', ['@name' => $resource_type->id()]) + ->atPath('resourceType') + ->addViolation(); + } + if ($resource_type->get('path') == $entity_data['path']) { + $this->context->buildViolation('There is already resource (@name) with this path.', ['@name' => $resource_type->id()]) + ->atPath('resourceType') + ->addViolation(); + } + } + } + +} diff --git a/src/ResourceType/ConfigurableResourceTypeRepository.php b/src/ResourceType/ConfigurableResourceTypeRepository.php index a014942d512366b14a279bbbe5a6649342c8e96d..d8ac0472127e2ad9f9ad9146a312c14e2587a23a 100644 --- a/src/ResourceType/ConfigurableResourceTypeRepository.php +++ b/src/ResourceType/ConfigurableResourceTypeRepository.php @@ -34,6 +34,11 @@ class ConfigurableResourceTypeRepository extends ResourceTypeRepository { */ protected $configFactory; + /** + * @var \Drupal\jsonapi_extras\ResourceType\ConfigurableResourceType[] + */ + protected $resourceTypes; + /** * {@inheritdoc} */ @@ -81,18 +86,29 @@ class ConfigurableResourceTypeRepository extends ResourceTypeRepository { * An array of resource types. */ public function getResourceTypes($include_disabled = TRUE) { + if (isset($this->resourceTypes)) { + return $this->resourceTypes; + } + $entity_type_ids = array_keys($this->entityTypeManager->getDefinitions()); $resource_types = []; + + $resource_config_ids = []; foreach ($entity_type_ids as $entity_type_id) { $bundles = array_keys($this->bundleManager->getBundleInfo($entity_type_id)); - $current_types = array_map(function ($bundle) use ($entity_type_id, $include_disabled) { + $resource_config_ids = array_merge($resource_config_ids, array_map(function ($bundle) use ($entity_type_id) { + $resource_config_ids[] = sprintf('%s--%s', $entity_type_id, $bundle); + }, $bundles)); + } + + $resource_configs = $this->entityTypeManager->getStorage('jsonapi_resource_config')->loadMultiple($resource_config_ids); + + foreach ($entity_type_ids as $entity_type_id) { + $bundles = array_keys($this->bundleManager->getBundleInfo($entity_type_id)); + $current_types = array_map(function ($bundle) use ($entity_type_id, $include_disabled, $resource_configs) { $resource_config_id = sprintf('%s--%s', $entity_type_id, $bundle); - $resource_config = $this->entityRepository->loadEntityByConfigTarget( - 'jsonapi_resource_config', - $resource_config_id - ); - $resource_config = $resource_config ?: new NullJsonapiResourceConfig([], ''); + $resource_config = isset($resource_configs[$resource_config_id]) ? $resource_configs[$resource_config_id] : new NullJsonapiResourceConfig([], ''); if (!$include_disabled && $resource_config->get('disabled')) { return NULL; } @@ -108,7 +124,8 @@ class ConfigurableResourceTypeRepository extends ResourceTypeRepository { $resource_types = array_merge($resource_types, $current_types); } - return array_filter($resource_types); + $this->resourceTypes = array_filter($resource_types); + return $this->resourceTypes; } }