text: <?php
  
  namespace Concrete\Core\Attribute;
  
  use Concrete\Core\Application\Application;
  use Concrete\Core\Attribute\Category\CategoryInterface;
  use Concrete\Core\Entity\Attribute\Key\Key;
  use Concrete\Core\Entity\Attribute\Value\Value;
  use Concrete\Core\Error\ErrorList\Error\ErrorInterface;
  use Concrete\Core\Error\ErrorList\Error\FieldNotPresentError;
  use Concrete\Core\Error\ErrorList\ErrorList;
  use Concrete\Core\Error\ErrorList\Field\Field;
  use Concrete\Core\Validation\Response;
  use Concrete\Core\Entity\Attribute\Type as TypeEntity;
  use Concrete\Core\Validation\ResponseInterface;
  use Symfony\Component\HttpFoundation\Request;
  
  class StandardValidator implements ValidatorInterface
  {
  
      protected $application;
  
      public function validateAddKeyRequest(CategoryInterface $category, TypeEntity $type, Request $request)
      {
          return $this->validate($category, $type->getController(), $request);
      }
  
      public function validateUpdateKeyRequest(CategoryInterface $category, Key $key, Request $request)
      {
          return $this->validate($category, $key->getAttributeType()->getController(), $request, $key);
      }
  
      public function validateSaveValueRequest(Controller $controller, Request $request, $includeFieldNotPresentErrors = true)
      {
          $key = $controller->getAttributeKey();
          $response = new Response();
          if ($key && method_exists($controller, 'validateForm')) {
              $controller->setRequest($request);
              $validateResponse = $controller->validateForm($controller->post());
              $response = $this->parseResponse($key, $response, $validateResponse, $includeFieldNotPresentErrors);
          }
          return $response;
      }
  
      /**
       * @param Key $key
       * @param Response $response
       * @param mixed $validateResponse
       * @param bool $includeFieldNotPresentErrors
       * @return Response $response
       */
      protected function parseResponse(
          Key $key,
          Response $response,
          $validateResponse,
          $includeFieldNotPresentErrors)
      {
          if ($validateResponse instanceof ErrorList) {
              foreach ($validateResponse->getList() as $error) {
                  if (!($error instanceof FieldNotPresentError) || $includeFieldNotPresentErrors) {
                      $response->setIsValid(false);
                      $response->getErrorObject()->add($error);
                  }
              }
          } else if ($validateResponse instanceof ErrorInterface) {
              if (!($validateResponse instanceof FieldNotPresentError) || $includeFieldNotPresentErrors) {
                  $response->setIsValid(false);
                  $response->getErrorObject()->add($validateResponse);
              }
          } else if ($validateResponse == false) {
              if ($includeFieldNotPresentErrors) {
                  $response->setIsValid(false);
                  $response->getErrorObject()->add(new FieldNotPresentError(new Field($key->getAttributeKeyDisplayName())));
              }
          }
          return $response;
      }
  
      public function validateCurrentAttributeValue(
          Controller $controller,
          AttributeValueInterface $value,
          $includeFieldNotPresentErrors = true)
      {
          $key = $controller->getAttributeKey();
          $controller->setAttributeValue($value);
          $response = new Response();
          if ($key && method_exists($controller, 'validateValue')) {
              $validateResponse = $controller->validateValue();
              $response = $this->parseResponse($key, $response, $validateResponse, $includeFieldNotPresentErrors);
          }
          return $response;
      }
  
      public function __construct(Application $application)
      {
          $this->application = $application;
      }
  
      protected function validate(CategoryInterface $category, Controller $controller, Request $request, Key $key = null)
      {
          /** @var \Concrete\Core\Form\Service\Validation $val */
          $val = $this->application->make('helper/validation/form');
          /** @var \Concrete\Core\Validation\CSRF\Token $valt */
          $valt = $this->application->make('helper/validation/token');
          $val->setData($request->request->all());
          $val->addRequired("akHandle", t("Handle required."));
          $val->addRequired("akName", t('Name required.'));
          $val->addRequired("atID", t('Type required.'));
          $val->test();
          $error = $val->getError();
  
          if (!$valt->validate('add_or_update_attribute')) {
              $error->add($valt->getErrorMessage());
          }
  
          /** @var \Concrete\Core\Utility\Service\Validation\Strings $stringValidator */
          $stringValidator = $this->application->make('helper/validation/strings');
          if (!$stringValidator->handle($request->request->get('akHandle'))) {
              $error->add(t('Attribute handles may only contain letters, numbers and underscore "_" characters'));
          }
  
          $existing = $category->getAttributeKeyByHandle($request->request->get('akHandle'));
          if (is_object($existing)) {
              if (is_object($key)) {
                  if ($key->getAttributeKeyID() != $existing->getAttributeKeyID()) {
                      $error->add(t("An attribute with the handle %s already exists.", $request->request->get('akHandle')));
                  }
              } else {
                  $error->add(t("An attribute with the handle %s already exists.", $request->request->get('akHandle')));
              }
          }
  
          $controllerResponse = $controller->validateKey($request->request->all());
          if ($controllerResponse instanceof ErrorList) {
              $error->add($controllerResponse);
          }
  
          $response = new Response();
          if ($error->has()) {
              $response->setIsValid(false);
              $response->setErrorObject($error);
          }
          return $response;
      }
  
  }
  