[修正前]/src/Eccube/Form/Type/Admin/ProductType.php [修正後]/src/Eccube/Form/Type/Admin/ProductType.php
<?php <?php
   
/* /*
* This file is part of EC-CUBE * This file is part of EC-CUBE
* *
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
* *
* http://www.ec-cube.co.jp/ * http://www.ec-cube.co.jp/
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
*/  */ 
   
namespace Eccube\Form\Type\Admin; namespace Eccube\Form\Type\Admin;
   
use Eccube\Common\EccubeConfig; use Eccube\Common\EccubeConfig;
use Eccube\Entity\Category; use Eccube\Entity\Category;
use Eccube\Form\Type\Master\ProductStatusType; use Eccube\Form\Type\Master\ProductStatusType;
use Eccube\Form\Validator\TwigLint; use Eccube\Form\Validator\TwigLint;
use Eccube\Repository\CategoryRepository; use Eccube\Repository\CategoryRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
.  use Symfony\Component\Form\FormError;
  use Symfony\Component\Form\FormEvent;
  use Symfony\Component\Form\FormEvents;
  use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
   
/** /**
* Class ProductType. * Class ProductType.
*/  */ 
class ProductType extends AbstractType class ProductType extends AbstractType
{ {
   /**    /**
    * @var CategoryRepository     * @var CategoryRepository
    */      */ 
   protected $categoryRepository;    protected $categoryRepository;
   
   /**    /**
    * @var EccubeConfig     * @var EccubeConfig
    */      */ 
   protected $eccubeConfig;    protected $eccubeConfig;
   
   /**    /**
    * ProductType constructor.     * ProductType constructor.
    *     *
    * @param CategoryRepository $categoryRepository     * @param CategoryRepository $categoryRepository
    * @param EccubeConfig $eccubeConfig     * @param EccubeConfig $eccubeConfig
    */      */ 
   public function __construct(    public function __construct(
       CategoryRepository $categoryRepository,        CategoryRepository $categoryRepository,
       EccubeConfig $eccubeConfig        EccubeConfig $eccubeConfig
   ) {    ) {
       $this->categoryRepository = $categoryRepository;        $this->categoryRepository = $categoryRepository;
       $this->eccubeConfig = $eccubeConfig;        $this->eccubeConfig = $eccubeConfig;
   }    }
   
   /**    /**
    * {@inheritdoc}     * {@inheritdoc}
    */      */ 
   public function buildForm(FormBuilderInterface $builder, array $options)    public function buildForm(FormBuilderInterface $builder, array $options)
   {    {
       $builder        $builder
           // 商品規格情報            // 商品規格情報
           ->add('class', ProductClassType::class, [            ->add('class', ProductClassType::class, [
               'mapped' => false,                'mapped' => false,
           ])            ])
           // 基本情報            // 基本情報
           ->add('name', TextType::class, [            ->add('name', TextType::class, [
               'constraints' => [                'constraints' => [
                   new Assert\NotBlank(),                    new Assert\NotBlank(),
                   new Assert\Length(['max' => $this->eccubeConfig['eccube_stext_len']]),                    new Assert\Length(['max' => $this->eccubeConfig['eccube_stext_len']]),
               ],                ],
           ])            ])
           ->add('product_image', FileType::class, [            ->add('product_image', FileType::class, [
               'multiple' => true,                'multiple' => true,
               'required' => false,                'required' => false,
               'mapped' => false,                'mapped' => false,
           ])            ])
           ->add('description_detail', TextareaType::class, [            ->add('description_detail', TextareaType::class, [
               'constraints' => [                'constraints' => [
                   new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),                    new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),
               ],                ],
           ])            ])
           ->add('description_list', TextareaType::class, [            ->add('description_list', TextareaType::class, [
               'required' => false,                'required' => false,
               'constraints' => [                'constraints' => [
                   new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),                    new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),
               ],                ],
           ])            ])
           ->add('Category', ChoiceType::class, [            ->add('Category', ChoiceType::class, [
               'choice_label' => 'Name',                'choice_label' => 'Name',
               'multiple' => true,                'multiple' => true,
               'mapped' => false,                'mapped' => false,
               'expanded' => true,                'expanded' => true,
               'choices' => $this->categoryRepository->getList(null, true),                'choices' => $this->categoryRepository->getList(null, true),
               'choice_value' => function (Category $Category = null) {                'choice_value' => function (Category $Category = null) {
                   return $Category ? $Category->getId() : null;                    return $Category ? $Category->getId() : null;
               },                },
           ])            ])
   
           // 詳細な説明            // 詳細な説明
           ->add('Tag', EntityType::class, [            ->add('Tag', EntityType::class, [
               'class' => 'Eccube\Entity\Tag',                'class' => 'Eccube\Entity\Tag',
               'query_builder' => function ($er) {                'query_builder' => function ($er) {
                   return $er->createQueryBuilder('t')                    return $er->createQueryBuilder('t')
                   ->orderBy('t.sort_no', 'DESC');                    ->orderBy('t.sort_no', 'DESC');
               },                },
               'required' => false,                'required' => false,
               'multiple' => true,                'multiple' => true,
               'expanded' => true,                'expanded' => true,
               'mapped' => false,                'mapped' => false,
           ])            ])
           ->add('search_word', TextType::class, [            ->add('search_word', TextType::class, [
               'required' => false,                'required' => false,
               'constraints' => [                'constraints' => [
                   new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),                    new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),
               ],                ],
           ])            ])
           // サブ情報            // サブ情報
           ->add('free_area', TextareaType::class, [            ->add('free_area', TextareaType::class, [
               'required' => false,                'required' => false,
               'constraints' => [                'constraints' => [
                   new TwigLint(),                    new TwigLint(),
               ],                ],
           ])            ])
   
           // 右ブロック            // 右ブロック
           ->add('Status', ProductStatusType::class, [            ->add('Status', ProductStatusType::class, [
               'constraints' => [                'constraints' => [
                   new Assert\NotBlank(),                    new Assert\NotBlank(),
               ],                ],
           ])            ])
           ->add('note', TextareaType::class, [            ->add('note', TextareaType::class, [
               'required' => false,                'required' => false,
               'constraints' => [                'constraints' => [
                   new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),                    new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),
               ],                ],
           ])            ])
   
           // タグ            // タグ
           ->add('tags', CollectionType::class, [            ->add('tags', CollectionType::class, [
               'entry_type' => HiddenType::class,                'entry_type' => HiddenType::class,
               'prototype' => true,                'prototype' => true,
               'mapped' => false,                'mapped' => false,
               'allow_add' => true,                'allow_add' => true,
               'allow_delete' => true,                'allow_delete' => true,
           ])            ])
           // 画像            // 画像
           ->add('images', CollectionType::class, [            ->add('images', CollectionType::class, [
               'entry_type' => HiddenType::class,                'entry_type' => HiddenType::class,
               'prototype' => true,                'prototype' => true,
               'mapped' => false,                'mapped' => false,
               'allow_add' => true,                'allow_add' => true,
               'allow_delete' => true,                'allow_delete' => true,
           ])            ])
           ->add('add_images', CollectionType::class, [            ->add('add_images', CollectionType::class, [
               'entry_type' => HiddenType::class,                'entry_type' => HiddenType::class,
               'prototype' => true,                'prototype' => true,
               'mapped' => false,                'mapped' => false,
               'allow_add' => true,                'allow_add' => true,
               'allow_delete' => true,                'allow_delete' => true,
           ])            ])
           ->add('delete_images', CollectionType::class, [            ->add('delete_images', CollectionType::class, [
               'entry_type' => HiddenType::class,                'entry_type' => HiddenType::class,
               'prototype' => true,                'prototype' => true,
               'mapped' => false,                'mapped' => false,
               'allow_add' => true,                'allow_add' => true,
               'allow_delete' => true,                'allow_delete' => true,
           ])            ])
           ->add('return_link', HiddenType::class, [            ->add('return_link', HiddenType::class, [
               'mapped' => false,                'mapped' => false,
           ])            ])
       ;        ;
