Completed
Push — 4.0 ( 87d096...bcc1be )
by Kiyotaka
05:44 queued 11s
created

Controller/Admin/Product/CsvImportController.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\Controller\Admin\Product;
15
16
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
17
use Eccube\Common\Constant;
18
use Eccube\Controller\Admin\AbstractCsvImportController;
19
use Eccube\Entity\BaseInfo;
20
use Eccube\Entity\Category;
21
use Eccube\Entity\Product;
22
use Eccube\Entity\ProductCategory;
23
use Eccube\Entity\ProductClass;
24
use Eccube\Entity\ProductImage;
25
use Eccube\Entity\ProductStock;
26
use Eccube\Entity\ProductTag;
27
use Eccube\Form\Type\Admin\CsvImportType;
28
use Eccube\Repository\BaseInfoRepository;
29
use Eccube\Repository\CategoryRepository;
30
use Eccube\Repository\ClassCategoryRepository;
31
use Eccube\Repository\DeliveryDurationRepository;
32
use Eccube\Repository\Master\ProductStatusRepository;
33
use Eccube\Repository\Master\SaleTypeRepository;
34
use Eccube\Repository\ProductRepository;
35
use Eccube\Repository\TagRepository;
36
use Eccube\Service\CsvImportService;
37
use Eccube\Util\CacheUtil;
38
use Eccube\Util\StringUtil;
39
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
40
use Symfony\Component\Filesystem\Filesystem;
41
use Symfony\Component\Form\FormInterface;
42
use Symfony\Component\HttpFoundation\Request;
43
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
44
use Symfony\Component\Routing\Annotation\Route;
45
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
46
use Symfony\Component\Validator\Validator\ValidatorInterface;
47
48
class CsvImportController extends AbstractCsvImportController
49
{
50
    /**
51
     * @var DeliveryDurationRepository
52
     */
53
    protected $deliveryDurationRepository;
54
55
    /**
56
     * @var SaleTypeRepository
57
     */
58
    protected $saleTypeRepository;
59
60
    /**
61
     * @var TagRepository
62
     */
63
    protected $tagRepository;
64
65
    /**
66
     * @var CategoryRepository
67
     */
68
    protected $categoryRepository;
69
70
    /**
71
     * @var ClassCategoryRepository
72
     */
73
    protected $classCategoryRepository;
74
75
    /**
76
     * @var ProductStatusRepository
77
     */
78
    protected $productStatusRepository;
79
80
    /**
81
     * @var ProductRepository
82
     */
83
    protected $productRepository;
84
85
    /**
86
     * @var BaseInfo
87
     */
88
    protected $BaseInfo;
89
90
    /**
91
     * @var ValidatorInterface
92
     */
93
    protected $validator;
94
95
    private $errors = [];
96
97
    /**
98
     * CsvImportController constructor.
99
     *
100
     * @param DeliveryDurationRepository $deliveryDurationRepository
101 16
     * @param SaleTypeRepository $saleTypeRepository
102
     * @param TagRepository $tagRepository
103 16
     * @param CategoryRepository $categoryRepository
104 16
     * @param ClassCategoryRepository $classCategoryRepository
105 16
     * @param ProductStatusRepository $productStatusRepository
106 16
     * @param ProductRepository $productRepository
107 16
     * @param BaseInfoRepository $baseInfoRepository
108 16
     * @param ValidatorInterface $validator
109 16
     *
110 16
     * @throws \Doctrine\ORM\NoResultException
111
     * @throws \Doctrine\ORM\NonUniqueResultException
112
     */
113 View Code Duplication
    public function __construct(
114
        DeliveryDurationRepository $deliveryDurationRepository,
115
        SaleTypeRepository $saleTypeRepository,
116
        TagRepository $tagRepository,
117
        CategoryRepository $categoryRepository,
118
        ClassCategoryRepository $classCategoryRepository,
119 10
        ProductStatusRepository $productStatusRepository,
120
        ProductRepository $productRepository,
121 10
        BaseInfoRepository $baseInfoRepository,
122 10
        ValidatorInterface $validator
123 10
    ) {
124 10
        $this->deliveryDurationRepository = $deliveryDurationRepository;
125 10
        $this->saleTypeRepository = $saleTypeRepository;
126 10
        $this->tagRepository = $tagRepository;
127 10
        $this->categoryRepository = $categoryRepository;
128 10
        $this->classCategoryRepository = $classCategoryRepository;
129 10
        $this->productStatusRepository = $productStatusRepository;
130 10
        $this->productRepository = $productRepository;
131
        $this->BaseInfo = $baseInfoRepository->get();
132
        $this->validator = $validator;
133
    }
134
135 10
    /**
136 10
     * 商品登録CSVアップロード
137 10
     *
138 10
     * @Route("/%eccube_admin_route%/product/product_csv_upload", name="admin_product_csv_import")
139 10
     * @Template("@admin/Product/csv_product.twig")
140 10
     */
141
    public function csvProduct(Request $request, CacheUtil $cacheUtil)
142 10
    {
143
        $form = $this->formFactory->createBuilder(CsvImportType::class)->getForm();
144 10
        $headers = $this->getProductCsvHeader();
145
        if ('POST' === $request->getMethod()) {
146
            $form->handleRequest($request);
147
            if ($form->isValid()) {
148
                $formFile = $form['import_file']->getData();
149
                if (!empty($formFile)) {
150 10
                    log_info('商品CSV登録開始');
151
                    $data = $this->getImportData($formFile);
152 10 View Code Duplication
                    if ($data === false) {
153
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
154
155
                        return $this->renderWithError($form, $headers, false);
156
                    }
157
                    $getId = function ($item) {
158 10
                        return $item['id'];
159 10
                    };
160
                    $requireHeader = array_keys(array_map($getId, array_filter($headers, function ($value) {
161 10
                        return $value['required'];
162 10
                    })));
163
164 10
                    $columnHeaders = $data->getColumnHeaders();
165 10
166 10 View Code Duplication
                    if (count(array_diff($requireHeader, $columnHeaders)) > 0) {
167
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
168
169
                        return $this->renderWithError($form, $headers, false);
170
                    }
171
172
                    $size = count($data);
173 10
174 7 View Code Duplication
                    if ($size < 1) {
175 7
                        $this->addErrors(trans('admin.common.csv_invalid_no_data'));
176
177 4
                        return $this->renderWithError($form, $headers, false);
178 3
                    }
179 3
180 1
                    $headerSize = count($columnHeaders);
181 1
                    $headerByKey = array_flip(array_map($getId, $headers));
182
                    $deleteImages = [];
183 3
184
                    $this->entityManager->getConfiguration()->setSQLLogger(null);
185
                    $this->entityManager->getConnection()->beginTransaction();
186 1
                    // CSVファイルの登録処理
187 1
                    foreach ($data as $row) {
188
                        $line = $data->key() + 1;
189 1
                        if ($headerSize != count($row)) {
190
                            $message = trans('admin.common.csv_invalid_format_line', ['%line%' => $line]);
191
                            $this->addErrors($message);
192
193 8
                            return $this->renderWithError($form, $headers);
194 1
                        }
195 1
196
                        if (!isset($row[$headerByKey['id']]) || StringUtil::isBlank($row[$headerByKey['id']])) {
197 7
                            $Product = new Product();
198 6
                            $this->entityManager->persist($Product);
199 6
                        } else {
200 1
                            if (preg_match('/^\d+$/', $row[$headerByKey['id']])) {
201 1
                                $Product = $this->productRepository->find($row[$headerByKey['id']]);
202
                                if (!$Product) {
203 6
                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['id']]);
204
                                    $this->addErrors($message);
205
206 1
                                    return $this->renderWithError($form, $headers);
207 1
                                }
208
                            } else {
209
                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['id']]);
210
                                $this->addErrors($message);
211 8
212
                                return $this->renderWithError($form, $headers);
213
                            }
214
215
                            if (isset($row[$headerByKey['product_del_flg']])) {
216
                                if (StringUtil::isNotBlank($row[$headerByKey['product_del_flg']]) && $row[$headerByKey['product_del_flg']] == (string) Constant::ENABLED) {
217 8
                                    // 商品を物理削除
218
                                    $deleteImages[] = $Product->getProductImage();
219
220 8
                                    try {
221 3
                                        $this->productRepository->delete($Product);
222
                                        $this->entityManager->flush();
223 5
224
                                        continue;
225
                                    } catch (ForeignKeyConstraintViolationException $e) {
226 8
                                        $message = trans('admin.common.csv_invalid_foreign_key', ['%line%' => $line, '%name%' => $Product->getName()]);
227 4
                                        $this->addErrors($message);
228
229 5
                                        return $this->renderWithError($form, $headers);
230
                                    }
231
                                }
232 8
                            }
233 4
                        }
234
235 4
                        if (StringUtil::isBlank($row[$headerByKey['status']])) {
236
                            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['status']]);
237
                            $this->addErrors($message);
238 8
                        } else {
239 3
                            if (preg_match('/^\d+$/', $row[$headerByKey['status']])) {
240
                                $ProductStatus = $this->productStatusRepository->find($row[$headerByKey['status']]);
241 5
                                if (!$ProductStatus) {
242
                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['status']]);
243
                                    $this->addErrors($message);
244 8
                                } else {
245 3
                                    $Product->setStatus($ProductStatus);
246
                                }
