app/Plugin/Api42/GraphQL/Query/SearchFormQuery.php line 115

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Plugin\Api42\GraphQL\Query;
  13. use Eccube\Common\EccubeConfig;
  14. use Eccube\Util\StringUtil;
  15. use GraphQL\Type\Definition\Type;
  16. use Knp\Component\Pager\PaginatorInterface;
  17. use Plugin\Api42\GraphQL\Error\InvalidArgumentException;
  18. use Plugin\Api42\GraphQL\Query;
  19. use Plugin\Api42\GraphQL\Type\ConnectionType;
  20. use Plugin\Api42\GraphQL\Types;
  21. use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
  22. use Symfony\Component\Form\Extension\Core\Type\IntegerType;
  23. use Symfony\Component\Form\FormBuilderInterface;
  24. use Symfony\Component\Form\FormFactoryInterface;
  25. use Symfony\Component\Form\FormInterface;
  26. use Symfony\Component\Validator\Constraints as Assert;
  27. abstract class SearchFormQuery implements Query
  28. {
  29.     /**
  30.      * @var PaginatorInterface
  31.      */
  32.     private $paginator;
  33.     /**
  34.      * @var EccubeConfig
  35.      */
  36.     private $eccubeConfig;
  37.     /**
  38.      * @var FormFactoryInterface
  39.      */
  40.     private $formFactory;
  41.     /**
  42.      * @var Types
  43.      */
  44.     private $types;
  45.     /**
  46.      * @required
  47.      */
  48.     public function setPaginator(PaginatorInterface $paginator): void
  49.     {
  50.         $this->paginator $paginator;
  51.     }
  52.     /**
  53.      * @required
  54.      */
  55.     public function setEccubeConfig(EccubeConfig $eccubeConfig): void
  56.     {
  57.         $this->eccubeConfig $eccubeConfig;
  58.     }
  59.     /**
  60.      * @required
  61.      */
  62.     public function setFormFactory(FormFactoryInterface $formFactory): void
  63.     {
  64.         $this->formFactory $formFactory;
  65.     }
  66.     /**
  67.      * @required
  68.      */
  69.     public function setTypes(Types $types): void
  70.     {
  71.         $this->types $types;
  72.     }
  73.     protected function createQuery($entityClass$searchFormType$resolver)
  74.     {
  75.         $builder $this->formFactory->createBuilder($searchFormTypenull, ['csrf_protection' => false]);
  76.         $this->overrideDateTimeFormat($builder);
  77.         $this->addPagingForms($builder);
  78.         $args array_reduce($builder->getForm()->all(), function ($acc$form) {
  79.             /* @var FormInterface $form */
  80.             $formConfig $form->getConfig();
  81.             $typeClass get_class($formConfig->getType()->getInnerType());
  82.             switch ($typeClass) {
  83.                 case IntegerType::class:
  84.                     $type Type::int();
  85.                     break;
  86.                 case DateTimeType::class:
  87.                     $type \Plugin\Api42\GraphQL\Type\Definition\DateTimeType::dateTime();
  88.                     break;
  89.                 default:
  90.                     $type Type::string();
  91.                     break;
  92.             }
  93.             if ($formConfig->getOption('multiple')) {
  94.                 $type Type::listOf($type);
  95.             }
  96.             if ($formConfig->getOption('required') && !$formConfig->getOption('multiple')) {
  97.                 $type Type::nonNull($type);
  98.             }
  99.             $defaultValue $form->getViewData();
  100.             $acc[$form->getName()] = [
  101.                 'type' => $type,
  102.                 'defaultValue' => StringUtil::isNotBlank($defaultValue) ? $defaultValue null,
  103.                 'description' => $formConfig->getOption('label') ? trans($formConfig->getOption('label')) : null,
  104.             ];
  105.             return $acc;
  106.         }, []);
  107.         return [
  108.             'type' => new ConnectionType($entityClass$this->types),
  109.             'args' => $args,
  110.             'resolve' => function ($root$args) use ($builder$resolver) {
  111.                 $form $builder->getForm();
  112.                 foreach ($form->all() as $field) {
  113.                     $formConfig $field->getConfig();
  114.                     if ($formConfig->getType()->getInnerType() instanceof DateTimeType) {
  115.                         $value $args[$field->getName()];
  116.                         if ($value instanceof \DateTime) {
  117.                             $args[$field->getName()] = $value->format(\DateTime::ATOM);
  118.                         }
  119.                     }
  120.                 }
  121.                 $form->submit($args);
  122.                 if (!$form->isValid()) {
  123.                     $message '';
  124.                     foreach ($form->getErrors(true) as $error) {
  125.                         $message .= sprintf('%s: %s;'$error->getOrigin()->getName(), $error->getMessage());
  126.                     }
  127.                     throw new InvalidArgumentException($message);
  128.                 }
  129.                 $data $form->getData();
  130.                 return $this->paginator->paginate($resolver($data), $args['page'], $args['limit']);
  131.             },
  132.         ];
  133.     }
  134.     /**
  135.      * DateTimeTypeのフォーマットを「yyyy-MM-dd'T'HH:mm:ssZ」に上書きする
  136.      *
  137.      * @param FormBuilderInterface $builder
  138.      */
  139.     private function overrideDateTimeFormat(FormBuilderInterface $builder)
  140.     {
  141.         /** @var FormBuilderInterface $field */
  142.         foreach ($builder->all() as $field) {
  143.             $type $field->getType()->getInnerType();
  144.             if ($type instanceof DateTimeType) {
  145.                 $options $field->getOptions();
  146.                 $options['format'] = "yyyy-MM-dd'T'HH:mm:ssZ";
  147.                 $options['html5'] = false;
  148.                 $builder->add($field->getName(), get_class($type), $options);
  149.             }
  150.         }
  151.     }
  152.     /**
  153.      * Pagingのためのフォームを追加
  154.      *
  155.      * @param FormBuilderInterface $builder
  156.      */
  157.     private function addPagingForms(FormBuilderInterface $builder)
  158.     {
  159.         $builder->add('page'IntegerType::class, [
  160.             'label' => 'api.search_form_query.args.description.page',
  161.             'required' => false,
  162.             'data' => 1,
  163.             'constraints' => [
  164.                 new Assert\Regex([
  165.                     'pattern' => "/^\d+$/u",
  166.                     'message' => 'form_error.numeric_only',
  167.                 ]),
  168.                 new Assert\GreaterThan(0),
  169.             ],
  170.         ])->add('limit'IntegerType::class, [
  171.             'label' => 'api.search_form_query.args.description.limit',
  172.             'required' => false,
  173.             'data' => $this->eccubeConfig->get('eccube_default_page_count'),
  174.             'constraints' => [
  175.                 new Assert\Regex([
  176.                     'pattern' => "/^\d+$/u",
  177.                     'message' => 'form_error.numeric_only',
  178.                 ]),
  179.                 new Assert\GreaterThan(0),
  180.             ],
  181.         ]);
  182.     }
  183. }