Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Commit

Permalink
[SDPAP-7155] webform validation
Browse files Browse the repository at this point in the history
  • Loading branch information
vincent-gao committed Apr 3, 2023
1 parent 9723b3e commit 3a21e60
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 0 deletions.
223 changes: 223 additions & 0 deletions modules/tide_webform_jsonapi/src/Resource/AddWebform.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
<?php

namespace Drupal\tide_webform_jsonapi\Resource;

use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\jsonapi\JsonApiResource\ErrorCollection;
use Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel;
use Drupal\jsonapi\JsonApiResource\LinkCollection;
use Drupal\jsonapi\JsonApiResource\NullIncludedData;
use Drupal\jsonapi\JsonApiResource\ResourceObject;
use Drupal\jsonapi\JsonApiResource\ResourceObjectData;
use Drupal\jsonapi\ResourceResponse;
use Drupal\jsonapi_resources\Resource\EntityQueryResourceBase;
use Drupal\webform\Entity\Webform;
use Drupal\webform\WebformSubmissionForm;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Routing\Route;

/**
* Processes a request to create a comment on an article.
*
* @package Drupal\jsonapi_resources_test\Resource
*/
final class AddWebform extends EntityQueryResourceBase implements ContainerInjectionInterface {

/**
* The current user account.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;

/**
* Constructs a resource for adding a comment.
*
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user account.
*/
public function __construct(AccountInterface $current_user) {
$this->currentUser = $current_user;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('current_user')
);
}

/**
* Process the resource request.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request.
* @param \Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel $document
* The deserialized request document.
*
* @return \Drupal\jsonapi\ResourceResponse
* The response.
*
* @throws \Symfony\Component\HttpKernel\Exception\ConflictHttpException
* Thrown when the entity to be created already exists.
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* Thrown if the storage handler couldn't be loaded.
* @throws \Drupal\Core\Entity\EntityStorageException
* Thrown if the entity could not be saved.
*/
public function process(Request $request, Webform $webform): ResourceResponse {
/** @var \Drupal\jsonapi\ResourceType\ResourceTypeRepository $resource_type_repo */
$resource_type_repo = \Drupal::service('jsonapi.resource_type.repository');
$resource_type = $resource_type_repo->get(
'webform_submission',
'tide_webform_content_rating'
);
/** @var \Drupal\jsonapi\Controller\EntityResource $entity_resource_controller */
$entity_resource_controller = \Drupal::service('jsonapi.entity_resource');
$reflectedMethod = new \ReflectionMethod(
$entity_resource_controller,
'deserialize'
);
$reflectedMethod->setAccessible(TRUE);
/** @var \Drupal\webform\Entity\WebformSubmission $entity */
$entity = $reflectedMethod->invoke(
$entity_resource_controller,
$resource_type,
$request,
JsonApiDocumentTopLevel::class
);

static::validate($entity);
$entity->save();

// $data = $this->createIndividualDataFromEntity($entity);
// $resource_object = $data->getIterator()->current();
// assert($resource_object instanceof ResourceObject);
// $response = $this->createJsonapiResponse($data, $request, 201);

// $webform = \Drupal\webform\Entity\Webform::load('tide_webform_content_rating');
$original_elements = $webform->getElementsDecodedAndFlattened();
$supported_validations = $this->getSupportedValidateElements();
$results = $this->webformValidateSettingsExtractor($supported_validations,$original_elements);
$new_array = [];
foreach ($results as $key => $r){
$new_array[$key] = $this->attachValidateSettingsToPayload($r);
}
$errors = $this->validatePayload($entity->getData(),$new_array);
// check internal errors
$internal_errors = WebformSubmissionForm::validateWebformSubmission($entity);
if (!empty($internal_errors)){
foreach ($internal_errors as $key => $message){
$errors[$key][] = $message->__toString();
}
}
$errors_collection = [];
if (!empty($errors)){
foreach ($errors as $field_id => $details){
foreach ($details as $item){
$errors_collection[] = new HttpException(422,$field_id . '|' . $item);
}
}
$errs = new ErrorCollection($errors_collection);
$document = new JsonApiDocumentTopLevel($errs, new NullIncludedData(), new LinkCollection([]));
$response = new ResourceResponse($document, 422);
return $response;
}

$resource_object = ResourceObject::createFromEntity($resource_type, $entity);
$primary_data = new ResourceObjectData([$resource_object], 1);
$response = $this->createJsonapiResponse($primary_data, $request, 201);
// Normal data
// $resource_object = ResourceObject::createFromEntity($resource_type, $entity);
// $primary_data = new ResourceObjectData([$resource_object], 1);
// $response = $this->createJsonapiResponse($primary_data, $request, 201);
// Normal data

// $err = new HttpException(422,'hello');
// $errs = new ErrorCollection([$err,$err,$err]);
// $errs = new ErrorCollection($errors_collection);
//
// $document = new JsonApiDocumentTopLevel($errs, new NullIncludedData(), new LinkCollection([]));
// $response = new ResourceResponse($document, 422);
return $response;
}