247 5
                            } else {
248
                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['status']]);
249
                                $this->addErrors($message);
250
                            }
251 8
                        }
252
253 8
                        if (StringUtil::isBlank($row[$headerByKey['name']])) {
254
                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['name']]);
255
                            $this->addErrors($message);
256 8
257
                            return $this->renderWithError($form, $headers);
258
                        } else {
259 8
                            $Product->setName(StringUtil::trimAll($row[$headerByKey['name']]));
260
                        }
261
262 View Code Duplication
                        if (isset($row[$headerByKey['note']]) && StringUtil::isNotBlank($row[$headerByKey['note']])) {
263 8
                            $Product->setNote(StringUtil::trimAll($row[$headerByKey['note']]));
264 8
                        } else {
265
                            $Product->setNote(null);
266 7
                        }
267 7
268 View Code Duplication
                        if (isset($row[$headerByKey['description_list']]) && StringUtil::isNotBlank($row[$headerByKey['description_list']])) {
269
                            $Product->setDescriptionList(StringUtil::trimAll($row[$headerByKey['description_list']]));
270
                        } else {
271
                            $Product->setDescriptionList(null);
272
                        }
273
274 View Code Duplication
                        if (isset($row[$headerByKey['description_detail']]) && StringUtil::isNotBlank($row[$headerByKey['description_detail']])) {
275
                            $Product->setDescriptionDetail(StringUtil::trimAll($row[$headerByKey['description_detail']]));
276
                        } else {
277
                            $Product->setDescriptionDetail(null);
278
                        }
279 7
280 2 View Code Duplication
                        if (isset($row[$headerByKey['search_word']]) && StringUtil::isNotBlank($row[$headerByKey['search_word']])) {
281
                            $Product->setSearchWord(StringUtil::trimAll($row[$headerByKey['search_word']]));
282
                        } else {
283
                            $Product->setSearchWord(null);
284
                        }
285
286 View Code Duplication
                        if (isset($row[$headerByKey['free_area']]) && StringUtil::isNotBlank($row[$headerByKey['free_area']])) {
287
                            $Product->setFreeArea(StringUtil::trimAll($row[$headerByKey['free_area']]));
288
                        } else {
289
                            $Product->setFreeArea(null);
290 2
                        }
291 2
292
                        // 商品画像登録
293
                        $this->createProductImage($row, $Product, $data, $headerByKey);
294 2
295
                        $this->entityManager->flush();
296
297 2
                        // 商品カテゴリ登録
298 2
                        $this->createProductCategory($row, $Product, $data, $headerByKey);
299 2
300 2
                        //タグ登録
301
                        $this->createProductTag($row, $Product, $data, $headerByKey);
302
303
                        // 商品規格が存在しなければ新規登録
304 2
                        /** @var ProductClass[] $ProductClasses */
305
                        $ProductClasses = $Product->getProductClasses();
306
                        if ($ProductClasses->count() < 1) {
307
                            // 規格分類1(ID)がセットされていると規格なし商品、規格あり商品を作成
308
                            $ProductClassOrg = $this->createProductClass($row, $Product, $data, $headerByKey);
309 View Code Duplication
                            if ($this->BaseInfo->isOptionProductDeliveryFee()) {
310
                                if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
311 2
                                    $deliveryFee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
312 2
                                    $errors = $this->validator->validate($deliveryFee, new GreaterThanOrEqual(['value' => 0]));
313 2
                                    if ($errors->count() === 0) {
314 2
                                        $ProductClassOrg->setDeliveryFee($deliveryFee);
315
                                    } else {
316
                                        $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
317
                                        $this->addErrors($message);
318 2
                                    }
319 2
                                }
320
                            }
321
322
                            if (isset($row[$headerByKey['class_category1']]) && StringUtil::isNotBlank($row[$headerByKey['class_category1']])) {
323
                                if (isset($row[$headerByKey['class_category2']]) && $row[$headerByKey['class_category1']] == $row[$headerByKey['class_category2']]) {
324 2
                                    $message = trans('admin.common.csv_invalid_not_same', [
325
                                        '%line%' => $line,
326
                                        '%name1%' => $headerByKey['class_category1'],
327
                                        '%name2%' => $headerByKey['class_category2'],
328
                                    ]);
329
                                    $this->addErrors($message);
330
                                } else {
331
                                    // 商品規格あり
332 2
                                    // 規格分類あり商品を作成
333 2
                                    $ProductClass = clone $ProductClassOrg;
334
                                    $ProductStock = clone $ProductClassOrg->getProductStock();
335 2
336 2
                                    // 規格分類1、規格分類2がnullであるデータを非表示
337
                                    $ProductClassOrg->setVisible(false);
338
339 5
                                    // 規格分類1、2をそれぞれセットし作成
340
                                    $ClassCategory1 = null;
341 7
                                    if (preg_match('/^\d+$/', $row[$headerByKey['class_category1']])) {
342
                                        $ClassCategory1 = $this->classCategoryRepository->find($row[$headerByKey['class_category1']]);
343
                                        if (!$ClassCategory1) {
344
                                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
345
                                            $this->addErrors($message);
346 2
                                        } else {
347 2
                                            $ProductClass->setClassCategory1($ClassCategory1);
348 2
                                        }
349
                                    } else {
350 2
                                        $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
351 2
                                        $this->addErrors($message);
352 2
                                    }
353
354
                                    if (isset($row[$headerByKey['class_category2']]) && StringUtil::isNotBlank($row[$headerByKey['class_category2']])) {
355 2
                                        if (preg_match('/^\d+$/', $row[$headerByKey['class_category2']])) {
356 2
                                            $ClassCategory2 = $this->classCategoryRepository->find($row[$headerByKey['class_category2']]);
357 View Code Duplication
                                            if (!$ClassCategory2) {
358 1
                                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
359
                                                $this->addErrors($message);
360 1
                                            } else {
361
                                                if ($ClassCategory1 &&
362
                                                    ($ClassCategory1->getClassName()->getId() == $ClassCategory2->getClassName()->getId())
363
                                                ) {
364
                                                    $message = trans('admin.common.csv_invalid_not_same', ['%line%' => $line, '%name1%' => $headerByKey['class_category1'], '%name2%' => $headerByKey['class_category2']]);
365
                                                    $this->addErrors($message);
366
                                                } else {
367
                                                    $ProductClass->setClassCategory2($ClassCategory2);
368
                                                }
369
                                            }
370
                                        } else {
371
                                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
372 1
                                            $this->addErrors($message);
373 2
                                        }
374
                                    }
375
                                    $ProductClass->setProductStock($ProductStock);
376
                                    $ProductStock->setProductClass($ProductClass);
377
378 2
                                    $this->entityManager->persist($ProductClass);
379 1
                                    $this->entityManager->persist($ProductStock);
380 1
                                }
381 1
                            } else {
382
                                if (isset($row[$headerByKey['class_category2']]) && StringUtil::isNotBlank($row[$headerByKey['class_category2']])) {
383
                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
384 1
                                    $this->addErrors($message);
385
                                }
386
                            }
