<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
*
* http://www.ec-cube.co.jp/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Eccube\Form\Type\Admin;
use Eccube\Common\EccubeConfig;
use Eccube\Entity\News;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
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\Validator\Constraints as Assert;
class NewsType extends AbstractType
{
/**
* @var EccubeConfig
*/
protected $eccubeConfig;
public function __construct(EccubeConfig $eccubeConfig)
{
$this->eccubeConfig = $eccubeConfig;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('publish_date', DateTimeType::class, [
'widget' => 'single_text',
'input' => 'datetime',
'years' => range($this->eccubeConfig['eccube_news_start_year'], date('Y') + 3),
'with_seconds' => true,
'constraints' => [
new Assert\NotBlank(),
new Assert\Range([
'min'=> '0003-01-01',
'minMessage' => 'form_error.out_of_range',
]),
],
])
->add('title', TextType::class, [
'required' => true,
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(['max' => $this->eccubeConfig['eccube_mtext_len']]),
],
])
->add('url', TextType::class, [
'required' => false,
'constraints' => [
new Assert\Url(),
new Assert\Length(['max' => $this->eccubeConfig['eccube_mtext_len']]),
],
])
->add('link_method', CheckboxType::class, [
'required' => false,
'label' => 'admin.content.news.new_window',
'value' => '1',
])
// 画像
->add('news_image', FileType::class, [
'multiple' => true,
'required' => false,
'mapped' => false,
])
->add('images', CollectionType::class, [
'entry_type' => HiddenType::class,
'prototype' => true,
'mapped' => false,
'allow_add' => true,
'allow_delete' => true,
])
->add('add_images', CollectionType::class, [
'entry_type' => HiddenType::class,
'prototype' => true,
'mapped' => false,
'allow_add' => true,
'allow_delete' => true,
])
->add('delete_images', CollectionType::class, [
'entry_type' => HiddenType::class,
'prototype' => true,
'mapped' => false,
'allow_add' => true,
'allow_delete' => true,
])
->add('description', TextareaType::class, [
'required' => false,
'purify_html' => true,
'attr' => [
'rows' => 8,
],
'constraints' => [
new Assert\Length(['max' => $this->eccubeConfig['eccube_ltext_len']]),
],
])
->add('visible', ChoiceType::class, [
'label' => false,
'choices' => ['admin.content.news.display_status__show' => true, 'admin.content.news.display_status__hide' => false],
'required' => true,
'expanded' => 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) {
if (strpos($fileName, '..') !== false) {
$form->getRoot()['product_image']->addError(new FormError(trans('admin.product.image__invalid_path')));
break;
}
$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(trans('admin.product.image__invalid_path')));
}
}
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => News::class,
]);
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'admin_news';
}
}