Snippets

Andrew Stark Symfony Api Validation (not full code)

Created by Andrew Stark last modified

    /**
     * @throws JsonException
     */
    public function update(UpdateUserAccountRequest $request): JsonResponse {
        $this->commandBus->dispatch(
            (UpdateUser::fromRequest($request))->setAuthToken($request->headers->get('X-AUTH-TOKEN'))
        );
        return $this->createResponse($this->translator->trans('entity.updated', [], 'message_success'));
    }
<?php
declare(strict_types=1);

/*
 * Created by BonBonSlick
 */

namespace App\Infrastructure\Validation\Request\PublicApi\Secured\Update;

use App\Domain\Core\Exceptions\BadParameterException;
use App\Domain\Core\Exceptions\WrongInstanceOfClassException;
use App\Domain\Core\ValueObjects\String\Description;
use App\Domain\Core\ValueObjects\String\Slug;
use App\Domain\Internationalization\Country\Filter\CountryFilter;
use App\Domain\Internationalization\Language\Filter\LanguageFilter;
use App\Domain\UserPack\Email\Entity\UserEmail;
use App\Domain\UserPack\Email\Filter\UserEmailFilter;
use App\Domain\UserPack\User\Entity\User;
use App\Domain\UserPack\User\Filter\UserFilter;
use App\Infrastructure\Traits\Helper\StringHelperTrait;
use App\Infrastructure\Validation\Constraints\Compound\EmailCompound;
use App\Infrastructure\Validation\Constraints\Compound\NicknameCompound;
use App\Infrastructure\Validation\Constraints\Compound\NonEmptyStringCompound;
use App\Infrastructure\Validation\Constraints\UniqueEntityConstraint;
use App\Infrastructure\Validation\Constraints\ValueExistsConstraint;
use App\Infrastructure\Validation\Request\AbstractValidationRequest;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Country;
use Symfony\Component\Validator\Constraints\Language;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Validator\Constraints\Sequentially;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\ClassMetadataInterface;


class UpdateUserAccountRequest extends AbstractValidationRequest {
    use StringHelperTrait;

    private ?string     $slug;
    private ?string     $nickname;
    private ?string     $description;
    private ?string     $languageAlpha2;
    private ?string     $countryAlpha2;
    private ?string     $email;
    private ?string     $fallbackEmail;

    public function __construct(Request $request) {
        parent::__construct($request);
        $this->slug           = (string)$request->request->get('slug');
        $this->nickname       = (string)$request->request->get('nickname');
        $this->description    = (string)$request->request->get('description');
        $this->languageAlpha2 = $this->lower((string)$request->request->get('languageAlpha2'));
        $this->countryAlpha2  = $this->upper((string)$request->request->get('countryAlpha2'));
        $this->email          = $this->lower((string)$request->request->get('email'));
        $this->fallbackEmail  = $this->lower((string)$request->request->get('fallbackEmail'));
    }

    public static function loadValidatorMetadata(ClassMetadataInterface $classMetadata): void {
        // added validation here cant be executed conditionally based on passed values 
        $classMetadata->addConstraint(new Callback(['callback' => 'validate']));
    }

    /**
     * @throws WrongInstanceOfClassException
     * @throws BadParameterException
     */
    public function validate(ExecutionContextInterface $context): void {
        /** @var ClassMetadataInterface $classMetadata */
        $classMetadata = $context->getMetadata();
        if (false === $classMetadata instanceof ClassMetadataInterface) {
            throw new WrongInstanceOfClassException();
        }
        if (false === empty($this->slug())) {
            $classMetadata->addPropertyConstraints(
                'slug',
                [
                    new Sequentially(
                        [
                            new NonEmptyStringCompound(),
                            new Length(['min' => Slug::LENGTH_MIN, 'max' => Slug::LENGTH_MAX]),
                            new Regex(
                                [
                                    'pattern' => '/[a-z0-9]+/',
                                    'message' => 'required.alphanumeric.values.123',
                                ]
                            ),
                            new UniqueEntityConstraint(
                                [
                                    'entityClass' => User::class,
                                    'filter'      => (new UserFilter())->setSlug($this->slug()),
                                ]
                            ),
                        ]
                    ),
                ]
            );
        }
        if (false === empty($this->nickname())) {
            $classMetadata->addPropertyConstraints(
                'nickname',
                [
                    new NicknameCompound(),
                    new UniqueEntityConstraint(
                        [
                            'entityClass' => User::class,
                            'filter'      => (new UserFilter())->setNickname($this->nickname()),
                        ]
                    ),
                ]
            );
        }
        if (false === empty($this->description())) {
            $classMetadata->addPropertyConstraints(
                'description',
                [
                    new Sequentially(
                        [
                            new NonEmptyStringCompound(),
                            new Length(['max' => Description::LENGTH_MAX]),
                        ]
                    ),
                ]
            );
        }
        if (false === empty($this->languageAlpha2())) {
            $classMetadata->addPropertyConstraints(
                'languageAlpha2',
                [
                    new Sequentially(
                        [
                            new NonEmptyStringCompound(),
                            new Length(['min' => 2, 'max' => 3]),
                            new Language(),
                            new ValueExistsConstraint(
                                [
                                    'entityClass' => \App\Domain\Internationalization\Language\Entity\Language::class,
                                    'filter'      => (new LanguageFilter())->setAlpha2($this->languageAlpha2()),
                                ]
                            ),
                        ]
                    ),
                ]
            );
        }
        if (false === empty($this->countryAlpha2())) {
            $classMetadata->addPropertyConstraints(
                'countryAlpha2',
                [
                    new Sequentially(
                        [
                            new NonEmptyStringCompound(),
                            new Length(['min' => 2, 'max' => 3]),
                            new Country(),
                            new ValueExistsConstraint(
                                [
                                    'entityClass' => \App\Domain\Internationalization\Country\Entity\Country::class,
                                    'filter'      => (new CountryFilter())->setAlpha2($this->countryAlpha2())
                                    ,
                                ]
                            ),
                        ]
                    ),
                ]
            );
        }

        if (false === empty($this->email())) {
            $classMetadata->addPropertyConstraints(
                'email',
                [
                    new Sequentially(
                        [
                            new NonEmptyStringCompound(),
                            new EmailCompound(),
                            new UniqueEntityConstraint(
                                [
                                    'entityClass' => UserEmail::class,
                                    'filter'      => (new UserEmailFilter())
                                        ->setEmail($this->email())
                                        ->setIsActive(true),
                                ]
                            ),
                        ],
                    ),
                ]
            );
        }
        // @todo - fallback email update
    }

    public function slug(): ?string {
        return $this->slug;
    }

    public function nickname(): ?string {
        return $this->nickname;
    }

    public function description(): ?string {
        return $this->description;
    }

    public function languageAlpha2(): ?string {
        return $this->languageAlpha2;
    }

    public function countryAlpha2(): ?string {
        return $this->lower($this->countryAlpha2);
    }

    public function email(): ?string {
        return $this->email;
    }

    public function fallbackEmail(): ?string {
        return $this->fallbackEmail;
    }

}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.