387 1
                        } else {
388 1
                            // 商品規格の更新
389
                            $flag = false;
390
                            $classCategoryId1 = StringUtil::isBlank($row[$headerByKey['class_category1']]) ? null : $row[$headerByKey['class_category1']];
391
                            $classCategoryId2 = StringUtil::isBlank($row[$headerByKey['class_category2']]) ? null : $row[$headerByKey['class_category2']];
392
393
                            foreach ($ProductClasses as $pc) {
394
                                $classCategory1 = is_null($pc->getClassCategory1()) ? null : $pc->getClassCategory1()->getId();
395
                                $classCategory2 = is_null($pc->getClassCategory2()) ? null : $pc->getClassCategory2()->getId();
396
397
                                // 登録されている商品規格を更新
398 1
                                if ($classCategory1 == $classCategoryId1 &&
399 1
                                    $classCategory2 == $classCategoryId2
400 1
                                ) {
401 1
                                    $this->updateProductClass($row, $Product, $pc, $data, $headerByKey);
402
403 1 View Code Duplication
                                    if ($this->BaseInfo->isOptionProductDeliveryFee()) {
404
                                        if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
405
                                            $deliveryFee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
406
                                            $errors = $this->validator->validate($deliveryFee, new GreaterThanOrEqual(['value' => 0]));
407
                                            if ($errors->count() === 0) {
408
                                                $pc->setDeliveryFee($deliveryFee);
409
                                            } else {
410 1
                                                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
411 1
                                                $this->addErrors($message);
412 1
                                            }
413
                                        }
414
                                    }
415
                                    $flag = true;
416 1
                                    break;
417 1
                                }
418 1
                            }
419
420
                            // 商品規格を登録
421
                            if (!$flag) {
422 1
                                $pc = $ProductClasses[0];
423 1
                                if ($pc->getClassCategory1() == null &&
424
                                    $pc->getClassCategory2() == null
425
                                ) {
426
                                    // 規格分類1、規格分類2がnullであるデータを非表示
427
                                    $pc->setVisible(false);
428
                                }
429
430 1
                                if (isset($row[$headerByKey['class_category1']]) && isset($row[$headerByKey['class_category2']])
431
                                    && $row[$headerByKey['class_category1']] == $row[$headerByKey['class_category2']]) {
432
                                    $message = trans('admin.common.csv_invalid_not_same', [
433
                                        '%line%' => $line,
434
                                        '%name1%' => $headerByKey['class_category1'],
435 1
                                        '%name2%' => $headerByKey['class_category2'],
436
                                    ]);
437
                                    $this->addErrors($message);
438
                                } else {
439
                                    // 必ず規格分類1がセットされている
440
                                    // 規格分類1、2をそれぞれセットし作成
441
                                    $ClassCategory1 = null;
442
                                    if (preg_match('/^\d+$/', $classCategoryId1)) {
443
                                        $ClassCategory1 = $this->classCategoryRepository->find($classCategoryId1);
444 1
                                        if (!$ClassCategory1) {
445
                                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
446 1
                                            $this->addErrors($message);
447
                                        }
448
                                    } else {
449
                                        $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
450
                                        $this->addErrors($message);
451
                                    }
452
453
                                    $ClassCategory2 = null;
454
                                    if (isset($row[$headerByKey['class_category2']]) && StringUtil::isNotBlank($row[$headerByKey['class_category2']])) {
455
                                        if ($pc->getClassCategory1() != null && $pc->getClassCategory2() == null) {
456
                                            $message = trans('admin.common.csv_invalid_can_not', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
457 1
                                            $this->addErrors($message);
458
                                        } else {
459
                                            if (preg_match('/^\d+$/', $classCategoryId2)) {
460
                                                $ClassCategory2 = $this->classCategoryRepository->find($classCategoryId2);
461 8 View Code Duplication
                                                if (!$ClassCategory2) {
462 3
                                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
463
                                                    $this->addErrors($message);
464 5
                                                } else {
465
                                                    if ($ClassCategory1 &&
466 5
                                                        ($ClassCategory1->getClassName()->getId() == $ClassCategory2->getClassName()->getId())
467 5
                                                    ) {
468 5
                                                        $message = trans('admin.common.csv_invalid_not_same', [
469 5
                                                            '%line%' => $line,
470 5
                                                            '%name1%' => $headerByKey['class_category1'],
471
                                                            '%name2%' => $headerByKey['class_category2'],
472
                                                        ]);
473
                                                        $this->addErrors($message);
474
                                                    }
475 5
                                                }
476
                                            } else {
477
                                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
478
                                                $this->addErrors($message);
479
                                            }
480
                                        }
481
                                    } else {
482
                                        if ($pc->getClassCategory1() != null && $pc->getClassCategory2() != null) {
483
                                            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
484 6
                                            $this->addErrors($message);
485
                                        }
486 6
                                    }
487
                                    $ProductClass = $this->createProductClass($row, $Product, $data, $headerByKey, $ClassCategory1, $ClassCategory2);
488 6
489 6 View Code Duplication
                                    if ($this->BaseInfo->isOptionProductDeliveryFee()) {
490 6
                                        if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
491 6
                                            $deliveryFee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
492 6
                                            $errors = $this->validator->validate($deliveryFee, new GreaterThanOrEqual(['value' => 0]));
493 6
                                            if ($errors->count() === 0) {
494 6
                                                $ProductClass->setDeliveryFee($deliveryFee);
495 6
                                            } else {
496 6
                                                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
497
                                                $this->addErrors($message);
498
                                            }
499
                                        }
500
                                    }
501
                                    $Product->addProductClass($ProductClass);
502
                                }
503
                            }
504
                        }
505 6
                        if ($this->hasErrors()) {
506
                            return $this->renderWithError($form, $headers);
507 6
                        }
508 6
                        $this->entityManager->persist($Product);
509 1
                    }
510
                    $this->entityManager->flush();