.   
         $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
             /** @var FormInterface $form */ 
             $form = $event->getForm();
             $saveImgDir = $this->eccubeConfig['eccube_save_image_dir'];
             $tempImgDir = $this->eccubeConfig['eccube_temp_image_dir'];
             $this->validateFilePath($form->get('delete_images'), [$saveImgDir, $tempImgDir]);
             $this->validateFilePath($form->get('add_images'), [$tempImgDir]);
         });
     }
   
     /**
      * 指定された複数ディレクトリのうち、いずれかのディレクトリ以下にファイルが存在するかを確認。
      *
      * @param $form FormInterface
      * @param $dirs array
      */ 
     private function validateFilePath($form, $dirs)
     {
         foreach ($form->getData() as $fileName) {
             $fileInDir = array_filter($dirs, function ($dir) use ($fileName) {
                 $filePath = realpath($dir.'/'.$fileName);
                 $topDirPath = realpath($dir);
                 return strpos($filePath, $topDirPath) === 0 && $filePath !== $topDirPath;
             });
             if (!$fileInDir) {
                 $form->getRoot()['product_image']->addError(new FormError('画像のパスが不正です。'));
             }
         }
   }    }
   
   /**    /**
    * {@inheritdoc}     * {@inheritdoc}
    */      */ 
   public function configureOptions(OptionsResolver $resolver)    public function configureOptions(OptionsResolver $resolver)
   {    {
   }    }
   
   /**    /**
    * {@inheritdoc}     * {@inheritdoc}
    */      */ 
   public function getBlockPrefix()    public function getBlockPrefix()
   {    {
       return 'admin_product';        return 'admin_product';
   }    }
} }