ShippingType::buildForm()   F
last analyzed

Complexity

Conditions 22
Paths 1

Size

Total Lines 205

Duplication

Lines 12
Ratio 5.85 %

Code Coverage

Tests 117
CRAP Score 22.0174

Importance

Changes 0
Metric Value
cc 22
nc 1
nop 2
dl 12
loc 205
ccs 117
cts 121
cp 0.9669
crap 22.0174
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.ec-cube.co.jp/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Eccube\Form\Type\Shopping;
15
16
use Eccube\Common\EccubeConfig;
17
use Eccube\Entity\Delivery;
18
use Eccube\Entity\DeliveryTime;
19
use Eccube\Entity\Shipping;
20
use Eccube\Repository\DeliveryFeeRepository;
21
use Eccube\Repository\DeliveryRepository;
22
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
23
use Symfony\Component\Form\AbstractType;
24
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
25
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
26
use Symfony\Component\Form\FormBuilderInterface;
27
use Symfony\Component\Form\FormEvent;
28
use Symfony\Component\Form\FormEvents;
29
use Symfony\Component\OptionsResolver\OptionsResolver;
30
use Symfony\Component\Validator\Constraints\NotBlank;
31
32
class ShippingType extends AbstractType
33
{
34
    /**
35
     * @var EccubeConfig
36
     */
37
    protected $eccubeConfig;
38
39
    /**
40
     * @var DeliveryRepository
41
     */
42
    protected $deliveryRepository;
43
44
    /**
45
     * @var DeliveryFeeRepository
46
     */
47
    protected $deliveryFeeRepository;
48
49
    /**
50
     * ShippingType constructor.
51
     *
52
     * @param EccubeConfig $eccubeConfig
53
     * @param DeliveryRepository $deliveryRepository
54
     * @param DeliveryFeeRepository $deliveryFeeRepository
55
     */
56
    public function __construct(EccubeConfig $eccubeConfig, DeliveryRepository $deliveryRepository, DeliveryFeeRepository $deliveryFeeRepository)
57 50
    {
58
        $this->eccubeConfig = $eccubeConfig;
59 50
        $this->deliveryRepository = $deliveryRepository;
60 50
        $this->deliveryFeeRepository = $deliveryFeeRepository;
61 50
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66
    public function buildForm(FormBuilderInterface $builder, array $options)
67 50
    {
68
        $builder
69
            ->add(
70 50
                'OrderItems',
71 50
                CollectionType::class,
72 50
                [
73
                    'entry_type' => OrderItemType::class,
74 50
                ]
75
            );
76
77
        // 配送業者のプルダウンを生成
78
        $builder->addEventListener(
79 50
            FormEvents::PRE_SET_DATA,
80 50
            function (FormEvent $event) {
81 50
                /* @var Shipping $Shipping */
82
                $Shipping = $event->getData();
83 50
                if (is_null($Shipping) || !$Shipping->getId()) {
84 50
                    return;
85
                }
86
87
                // 配送商品に含まれる販売種別を抽出.
88
                $OrderItems = $Shipping->getProductOrderItems();
89 50
                $SaleTypes = [];
90 50 View Code Duplication
                foreach ($OrderItems as $OrderItem) {
91 50
                    $ProductClass = $OrderItem->getProductClass();
92 50
                    $SaleType = $ProductClass->getSaleType();
93 50
                    $SaleTypes[$SaleType->getId()] = $SaleType;
94 50
                }
95
96
                // 販売種別に紐づく配送業者を取得.
97
                $Deliveries = $this->deliveryRepository->getDeliveries($SaleTypes);
98 50
99
                // 配送業者のプルダウンにセット.
100
                $form = $event->getForm();
101 50
                $form->add(
102 50
                    'Delivery',
103 50
                    EntityType::class,
104 50
                    [
105
                        'required' => false,
106 50
                        'label' => 'shipping.label.delivery_hour',
107 50
                        'class' => 'Eccube\Entity\Delivery',
108 50
                        'choice_label' => 'name',
109 50
                        'choices' => $Deliveries,
110 50
                        'placeholder' => false,
111
                        'constraints' => [
112
                            new NotBlank(),
113 50
                        ],
114
                    ]
115
                );
116
            }
117 50
        );
118
119
        // お届け日のプルダウンを生成
120
        $builder->addEventListener(
121 50
            FormEvents::PRE_SET_DATA,
122 50
            function (FormEvent $event) {
123 50
                $Shipping = $event->getData();
124 50
                if (is_null($Shipping) || !$Shipping->getId()) {
125 50
                    return;
126
                }
127
128
                // お届け日の設定
129
                $minDate = 0;
130 50
                $deliveryDurationFlag = false;
131 50
132
                // 配送時に最大となる商品日数を取得
133
                foreach ($Shipping->getOrderItems() as $detail) {
134 50
                    $ProductClass = $detail->getProductClass();
135 50
                    if (is_null($ProductClass)) {
136 50
                        continue;
137 41
                    }
138
                    $deliveryDuration = $ProductClass->getDeliveryDuration();
139 50
                    if (is_null($deliveryDuration)) {
140 50
                        continue;
141 20
                    }
142
                    if ($deliveryDuration->getDuration() < 0) {
143 31
                        // 配送日数がマイナスの場合はお取り寄せなのでスキップする
144
                        $deliveryDurationFlag = false;
145 9
                        break;
146 9
                    }
147
148
                    if ($minDate < $deliveryDuration->getDuration()) {
149 26
                        $minDate = $deliveryDuration->getDuration();
150 21
                    }
151
                    // 配送日数が設定されている
152
                    $deliveryDurationFlag = true;
153 26
                }
154
155
                // 配達最大日数期間を設定
156
                $deliveryDurations = [];
157 50
158
                // 配送日数が設定されている
159
                if ($deliveryDurationFlag) {
160 50
                    $period = new \DatePeriod(
161 22
                        new \DateTime($minDate.' day'),
162 22
                        new \DateInterval('P1D'),
163 22
                        new \DateTime($minDate + $this->eccubeConfig['eccube_deliv_date_end_max'].' day')
164 22
                    );
165
166
                    // 曜日設定用
167
                    $dateFormatter = \IntlDateFormatter::create(
168 22
                        '[email protected]=japanese',
169 22
                        \IntlDateFormatter::FULL,
170 22
                        \IntlDateFormatter::FULL,
171 22
                        'Asia/Tokyo',
172 22
                        \IntlDateFormatter::TRADITIONAL,
173 22
                        'E'
174 22
                    );
175
176
                    foreach ($period as $day) {
177 22
                        $deliveryDurations[$day->format('Y/m/d')] = $day->format('Y/m/d').'('.$dateFormatter->format($day).')';
178 22
                    }
179
                }
180
181
                $form = $event->getForm();
182 50
                $form
183
                    ->add(
184 50
                        'shipping_delivery_date',
185 50
                        ChoiceType::class,
186 50
                        [
187
                            'choices' => array_flip($deliveryDurations),
188 50
                            'required' => false,
189
                            'placeholder' => 'common.select__unspecified',
190 50
                            'mapped' => false,
191
                            'data' => $Shipping->getShippingDeliveryDate() ? $Shipping->getShippingDeliveryDate()->format('Y/m/d') : null,
192 50
                        ]
193
                    );
194
            }
195 50
        );
196
        // お届け時間のプルダウンを生成
197
        $builder->addEventListener(
198 50
            FormEvents::PRE_SET_DATA,
199 50
            function (FormEvent $event) {
200 50
                /** @var Shipping $Shipping */
201 50
                $Shipping = $event->getData();
202 50
                if (is_null($Shipping) || !$Shipping->getId()) {
203
                    return;
204
                }
205
206 50
                $ShippingDeliveryTime = null;
207 50
                $DeliveryTimes = [];
208 50
                $Delivery = $Shipping->getDelivery();
209 50
                if ($Delivery) {
210 50
                    $DeliveryTimes = $Delivery->getDeliveryTimes();
211 50
                    $DeliveryTimes = $DeliveryTimes->filter(function (DeliveryTime $DeliveryTime) {
212 50
                        return $DeliveryTime->isVisible();
213 5
                    });
214 50
215
                    foreach ($DeliveryTimes as $deliveryTime) {
216
                        if ($deliveryTime->getId() == $Shipping->getTimeId()) {
217
                            $ShippingDeliveryTime = $deliveryTime;
218
                            break;
219 50
                        }
220 50
                    }
221 50
                }
222 50
223
                $form = $event->getForm();
224 50
                $form->add(
225 50
                    'DeliveryTime',
226 50
                    EntityType::class,
227 50
                    [
228
                        'label' => 'front.shopping.delivery_time',
229 50
                        'class' => 'Eccube\Entity\DeliveryTime',
230
                        'choice_label' => 'deliveryTime',
231 50
                        'choices' => $DeliveryTimes,
232
                        'required' => false,
233
                        'placeholder' => 'common.select__unspecified',
234 50
                        'mapped' => false,
235
                        'data' => $ShippingDeliveryTime,
236
                    ]
237
                );
238
            }
239 50
        );
240 25
241 25
        // POSTされないデータをエンティティにセットする.
242
        // TODO PurchaseFlow で行うのが適切.
243 25
        $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
244 25
            /** @var Shipping $Shipping */
245 25
            $Shipping = $event->getData();
246 25
            $form = $event->getForm();
247
            /** @var Delivery $Delivery */
248
            $Delivery = $form['Delivery']->getData();
249 25
            if ($Delivery) {
250 25
                $Shipping->setShippingDeliveryName($Delivery->getName());
251 25
            } else {
252
                $Shipping->setShippingDeliveryName(null);
253 25
            }
254 25
            $DeliveryDate = $form['shipping_delivery_date']->getData();
255 25
            if ($DeliveryDate) {
256
                $Shipping->setShippingDeliveryDate(new \DateTime($DeliveryDate));
257
            } else {
258 25
                $Shipping->setShippingDeliveryDate(null);
259
            }
260
261 25
            $DeliveryTime = $form['DeliveryTime']->getData();
262 25 View Code Duplication
            if ($DeliveryTime) {
263 20
                $Shipping->setShippingDeliveryTime($DeliveryTime->getDeliveryTime());
264 20
                $Shipping->setTimeId($DeliveryTime->getId());
265
            } else {
266 5
                $Shipping->setShippingDeliveryTime(null);
267 5
                $Shipping->setTimeId(null);
268
            }
269 50
        });
270
    }
271
272 50
    public function configureOptions(OptionsResolver $resolver)
273
    {
274 50
        $resolver->setDefaults(
275
            [
276 50
                'data_class' => 'Eccube\Entity\Shipping',
277
            ]
278
        );
279
    }
280
281 45
    public function getBlockPrefix()
282
    {
283 45
        return '_shopping_shipping';
284
    }
285
}
286