511 1
                    $this->entityManager->getConnection()->commit();
512
513
                    // 画像ファイルの削除(commit後に削除させる)
514 5 View Code Duplication
                    foreach ($deleteImages as $images) {
515 5
                        foreach ($images as $image) {
516
                            try {
517
                                $fs = new Filesystem();
518
                                $fs->remove($this->eccubeConfig['eccube_save_image_dir'].'/'.$image);
519
                            } catch (\Exception $e) {
520 5
                                // エラーが発生しても無視する
521 5
                            }
522
                        }
523 5
                    }
524
525 5
                    log_info('商品CSV登録完了');
526 5
                    $message = 'admin.common.csv_upload_complete';
527 1
                    $this->session->getFlashBag()->add('eccube.admin.success', $message);
528
529
                    $cacheUtil->clearDoctrineCache();
530
                }
531
            }
532 1
        }
533 1
534
        return $this->renderWithError($form, $headers);
535
    }
536
537
    /**
538 1
     * カテゴリ登録CSVアップロード
539
     *
540
     * @Route("/%eccube_admin_route%/product/category_csv_upload", name="admin_product_category_csv_import")
541
     * @Template("@admin/Product/csv_category.twig")
542
     */
543
    public function csvCategory(Request $request, CacheUtil $cacheUtil)
544
    {
545 5
        $form = $this->formFactory->createBuilder(CsvImportType::class)->getForm();
546 1
547
        $headers = $this->getCategoryCsvHeader();
548
        if ('POST' === $request->getMethod()) {
549
            $form->handleRequest($request);
550
            if ($form->isValid()) {
551
                $formFile = $form['import_file']->getData();
552
                if (!empty($formFile)) {
553
                    log_info('カテゴリCSV登録開始');
554
                    $data = $this->getImportData($formFile);
555 View Code Duplication
                    if ($data === false) {
556
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
557
558
                        return $this->renderWithError($form, $headers, false);
559
                    }
560
561
                    $getId = function ($item) {
562
                        return $item['id'];
563
                    };
564
                    $requireHeader = array_keys(array_map($getId, array_filter($headers, function ($value) {
565 5
                        return $value['required'];
566 1
                    })));
567
568 1
                    $headerByKey = array_flip(array_map($getId, $headers));
569
570 4
                    $columnHeaders = $data->getColumnHeaders();
571 View Code Duplication
                    if (count(array_diff($requireHeader, $columnHeaders)) > 0) {
572
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
573 4
574 4
                        return $this->renderWithError($form, $headers, false);
575 1
                    }
576
577
                    $size = count($data);
578 View Code Duplication
                    if ($size < 1) {
579
                        $this->addErrors(trans('admin.common.csv_invalid_no_data'));
580
581
                        return $this->renderWithError($form, $headers, false);
582 1
                    }
583 1
                    $this->entityManager->getConfiguration()->setSQLLogger(null);
584
                    $this->entityManager->getConnection()->beginTransaction();
585
                    // CSVファイルの登録処理
586
                    foreach ($data as $row) {
587
                        /** @var $Category Category */
588
                        $Category = new Category();
589 4
                        if (isset($row[$headerByKey['id']]) && strlen($row[$headerByKey['id']]) > 0) {
590 View Code Duplication
                            if (!preg_match('/^\d+$/', $row[$headerByKey['id']])) {
591
                                $this->addErrors(($data->key() + 1).'行目のカテゴリIDが存在しません。');
592 4
593
                                return $this->renderWithError($form, $headers);
594
                            }
595
                            $Category = $this->categoryRepository->find($row[$headerByKey['id']]);
596
                            if (!$Category) {
597
                                $this->addErrors(($data->key() + 1).'行目のカテゴリIDが存在しません。');
598
599
                                return $this->renderWithError($form, $headers);
600 4
                            }
601 4
                            if ($row[$headerByKey['id']] == $row[$headerByKey['parent_category_id']]) {
602 1
                                $this->addErrors(($data->key() + 1).'行目のカテゴリIDと親カテゴリIDが同じです。');
603
604
                                return $this->renderWithError($form, $headers);
605
                            }
606 4
                        }
607
608 4
                        if (isset($row[$headerByKey['category_del_flg']]) && StringUtil::isNotBlank($row[$headerByKey['category_del_flg']])) {
609
                            if (StringUtil::trimAll($row[$headerByKey['category_del_flg']]) == 1) {
610
                                if ($Category->getId()) {
611
                                    log_info('カテゴリ削除開始', [$Category->getId()]);
612
                                    try {
613
                                        $this->categoryRepository->delete($Category);
614 4
                                        log_info('カテゴリ削除完了', [$Category->getId()]);
615
                                    } catch (ForeignKeyConstraintViolationException $e) {
616
                                        log_info('カテゴリ削除エラー', [$Category->getId(), $e]);
617 4
                                        $message = trans('admin.common.delete_error_foreign_key', ['%name%' => $Category->getName()]);
618 4
                                        $this->addError($message, 'admin');
619
620
                                        return $this->renderWithError($form, $headers);
621 4
                                    }
622 4
                                }
623 4
624 4
                                continue;
625
                            }
626
                        }
627
628
                        if (!isset($row[$headerByKey['category_name']]) || StringUtil::isBlank($row[$headerByKey['category_name']])) {
629 4
                            $this->addErrors(($data->key() + 1).'行目のカテゴリ名が設定されていません。');
630
631
                            return $this->renderWithError($form, $headers);
632
                        } else {
633
                            $Category->setName(StringUtil::trimAll($row[$headerByKey['category_name']]));
634
                        }
635
636
                        $ParentCategory = null;
637
                        if (isset($row[$headerByKey['parent_category_id']]) && StringUtil::isNotBlank($row[$headerByKey['parent_category_id']])) {
638 View Code Duplication
                            if (!preg_match('/^\d+$/', $row[$headerByKey['parent_category_id']])) {
639
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
640
641
                                return $this->renderWithError($form, $headers);
642
                            }
643
644
                            /** @var $ParentCategory Category */
645
                            $ParentCategory = $this->categoryRepository->find($row[$headerByKey['parent_category_id']]);
646
                            if (!$ParentCategory) {
647
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
648
649
                                return $this->renderWithError($form, $headers);
650
                            }
651
                        }
652
                        $Category->setParent($ParentCategory);
653
654
                        // Level
655
                        if (isset($row['階層']) && StringUtil::isNotBlank($row['階層'])) {
656 View Code Duplication
                            if ($ParentCategory == null && $row['階層'] != 1) {
657
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
658
659
                                return $this->renderWithError($form, $headers);
660
                            }
661
                            $level = StringUtil::trimAll($row['階層']);
662
                        } else {
663 16
                            $level = 1;
664
                            if ($ParentCategory) {
665 16
                                $level = $ParentCategory->getHierarchy() + 1;
666 7
                            }
667 6
                        }
668
669
                        $Category->setHierarchy($level);
670
671 16
                        if ($this->eccubeConfig['eccube_category_nest_level'] < $Category->getHierarchy()) {
672
                            $this->addErrors(($data->key() + 1).'行目のカテゴリが最大レベルを超えているため設定できません。');
673
674 16
                            return $this->renderWithError($form, $headers);
675 16
                        }
676 16
677
                        if ($this->hasErrors()) {
678
                            return $this->renderWithError($form, $headers);
679
                        }
680
                        $this->entityManager->persist($Category);
681
                        $this->categoryRepository->save($Category);
682
                    }
683
684
                    $this->entityManager->getConnection()->commit();
685
                    log_info('カテゴリCSV登録完了');
686
                    $message = 'admin.common.csv_upload_complete';
687 8
                    $this->session->getFlashBag()->add('eccube.admin.success', $message);
688
689 8
                    $cacheUtil->clearDoctrineCache();
690
                }
691 4
            }
692 4
        }
693 2
694 2
        return $this->renderWithError($form, $headers);
695
    }