public function getRouteResourceTypes(Route $route, string $route_name): array {
return $this->getResourceTypesByEntityTypeId('webform_submission');
}

public function webformValidateSettingsExtractor(array $supported_validation,array $original_elements): array {
$res = [];
// Iterate through webform values.
foreach ($original_elements as $w_key => $items) {
// Iterate through supported validation keys and their values.
foreach ($supported_validation as $key => $value) {
// If the current value is an array, check for a match with the key.
if (is_array($value)) {
if (array_key_exists($key, $items)) {
$res[$w_key][$key] = $items[$key];
}
}
else {
// If the value exists in the items and is not an array, store it in the result.
if (array_key_exists($value, $items)) {
$res[$w_key][$value] = $items[$value];
}
}
}
}
return $res;
}

public function getSupportedValidateElements(){
return [
'#required',
'#required_error',
'#pattern',
'#pattern_error',
];
}

public function attachValidateSettingsToPayload(array $payload){
$output = [];
$mapping = [
'#required' => 'required',
'#required_error' => 'required',
'#pattern' => 'pattern',
'#pattern_error' => 'pattern',
];
foreach ($payload as $key => $value) {
if (isset($mapping[$key])) {
$output[$mapping[$key]][] = $value;
}
}
return $output;
}

public function validatePayload(array $payload, array $massaged_validates_array){
$results = [];
foreach ($payload as $id => $value){
if (array_key_exists($id,$massaged_validates_array)){
if (!empty($this->generateErrorString($value, $massaged_validates_array[$id]))){
$results[$id] = $this->generateErrorString($value, $massaged_validates_array[$id]);
}
}
}
return $results;
}

public function generateErrorString($value, array $arr){
$res = [];
foreach ($arr as $k => $v) {
if (call_user_func('tide_webform_' . $k . '_validate',$value,$v) !== TRUE){
$res[] = call_user_func('tide_webform_' . $k . '_validate',$value,$v);
}
}
return $res;
}
}
6 changes: 6 additions & 0 deletions modules/tide_webform_jsonapi/tide_webform_jsonapi.info.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: 'JSON:API Tide_webform'
description: "This module let's you validate payload for webform."
core_version_requirement: ^9 || ^10
type: module
dependencies:
- drupal:jsonapi_resources
11 changes: 11 additions & 0 deletions modules/tide_webform_jsonapi/tide_webform_jsonapi.routing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
tide_webform_jsonapi.add_webform:
path: '/%jsonapi%/webform/{webform}/add'
methods: ['POST']
defaults:
_jsonapi_resource: Drupal\tide_webform_jsonapi\Resource\AddWebform
requirements:
_permission: 'access content'
options:
parameters:
webform:
type: 'entity:webform'

0 comments on commit 3a21e60

Please sign in to comment.