696
697
    /**
698 4
     * アップロード用CSV雛形ファイルダウンロード
699
     *
700 4
     * @Route("/%eccube_admin_route%/product/csv_template/{type}", requirements={"type" = "\w+"}, name="admin_product_csv_template")
701
     */
702 4
    public function csvTemplate(Request $request, $type)
703 4
    {
704 4
        if ($type == 'product') {
705
            $headers = $this->getProductCsvHeader();
706
            $filename = 'product.csv';
707 4
        } elseif ($type == 'category') {
708
            $headers = $this->getCategoryCsvHeader();
709
            $filename = 'category.csv';
710
        } else {
711
            throw new NotFoundHttpException();
712 4
        }
713 4
714 4
        return $this->sendTemplateResponse($request, array_keys($headers), $filename);
715 4
    }
716 4
717
    /**
718 4
     * 登録、更新時のエラー画面表示
719 4
     *
720 4
     * @param FormInterface $form
721
     * @param array $headers
722
     * @param bool $rollback
723
     *
724
     * @return array
725
     *
726
     * @throws \Doctrine\DBAL\ConnectionException
727
     */
728
    protected function renderWithError($form, $headers, $rollback = true)
729
    {
730
        if ($this->hasErrors()) {
731
            if ($rollback) {
732
                $this->entityManager->getConnection()->rollback();
733
            }
734
        }
735 8
736
        $this->removeUploadedFile();
737
738 8
        return [
739 8
            'form' => $form->createView(),
740 2
            'headers' => $headers,
741 2
            'errors' => $this->errors,
742 2
        ];
743
    }
744
745 8
    /**
746
     * 商品画像の削除、登録
747 4
     *
748 4
     * @param $row
749 4
     * @param Product $Product
750 4
     * @param CsvImportService $data
751 4
     */
752 4
    protected function createProductImage($row, Product $Product, $data, $headerByKey)
753 4
    {
754 4
        if (isset($row[$headerByKey['product_image']]) && StringUtil::isNotBlank($row[$headerByKey['product_image']])) {
755
            // 画像の削除
756
            $ProductImages = $Product->getProductImage();
757
            foreach ($ProductImages as $ProductImage) {
758
                $Product->removeProductImage($ProductImage);
759
                $this->entityManager->remove($ProductImage);
760
            }
761
762 4
            // 画像の登録
763 4
            $images = explode(',', $row[$headerByKey['product_image']]);
764 4
765 4
            $sortNo = 1;
766 4
767
            $pattern = "/\\$|^.*.\.\\\.*|\/$|^.*.\.\/\.*/";
768 4
            foreach ($images as $image) {
769 4
                $fileName = StringUtil::trimAll($image);
770
771
                // 商品画像名のフォーマットチェック
772 4
                if (strlen($fileName) > 0 && preg_match($pattern, $fileName)) {
773
                    $message = trans('admin.common.csv_invalid_image', ['%line%' => $data->key() + 1, '%name%' => $headerByKey['product_image']]);
774
                    $this->addErrors($message);
775
                } else {
776
                    // 空文字は登録対象外
777
                    if (!empty($fileName)) {
778
                        $ProductImage = new ProductImage();
779
                        $ProductImage->setFileName($fileName);
780
                        $ProductImage->setProduct($Product);
781 4
                        $ProductImage->setSortNo($sortNo);
782
783
                        $Product->addProductImage($ProductImage);
784
                        $sortNo++;
785
                        $this->entityManager->persist($ProductImage);
786 4
                    }
787
                }
788
            }
789
        }
790
    }
791
792
    /**
793
     * 商品カテゴリの削除、登録
794 4
     *
795
     * @param $row
796
     * @param Product $Product
797
     * @param CsvImportService $data
798
     * @param $headerByKey
799
     */
800
    protected function createProductCategory($row, Product $Product, $data, $headerByKey)
801
    {
802
        // カテゴリの削除
803
        $ProductCategories = $Product->getProductCategories();
804
        foreach ($ProductCategories as $ProductCategory) {
805
            $Product->removeProductCategory($ProductCategory);
806
            $this->entityManager->remove($ProductCategory);
807 8
            $this->entityManager->flush();
808
        }
809
810 8
        if (isset($row[$headerByKey['product_category']]) && StringUtil::isNotBlank($row[$headerByKey['product_category']])) {
811 8
            // カテゴリの登録
812 1
            $categories = explode(',', $row[$headerByKey['product_category']]);
813 1
            $sortNo = 1;
814
            $categoriesIdList = [];
815
            foreach ($categories as $category) {
816 8
                $line = $data->key() + 1;
817
                if (preg_match('/^\d+$/', $category)) {
818 4
                    $Category = $this->categoryRepository->find($category);
819 4
                    if (!$Category) {
820 4
                        $message = trans('admin.common.csv_invalid_not_found_target', [
821 4
                            '%line%' => $line,
822 4
                            '%name%' => $headerByKey['product_category'],
823
                            '%target_name%' => $category,
824 4
                        ]);
825 4
                        $this->addErrors($message);
826
                    } else {
827 4 View Code Duplication
                        foreach ($Category->getPath() as $ParentCategory) {
828 4
                            if (!isset($categoriesIdList[$ParentCategory->getId()])) {
829
                                $ProductCategory = $this->makeProductCategory($Product, $ParentCategory, $sortNo);
830 4
                                $this->entityManager->persist($ProductCategory);
831
                                $sortNo++;
832 4
833
                                $Product->addProductCategory($ProductCategory);
834
                                $categoriesIdList[$ParentCategory->getId()] = true;
835 4
                            }
836
                        }
837
                        if (!isset($categoriesIdList[$Category->getId()])) {
838
                            $ProductCategory = $this->makeProductCategory($Product, $Category, $sortNo);
839
                            $sortNo++;
840
                            $this->entityManager->persist($ProductCategory);
841 4
                            $Product->addProductCategory($ProductCategory);
842
                            $categoriesIdList[$Category->getId()] = true;
843
                        }
844
                    }
845 View Code Duplication
                } else {
846
                    $message = trans('admin.common.csv_invalid_not_found_target', [
847
                        '%line%' => $line,
848
                        '%name%' => $headerByKey['product_category'],
849
                        '%target_name%' => $category,
850
                    ]);
851
                    $this->addErrors($message);
852
                }
853
            }
854
        }
855
    }
856
857
    /**
858
     * タグの登録
859 8
     *
860
     * @param array $row
861
     * @param Product $Product
862 8
     * @param CsvImportService $data
863 8
     */
864 8
    protected function createProductTag($row, Product $Product, $data, $headerByKey)
865
    {
866 8
        // タグの削除
867 8
        $ProductTags = $Product->getProductTag();
868 8
        foreach ($ProductTags as $ProductTag) {
869 8
            $Product->removeProductTag($ProductTag);
870 8
            $this->entityManager->remove($ProductTag);
871
        }
872
873
        if (isset($row[$headerByKey['product_tag']]) && StringUtil::isNotBlank($row[$headerByKey['product_tag']])) {
874 8
            // タグの登録
875
            $tags = explode(',', $row[$headerByKey['product_tag']]);
876
            foreach ($tags as $tag_id) {
877
                $Tag = null;
878 8
                if (preg_match('/^\d+$/', $tag_id)) {
879
                    $Tag = $this->tagRepository->find($tag_id);
880
881
                    if ($Tag) {
882
                        $ProductTags = new ProductTag();
883
                        $ProductTags
884
                            ->setProduct($Product)
885 8
                            ->setTag($Tag);
886 8
887
                        $Product->addProductTag($ProductTags);
888 8
889 3
                        $this->entityManager->persist($ProductTags);
890 3
                    }
891 3
                }
892 View Code Duplication
                if (!$Tag) {
893
                    $message = trans('admin.common.csv_invalid_not_found_target', [
894
                        '%line%' => $data->key() + 1,
895 3
                        '%name%' => $headerByKey['product_tag'],
896
                        '%target_name%' => $tag_id,
897
                    ]);
898
                    $this->addErrors($message);
899
                }
900
            }
901
        }
902
    }
903 8
904 3
    /**
905
     * 商品規格分類1、商品規格分類2がnullとなる商品規格情報を作成
906 5
     *
907
     * @param $row
908
     * @param Product $Product
909 8
     * @param CsvImportService $data
910
     * @param $headerByKey
911
     * @param null $ClassCategory1
912
     * @param null $ClassCategory2
913 8
     *
914 4
     * @return ProductClass
915
     */
916 4
    protected function createProductClass($row, Product $Product, $data, $headerByKey, $ClassCategory1 = null, $ClassCategory2 = null)
917 4
    {
918 4
        // 規格分類1、規格分類2がnullとなる商品を作成
919 4
        $ProductClass = new ProductClass();
920
        $ProductClass->setProduct($Product);
921
        $ProductClass->setVisible(true);
922 4
923
        $line = $data->key() + 1;
924
        if (isset($row[$headerByKey['sale_type']]) && StringUtil::isNotBlank($row[$headerByKey['sale_type']])) {
925
            if (preg_match('/^\d+$/', $row[$headerByKey['sale_type']])) {
926 4
                $SaleType = $this->saleTypeRepository->find($row[$headerByKey['sale_type']]);
927
                if (!$SaleType) {
928 4
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
929 4
                    $this->addErrors($message);
930 4
                } else {
931
                    $ProductClass->setSaleType($SaleType);
932
                }
933
            } else {
934
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
935
                $this->addErrors($message);
936
            }
937 8
        } else {
938
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
939
            $this->addErrors($message);
940
        }
941
942
        $ProductClass->setClassCategory1($ClassCategory1);
943
        $ProductClass->setClassCategory2($ClassCategory2);
944
945
        if (isset($row[$headerByKey['delivery_date']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_date']])) {
946
            if (preg_match('/^\d+$/', $row[$headerByKey['delivery_date']])) {
947 8
                $DeliveryDuration = $this->deliveryDurationRepository->find($row[$headerByKey['delivery_date']]);
948 3
                if (!$DeliveryDuration) {
949 3
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
950 3
                    $this->addErrors($message);
951
                } else {
952
                    $ProductClass->setDeliveryDuration($DeliveryDuration);
953
                }
954
            } else {
955
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
956
                $this->addErrors($message);
957 8
            }
958 8
        }
959 8
960 8 View Code Duplication
        if (isset($row[$headerByKey['product_code']]) && StringUtil::isNotBlank($row[$headerByKey['product_code']])) {
961
            $ProductClass->setCode(StringUtil::trimAll($row[$headerByKey['product_code']]));
962
        } else {
963 8
            $ProductClass->setCode(null);
964
        }
965
966 View Code Duplication
        if (!isset($row[$headerByKey['stock_unlimited']])
967
            || StringUtil::isBlank($row[$headerByKey['stock_unlimited']])
968
            || $row[$headerByKey['stock_unlimited']] == (string) Constant::DISABLED
969
        ) {
970 8
            $ProductClass->setStockUnlimited(false);
971 3
            // 在庫数が設定されていなければエラー
972 3
            if (isset($row[$headerByKey['stock']]) && StringUtil::isNotBlank($row[$headerByKey['stock']])) {
973 3
                $stock = str_replace(',', '', $row[$headerByKey['stock']]);
974
                if (preg_match('/^\d+$/', $stock) && $stock >= 0) {
975
                    $ProductClass->setStock($stock);
976
                } else {
977
                    $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
978
                    $this->addErrors($message);
979
                }
980 8
            } else {
981 8
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
982 8
                $this->addErrors($message);
983 8
            }
984
        } elseif ($row[$headerByKey['stock_unlimited']] == (string) Constant::ENABLED) {
985 8
            $ProductClass->setStockUnlimited(true);
986 4
            $ProductClass->setStock(null);
987
        } else {
988
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock_unlimited']]);
989 4
            $this->addErrors($message);
990
        }
991
992 8
        if (isset($row[$headerByKey['sale_limit']]) && StringUtil::isNotBlank($row[$headerByKey['sale_limit']])) {
993 8
            $saleLimit = str_replace(',', '', $row[$headerByKey['sale_limit']]);
994
            if (preg_match('/^\d+$/', $saleLimit) && $saleLimit >= 0) {
995 8
                $ProductClass->setSaleLimit($saleLimit);
996
            } else {
997
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['sale_limit']]);
998
                $this->addErrors($message);
999
            }
1000
        }
1001
1002
        if (isset($row[$headerByKey['price01']]) && StringUtil::isNotBlank($row[$headerByKey['price01']])) {
1003
            $price01 = str_replace(',', '', $row[$headerByKey['price01']]);
1004
            $errors = $this->validator->validate($price01, new GreaterThanOrEqual(['value' => 0]));
1005
            if ($errors->count() === 0) {
1006
                $ProductClass->setPrice01($price01);
1007
            } else {
1008 1
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price01']]);
1009
                $this->addErrors($message);
1010 1
            }
1011
        }
1012 1
1013 1
        if (isset($row[$headerByKey['price02']]) && StringUtil::isNotBlank($row[$headerByKey['price02']])) {
1014
            $price02 = str_replace(',', '', $row[$headerByKey['price02']]);
1015
            $errors = $this->validator->validate($price02, new GreaterThanOrEqual(['value' => 0]));
1016
            if ($errors->count() === 0) {
1017 1
                $ProductClass->setPrice02($price02);
1018 1
            } else {
1019 1
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1020
                $this->addErrors($message);
1021
            }
1022
        } else {
1023 1
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1024
            $this->addErrors($message);
1025
        }
1026
1027 View Code Duplication
        if ($this->BaseInfo->isOptionProductDeliveryFee()) {
1028
            if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
1029
                $delivery_fee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
1030
                $errors = $this->validator->validate($delivery_fee, new GreaterThanOrEqual(['value' => 0]));
1031
                if ($errors->count() === 0) {
1032 1
                    $ProductClass->setDeliveryFee($delivery_fee);
1033 1
                } else {
1034 1
                    $message = trans('admin.common.csv_invalid_greater_than_zero',
1035 1
                        ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
1036
                    $this->addErrors($message);
1037
                }
1038
            }
1039 1
        }
1040
1041
        $Product->addProductClass($ProductClass);
1042
        $ProductStock = new ProductStock();
1043
        $ProductClass->setProductStock($ProductStock);
1044
        $ProductStock->setProductClass($ProductClass);
1045
1046
        if (!$ProductClass->isStockUnlimited()) {
1047 1
            $ProductStock->setStock($ProductClass->getStock());
1048 1
        } else {
1049 1
            // 在庫無制限時はnullを設定
1050 1
            $ProductStock->setStock(null);
1051
        }
1052
1053
        $this->entityManager->persist($ProductClass);
1054 1
        $this->entityManager->persist($ProductStock);
1055
1056
        return $ProductClass;
1057
    }
1058
1059
    /**
1060
     * 商品規格情報を更新
1061
     *
1062 1
     * @param $row
1063
     * @param Product $Product
1064
     * @param ProductClass $ProductClass
1065
     * @param CsvImportService $data
1066
     *
1067
     * @return ProductClass
1068
     */
1069
    protected function updateProductClass($row, Product $Product, ProductClass $ProductClass, $data, $headerByKey)
1070
    {
1071
        $ProductClass->setProduct($Product);
1072
1073
        $line = $data->key() + 1;
1074
        if ($row[$headerByKey['sale_type']] == '') {
1075
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1076
            $this->addErrors($message);
1077 1
        } else {
1078 1
            if (preg_match('/^\d+$/', $row[$headerByKey['sale_type']])) {
1079
                $SaleType = $this->saleTypeRepository->find($row[$headerByKey['sale_type']]);
1080
                if (!$SaleType) {
1081
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1082
                    $this->addErrors($message);
1083 1
                } else {
1084
                    $ProductClass->setSaleType($SaleType);
1085
                }
1086
            } else {
1087 1
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1088 1
                $this->addErrors($message);
1089
            }
1090 1
        }
1091
1092
        // 規格分類1、2をそれぞれセットし作成
1093 View Code Duplication
        if ($row[$headerByKey['class_category1']] != '') {
1094 1
            if (preg_match('/^\d+$/', $row[$headerByKey['class_category1']])) {
1095 1
                $ClassCategory = $this->classCategoryRepository->find($row[$headerByKey['class_category1']]);
1096 1
                if (!$ClassCategory) {
1097
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
1098
                    $this->addErrors($message);
1099 1
                } else {
1100
                    $ProductClass->setClassCategory1($ClassCategory);
1101
                }
1102 1
            } else {
1103 1
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
1104 1
                $this->addErrors($message);
1105
            }
1106
        }
1107
1108 View Code Duplication
        if ($row[$headerByKey['class_category2']] != '') {
1109
            if (preg_match('/^\d+$/', $row[$headerByKey['class_category2']])) {
1110
                $ClassCategory = $this->classCategoryRepository->find($row[$headerByKey['class_category2']]);
1111 1
                if (!$ClassCategory) {
1112 1
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
1113 1
                    $this->addErrors($message);
1114 1
                } else {
1115
                    $ProductClass->setClassCategory2($ClassCategory);
1116
                }
1117
            } else {
1118
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
1119
                $this->addErrors($message);
1120
            }
1121 1
        }
1122 1
1123 1 View Code Duplication
        if ($row[$headerByKey['delivery_date']] != '') {
1124 1
            if (preg_match('/^\d+$/', $row[$headerByKey['delivery_date']])) {
1125
                $DeliveryDuration = $this->deliveryDurationRepository->find($row[$headerByKey['delivery_date']]);
1126
                if (!$DeliveryDuration) {
1127
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
1128
                    $this->addErrors($message);
1129
                } else {
1130
                    $ProductClass->setDeliveryDuration($DeliveryDuration);
1131 1
                }
1132
            } else {
1133
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
1134
                $this->addErrors($message);
1135 1
            }
1136 1
        }
1137 1
1138
        if (StringUtil::isNotBlank($row[$headerByKey['product_code']])) {
1139
            $ProductClass->setCode(StringUtil::trimAll($row[$headerByKey['product_code']]));
1140
        } else {
1141
            $ProductClass->setCode(null);
1142
        }
1143
1144 1 View Code Duplication
        if (!isset($row[$headerByKey['stock_unlimited']])
1145
            || StringUtil::isBlank($row[$headerByKey['stock_unlimited']])
1146 1
            || $row[$headerByKey['stock_unlimited']] == (string) Constant::DISABLED
1147 1
        ) {
1148
            $ProductClass->setStockUnlimited(false);
1149
            // 在庫数が設定されていなければエラー
1150 1
            if ($row[$headerByKey['stock']] == '') {
1151
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
1152
                $this->addErrors($message);
1153 1
            } else {
1154
                $stock = str_replace(',', '', $row[$headerByKey['stock']]);
1155
                if (preg_match('/^\d+$/', $stock) && $stock >= 0) {
1156
                    $ProductClass->setStock($row[$headerByKey['stock']]);
1157
                } else {
1158
                    $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
1159 7
                    $this->addErrors($message);
1160
                }
1161 7
            }
1162 7
        } elseif ($row[$headerByKey['stock_unlimited']] == (string) Constant::ENABLED) {
1163
            $ProductClass->setStockUnlimited(true);
1164
            $ProductClass->setStock(null);
1165
        } else {
1166
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock_unlimited']]);
1167
            $this->addErrors($message);
1168 16
        }
1169
1170 16
        if ($row[$headerByKey['sale_limit']] != '') {
1171
            $saleLimit = str_replace(',', '', $row[$headerByKey['sale_limit']]);
1172
            if (preg_match('/^\d+$/', $saleLimit) && $saleLimit >= 0) {
1173
                $ProductClass->setSaleLimit($saleLimit);
1174
            } else {
1175
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['sale_limit']]);
1176 16
                $this->addErrors($message);
1177
            }
1178 16
        }
1179
1180
        if ($row[$headerByKey['price01']] != '') {
1181
            $price01 = str_replace(',', '', $row[$headerByKey['price01']]);
1182
            $errors = $this->validator->validate($price01, new GreaterThanOrEqual(['value' => 0]));
1183
            if ($errors->count() === 0) {
1184
                $ProductClass->setPrice01($price01);
1185
            } else {
1186 10
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price01']]);
1187
                $this->addErrors($message);
1188
            }
1189 10
        }
1190
1191
        if ($row[$headerByKey['price02']] == '') {
1192
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1193
            $this->addErrors($message);
1194 10
        } else {
1195
            $price02 = str_replace(',', '', $row[$headerByKey['price02']]);
1196
            $errors = $this->validator->validate($price02, new GreaterThanOrEqual(['value' => 0]));
1197
            if ($errors->count() === 0) {
1198
                $ProductClass->setPrice02($price02);
1199 10
            } else {
1200
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1201
                $this->addErrors($message);
1202
            }
1203
        }
1204 10
1205
        $ProductStock = $ProductClass->getProductStock();
1206
1207
        if (!$ProductClass->isStockUnlimited()) {
1208
            $ProductStock->setStock($ProductClass->getStock());
1209 10
        } else {
1210
            // 在庫無制限時はnullを設定
1211
            $ProductStock->setStock(null);
1212
        }
1213
1214 10
        return $ProductClass;
1215
    }
1216
1217
    /**
1218
     * 登録、更新時のエラー画面表示
1219 10
     */
1220
    protected function addErrors($message)
1221
    {
1222
        $this->errors[] = $message;
1223
    }
1224 10
1225
    /**
1226
     * @return array
1227
     */
1228
    protected function getErrors()
1229 10
    {
1230
        return $this->errors;
1231
    }
1232
1233
    /**
1234 10
     * @return boolean
1235
     */
1236
    protected function hasErrors()
1237
    {
1238
        return count($this->getErrors()) > 0;
1239 10
    }
1240
1241
    /**
1242
     * 商品登録CSVヘッダー定義
1243
     *
1244 10
     * @return array
1245
     */
1246
    protected function getProductCsvHeader()
1247
    {
1248
        return [
1249 10
            trans('admin.product.product_csv.product_id_col') => [
1250
                'id' => 'id',
1251
                'description' => 'admin.product.product_csv.product_id_description',
1252
                'required' => false,
1253
            ],
1254 10
            trans('admin.product.product_csv.display_status_col') => [
1255
                'id' => 'status',
1256
                'description' => 'admin.product.product_csv.display_status_description',
1257
                'required' => true,
1258
            ],
1259 10
            trans('admin.product.product_csv.product_name_col') => [
1260
                'id' => 'name',
1261
                'description' => 'admin.product.product_csv.product_name_description',
1262
                'required' => true,
1263
            ],
1264 10
            trans('admin.product.product_csv.shop_memo_col') => [
1265
                'id' => 'note',
1266
                'description' => 'admin.product.product_csv.shop_memo_description',
1267
                'required' => false,
1268
            ],
1269 10
            trans('admin.product.product_csv.description_list_col') => [
1270
                'id' => 'description_list',
1271
                'description' => 'admin.product.product_csv.description_list_description',
1272
                'required' => false,
1273
            ],
1274 10
            trans('admin.product.product_csv.description_detail_col') => [
1275
                'id' => 'description_detail',
1276
                'description' => 'admin.product.product_csv.description_detail_description',
1277
                'required' => false,
1278
            ],
1279 10
            trans('admin.product.product_csv.keyword_col') => [
1280
                'id' => 'search_word',
1281
                'description' => 'admin.product.product_csv.keyword_description',
1282
                'required' => false,
1283
            ],
1284 10
            trans('admin.product.product_csv.free_area_col') => [
1285
                'id' => 'free_area',
1286
                'description' => 'admin.product.product_csv.free_area_description',
1287
                'required' => false,
1288
            ],
1289 10
            trans('admin.product.product_csv.delete_flag_col') => [
1290
                'id' => 'product_del_flg',
1291
                'description' => 'admin.product.product_csv.delete_flag_description',
1292
                'required' => false,
1293
            ],
1294 10
            trans('admin.product.product_csv.product_image_col') => [
1295
                'id' => 'product_image',
1296
                'description' => 'admin.product.product_csv.product_image_description',
1297
                'required' => false,
1298
            ],
1299 10
            trans('admin.product.product_csv.category_col') => [
1300
                'id' => 'product_category',
1301
                'description' => 'admin.product.product_csv.category_description',
1302
                'required' => false,
1303
            ],
1304
            trans('admin.product.product_csv.tag_col') => [
1305
                'id' => 'product_tag',
1306
                'description' => 'admin.product.product_csv.tag_description',
1307
                'required' => false,
1308
            ],
1309
            trans('admin.product.product_csv.sale_type_col') => [
1310 6
                'id' => 'sale_type',
1311
                'description' => 'admin.product.product_csv.sale_type_description',
1312
                'required' => true,
1313 6
            ],
1314
            trans('admin.product.product_csv.class_category1_col') => [
1315
                'id' => 'class_category1',
1316
                'description' => 'admin.product.product_csv.class_category1_description',
1317
                'required' => false,
1318 6
            ],
1319
            trans('admin.product.product_csv.class_category2_col') => [
1320
                'id' => 'class_category2',
1321
                'description' => 'admin.product.product_csv.class_category2_description',
1322
                'required' => false,
1323 6
            ],
1324
            trans('admin.product.product_csv.delivery_duration_col') => [
1325
                'id' => 'delivery_date',
1326
                'description' => 'admin.product.product_csv.delivery_duration_description',
1327
                'required' => false,
1328 6
            ],
1329
            trans('admin.product.product_csv.product_code_col') => [
1330
                'id' => 'product_code',
1331
                'description' => 'admin.product.product_csv.product_code_description',
1332
                'required' => false,
1333
            ],
1334
            trans('admin.product.product_csv.stock_col') => [
1335
                'id' => 'stock',
1336
                'description' => 'admin.product.product_csv.stock_description',
1337
                'required' => false,
1338
            ],
1339
            trans('admin.product.product_csv.stock_unlimited_col') => [
1340
                'id' => 'stock_unlimited',
1341
                'description' => 'admin.product.product_csv.stock_unlimited_description',
1342
                'required' => false,
1343
            ],
1344
            trans('admin.product.product_csv.sale_limit_col') => [
1345 4
                'id' => 'sale_limit',
1346
                'description' => 'admin.product.product_csv.sale_limit_description',
1347 4
                'required' => false,
1348 4
            ],
1349 4
            trans('admin.product.product_csv.normal_price_col') => [
1350 4
                'id' => 'price01',
1351 4
                'description' => 'admin.product.product_csv.normal_price_description',
1352 4
                'required' => false,
1353
            ],
1354 4
            trans('admin.product.product_csv.sale_price_col') => [
1355
                'id' => 'price02',
1356
                'description' => 'admin.product.product_csv.sale_price_description',
1357
                'required' => true,
1358
            ],
1359
            trans('admin.product.product_csv.delivery_fee_col') => [
1360
                'id' => 'delivery_fee',
1361
                'description' => 'admin.product.product_csv.delivery_fee_description',
1362
                'required' => false,
1363
            ],
1364
        ];
1365
    }
1366
1367
    /**
1368
     * カテゴリCSVヘッダー定義
1369
     */
1370
    protected function getCategoryCsvHeader()
1371
    {
1372
        return [
1373
            trans('admin.product.category_csv.category_id_col') => [
1374
                'id' => 'id',
1375
                'description' => 'admin.product.category_csv.category_id_description',
1376
                'required' => false,
1377
            ],
1378
            trans('admin.product.category_csv.category_name_col') => [
1379
                'id' => 'category_name',
1380
                'description' => 'admin.product.category_csv.category_name_description',
1381
                'required' => true,
1382
            ],
1383
            trans('admin.product.category_csv.parent_category_id_col') => [
1384
                'id' => 'parent_category_id',
1385
                'description' => 'admin.product.category_csv.parent_category_id_description',
1386
                'required' => false,
1387
            ],
1388
            trans('admin.product.category_csv.delete_flag_col') => [
1389
                'id' => 'category_del_flg',
1390
                'description' => 'admin.product.category_csv.delete_flag_description',
1391
                'required' => false,
1392
            ],
1393
        ];
1394
    }
1395
1396
    /**
1397
     * ProductCategory作成
1398
     *
1399
     * @param \Eccube\Entity\Product $Product
1400
     * @param \Eccube\Entity\Category $Category
1401
     * @param int $sortNo
1402
     *
1403
     * @return ProductCategory
1404
     */
1405 View Code Duplication
    private function makeProductCategory($Product, $Category, $sortNo)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1406
    {
1407
        $ProductCategory = new ProductCategory();
1408
        $ProductCategory->setProduct($Product);
1409
        $ProductCategory->setProductId($Product->getId());
1410
        $ProductCategory->setCategory($Category);
1411
        $ProductCategory->setCategoryId($Category->getId());
1412
1413
        return $ProductCategory;
1414
    }
1415
}
1416