Completed
Push — 4.0 ( b48f64...137622 )
by chihiro
20:21 queued 10s
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) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.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(
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...
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::isBlank($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
                                        $headerByKey['delivery_fee'] = trans('csvimport.label.delivery_fee');
405
                                        if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
406
                                            $deliveryFee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
407
                                            $errors = $this->validator->validate($deliveryFee, new GreaterThanOrEqual(['value' => 0]));
408
                                            if ($errors->count() === 0) {
409
                                                $pc->setDeliveryFee($deliveryFee);
410 1
                                            } else {
411 1
                                                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
412 1
                                                $this->addErrors($message);
413
                                            }
414
                                        }
415
                                    }
416 1
                                    $flag = true;
417 1
                                    break;
418 1
                                }
419
                            }
420
421
                            // 商品規格を登録
422 1
                            if (!$flag) {
423 1
                                $pc = $ProductClasses[0];
424
                                if ($pc->getClassCategory1() == null &&
425
                                    $pc->getClassCategory2() == null
426
                                ) {
427
                                    // 規格分類1、規格分類2がnullであるデータを非表示
428
                                    $pc->setVisible(false);
429
                                }
430 1
431
                                if (isset($row[$headerByKey['class_category1']]) && isset($row[$headerByKey['class_category2']])
432
                                    && $row[$headerByKey['class_category1']] == $row[$headerByKey['class_category2']]) {
433
                                    $message = trans('admin.common.csv_invalid_not_same', [
434
                                        '%line%' => $line,
435 1
                                        '%name1%' => $headerByKey['class_category1'],
436
                                        '%name2%' => $headerByKey['class_category2'],
437
                                    ]);
438
                                    $this->addErrors($message);
439
                                } else {
440
                                    // 必ず規格分類1がセットされている
441
                                    // 規格分類1、2をそれぞれセットし作成
442
                                    $ClassCategory1 = null;
443
                                    if (preg_match('/^\d+$/', $classCategoryId1)) {
444 1
                                        $ClassCategory1 = $this->classCategoryRepository->find($classCategoryId1);
445
                                        if (!$ClassCategory1) {
446 1
                                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
447
                                            $this->addErrors($message);
448
                                        }
449
                                    } else {
450
                                        $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
451
                                        $this->addErrors($message);
452
                                    }
453
454
                                    $ClassCategory2 = null;
455
                                    if (isset($row[$headerByKey['class_category2']]) && StringUtil::isNotBlank($row[$headerByKey['class_category2']])) {
456
                                        if ($pc->getClassCategory1() != null && $pc->getClassCategory2() == null) {
457 1
                                            $message = trans('admin.common.csv_invalid_can_not', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
458
                                            $this->addErrors($message);
459
                                        } else {
460
                                            if (preg_match('/^\d+$/', $classCategoryId2)) {
461 8
                                                $ClassCategory2 = $this->classCategoryRepository->find($classCategoryId2);
462 3 View Code Duplication
                                                if (!$ClassCategory2) {
463
                                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
464 5
                                                    $this->addErrors($message);
465
                                                } else {
466 5
                                                    if ($ClassCategory1 &&
467 5
                                                        ($ClassCategory1->getClassName()->getId() == $ClassCategory2->getClassName()->getId())
468 5
                                                    ) {
469 5
                                                        $message = trans('admin.common.csv_invalid_not_same', [
470 5
                                                            '%line%' => $line,
471
                                                            '%name1%' => $headerByKey['class_category1'],
472
                                                            '%name2%' => $headerByKey['class_category2'],
473
                                                        ]);
474
                                                        $this->addErrors($message);
475 5
                                                    }
476
                                                }
477
                                            } else {
478
                                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
479
                                                $this->addErrors($message);
480
                                            }
481
                                        }
482
                                    } else {
483
                                        if ($pc->getClassCategory1() != null && $pc->getClassCategory2() != null) {
484 6
                                            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
485
                                            $this->addErrors($message);
486 6
                                        }
487
                                    }
488 6
                                    $ProductClass = $this->createProductClass($row, $Product, $data, $headerByKey, $ClassCategory1, $ClassCategory2);
489 6
490 6 View Code Duplication
                                    if ($this->BaseInfo->isOptionProductDeliveryFee()) {
491 6
                                        if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
492 6
                                            $deliveryFee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
493 6
                                            $errors = $this->validator->validate($deliveryFee, new GreaterThanOrEqual(['value' => 0]));
494 6
                                            if ($errors->count() === 0) {
495 6
                                                $ProductClass->setDeliveryFee($deliveryFee);
496 6
                                            } else {
497
                                                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
498
                                                $this->addErrors($message);
499
                                            }
500
                                        }
501
                                    }
502
                                    $Product->addProductClass($ProductClass);
503
                                }
504
                            }
505 6
                        }
506
                        if ($this->hasErrors()) {
507 6
                            return $this->renderWithError($form, $headers);
508 6
                        }
509 1
                        $this->entityManager->persist($Product);
510
                    }
511 1
                    $this->entityManager->flush();
512
                    $this->entityManager->getConnection()->commit();
513
514 5
                    // 画像ファイルの削除(commit後に削除させる)
515 5 View Code Duplication
                    foreach ($deleteImages as $images) {
516
                        foreach ($images as $image) {
517
                            try {
518
                                $fs = new Filesystem();
519
                                $fs->remove($this->eccubeConfig['eccube_save_image_dir'].'/'.$image);
520 5
                            } catch (\Exception $e) {
521 5
                                // エラーが発生しても無視する
522
                            }
523 5
                        }
524
                    }
525 5
526 5
                    log_info('商品CSV登録完了');
527 1
                    $message = 'admin.common.csv_upload_complete';
528
                    $this->session->getFlashBag()->add('eccube.admin.success', $message);
529
530
                    $cacheUtil->clearDoctrineCache();
531
                }
532 1
            }
533 1
        }
534
535
        return $this->renderWithError($form, $headers);
536
    }
537
538 1
    /**
539
     * カテゴリ登録CSVアップロード
540
     *
541
     * @Route("/%eccube_admin_route%/product/category_csv_upload", name="admin_product_category_csv_import")
542
     * @Template("@admin/Product/csv_category.twig")
543
     */
544
    public function csvCategory(Request $request, CacheUtil $cacheUtil)
545 5
    {
546 1
        $form = $this->formFactory->createBuilder(CsvImportType::class)->getForm();
547
548
        $headers = $this->getCategoryCsvHeader();
549
        if ('POST' === $request->getMethod()) {
550
            $form->handleRequest($request);
551
            if ($form->isValid()) {
552
                $formFile = $form['import_file']->getData();
553
                if (!empty($formFile)) {
554
                    log_info('カテゴリCSV登録開始');
555
                    $data = $this->getImportData($formFile);
556 View Code Duplication
                    if ($data === false) {
557
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
558
559
                        return $this->renderWithError($form, $headers, false);
560
                    }
561
562
                    $getId = function ($item) {
563
                        return $item['id'];
564
                    };
565 5
                    $requireHeader = array_keys(array_map($getId, array_filter($headers, function ($value) {
566 1
                        return $value['required'];
567
                    })));
568 1
569
                    $headerByKey = array_flip(array_map($getId, $headers));
570 4
571
                    $columnHeaders = $data->getColumnHeaders();
572 View Code Duplication
                    if (count(array_diff($requireHeader, $columnHeaders)) > 0) {
573 4
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
574 4
575 1
                        return $this->renderWithError($form, $headers, false);
576
                    }
577
578
                    $size = count($data);
579 View Code Duplication
                    if ($size < 1) {
580
                        $this->addErrors(trans('admin.common.csv_invalid_no_data'));
581
582 1
                        return $this->renderWithError($form, $headers, false);
583 1
                    }
584
                    $this->entityManager->getConfiguration()->setSQLLogger(null);
585
                    $this->entityManager->getConnection()->beginTransaction();
586
                    // CSVファイルの登録処理
587
                    foreach ($data as $row) {
588
                        /** @var $Category Category */
589 4
                        $Category = new Category();
590
                        if (isset($row[$headerByKey['id']]) && strlen($row[$headerByKey['id']]) > 0) {
591 View Code Duplication
                            if (!preg_match('/^\d+$/', $row[$headerByKey['id']])) {
592 4
                                $this->addErrors(($data->key() + 1).'行目のカテゴリIDが存在しません。');
593
594
                                return $this->renderWithError($form, $headers);
595
                            }
596
                            $Category = $this->categoryRepository->find($row[$headerByKey['id']]);
597
                            if (!$Category) {
598
                                $this->addErrors(($data->key() + 1).'行目のカテゴリIDが存在しません。');
599
600 4
                                return $this->renderWithError($form, $headers);
601 4
                            }
602 1
                            if ($row[$headerByKey['id']] == $row[$headerByKey['parent_category_id']]) {
603
                                $this->addErrors(($data->key() + 1).'行目のカテゴリIDと親カテゴリIDが同じです。');
604
605
                                return $this->renderWithError($form, $headers);
606 4
                            }
607
                        }
608 4
609
                        if (isset($row[$headerByKey['category_del_flg']]) && StringUtil::isNotBlank($row[$headerByKey['category_del_flg']])) {
610
                            if (StringUtil::trimAll($row[$headerByKey['category_del_flg']]) == 1) {
611
                                if ($Category->getId()) {
612
                                    log_info('カテゴリ削除開始', [$Category->getId()]);
613
                                    try {
614 4
                                        $this->categoryRepository->delete($Category);
615
                                        log_info('カテゴリ削除完了', [$Category->getId()]);
616
                                    } catch (ForeignKeyConstraintViolationException $e) {
617 4
                                        log_info('カテゴリ削除エラー', [$Category->getId(), $e]);
618 4
                                        $message = trans('admin.common.delete_error_foreign_key', ['%name%' => $Category->getName()]);
619
                                        $this->addError($message, 'admin');
620
621 4
                                        return $this->renderWithError($form, $headers);
622 4
                                    }
623 4
                                }
624 4
625
                                continue;
626
                            }
627
                        }
628
629 4
                        if (!isset($row[$headerByKey['category_name']]) || StringUtil::isBlank($row[$headerByKey['category_name']])) {
630
                            $this->addErrors(($data->key() + 1).'行目のカテゴリ名が設定されていません。');
631
632
                            return $this->renderWithError($form, $headers);
633
                        } else {
634
                            $Category->setName(StringUtil::trimAll($row[$headerByKey['category_name']]));
635
                        }
636
637
                        $ParentCategory = null;
638
                        if (isset($row[$headerByKey['parent_category_id']]) && StringUtil::isNotBlank($row[$headerByKey['parent_category_id']])) {
639 View Code Duplication
                            if (!preg_match('/^\d+$/', $row[$headerByKey['parent_category_id']])) {
640
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
641
642
                                return $this->renderWithError($form, $headers);
643
                            }
644
645
                            /** @var $ParentCategory Category */
646
                            $ParentCategory = $this->categoryRepository->find($row[$headerByKey['parent_category_id']]);
647
                            if (!$ParentCategory) {
648
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
649
650
                                return $this->renderWithError($form, $headers);
651
                            }
652
                        }
653
                        $Category->setParent($ParentCategory);
654
655
                        // Level
656
                        if (isset($row['階層']) && StringUtil::isNotBlank($row['階層'])) {
657 View Code Duplication
                            if ($ParentCategory == null && $row['階層'] != 1) {
658
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
659
660
                                return $this->renderWithError($form, $headers);
661
                            }
662
                            $level = StringUtil::trimAll($row['階層']);
663 16
                        } else {
664
                            $level = 1;
665 16
                            if ($ParentCategory) {
666 7
                                $level = $ParentCategory->getHierarchy() + 1;
667 6
                            }
668
                        }
669
670
                        $Category->setHierarchy($level);
671 16
672
                        if ($this->eccubeConfig['eccube_category_nest_level'] < $Category->getHierarchy()) {
673
                            $this->addErrors(($data->key() + 1).'行目のカテゴリが最大レベルを超えているため設定できません。');
674 16
675 16
                            return $this->renderWithError($form, $headers);
676 16
                        }
677
678
                        if ($this->hasErrors()) {
679
                            return $this->renderWithError($form, $headers);
680
                        }
681
                        $this->entityManager->persist($Category);
682
                        $this->categoryRepository->save($Category);
683
                    }
684
685
                    $this->entityManager->getConnection()->commit();
686
                    log_info('カテゴリCSV登録完了');
687 8
                    $message = 'admin.common.csv_upload_complete';
688
                    $this->session->getFlashBag()->add('eccube.admin.success', $message);
689 8
690
                    $cacheUtil->clearDoctrineCache();
691 4
                }
692 4
            }
693 2
        }
694 2
695
        return $this->renderWithError($form, $headers);
696
    }
697
698 4
    /**
699
     * アップロード用CSV雛形ファイルダウンロード
700 4
     *
701
     * @Route("/%eccube_admin_route%/product/csv_template/{type}", requirements={"type" = "\w+"}, name="admin_product_csv_template")
702 4
     */
703 4
    public function csvTemplate(Request $request, $type)
704 4
    {
705
        if ($type == 'product') {
706
            $headers = $this->getProductCsvHeader();
707 4
            $filename = 'product.csv';
708
        } elseif ($type == 'category') {
709
            $headers = $this->getCategoryCsvHeader();
710
            $filename = 'category.csv';
711
        } else {
712 4
            throw new NotFoundHttpException();
713 4
        }
714 4
715 4
        return $this->sendTemplateResponse($request, array_keys($headers), $filename);
716 4
    }
717
718 4
    /**
719 4
     * 登録、更新時のエラー画面表示
720 4
     *
721
     * @param FormInterface $form
722
     * @param array $headers
723
     * @param bool $rollback
724
     *
725
     * @return array
726
     *
727
     * @throws \Doctrine\DBAL\ConnectionException
728
     */
729
    protected function renderWithError($form, $headers, $rollback = true)
730
    {
731
        if ($this->hasErrors()) {
732
            if ($rollback) {
733
                $this->entityManager->getConnection()->rollback();
734
            }
735 8
        }
736
737
        $this->removeUploadedFile();
738 8
739 8
        return [
740 2
            'form' => $form->createView(),
741 2
            'headers' => $headers,
742 2
            'errors' => $this->errors,
743
        ];
744
    }
745 8
746
    /**
747 4
     * 商品画像の削除、登録
748 4
     *
749 4
     * @param $row
750 4
     * @param Product $Product
751 4
     * @param CsvImportService $data
752 4
     */
753 4
    protected function createProductImage($row, Product $Product, $data, $headerByKey)
754 4
    {
755
        if (isset($row[$headerByKey['product_image']]) && StringUtil::isNotBlank($row[$headerByKey['product_image']])) {
756
            // 画像の削除
757
            $ProductImages = $Product->getProductImage();
758
            foreach ($ProductImages as $ProductImage) {
759
                $Product->removeProductImage($ProductImage);
760
                $this->entityManager->remove($ProductImage);
761
            }
762 4
763 4
            // 画像の登録
764 4
            $images = explode(',', $row[$headerByKey['product_image']]);
765 4
766 4
            $sortNo = 1;
767
768 4
            $pattern = "/\\$|^.*.\.\\\.*|\/$|^.*.\.\/\.*/";
769 4
            foreach ($images as $image) {
770
                $fileName = StringUtil::trimAll($image);
771
772 4
                // 商品画像名のフォーマットチェック
773
                if (strlen($fileName) > 0 && preg_match($pattern, $fileName)) {
774
                    $message = trans('admin.common.csv_invalid_image', ['%line%' => $data->key() + 1, '%name%' => $headerByKey['product_image']]);
775
                    $this->addErrors($message);
776
                } else {
777
                    // 空文字は登録対象外
778
                    if (!empty($fileName)) {
779
                        $ProductImage = new ProductImage();
780
                        $ProductImage->setFileName($fileName);
781 4
                        $ProductImage->setProduct($Product);
782
                        $ProductImage->setSortNo($sortNo);
783
784
                        $Product->addProductImage($ProductImage);
785
                        $sortNo++;
786 4
                        $this->entityManager->persist($ProductImage);
787
                    }
788
                }
789
            }
790
        }
791
    }
792
793
    /**
794 4
     * 商品カテゴリの削除、登録
795
     *
796
     * @param $row
797
     * @param Product $Product
798
     * @param CsvImportService $data
799
     * @param $headerByKey
800
     */
801
    protected function createProductCategory($row, Product $Product, $data, $headerByKey)
802
    {
803
        // カテゴリの削除
804
        $ProductCategories = $Product->getProductCategories();
805
        foreach ($ProductCategories as $ProductCategory) {
806
            $Product->removeProductCategory($ProductCategory);
807 8
            $this->entityManager->remove($ProductCategory);
808
            $this->entityManager->flush();
809
        }
810 8
811 8
        if (isset($row[$headerByKey['product_category']]) && StringUtil::isNotBlank($row[$headerByKey['product_category']])) {
812 1
            // カテゴリの登録
813 1
            $categories = explode(',', $row[$headerByKey['product_category']]);
814
            $sortNo = 1;
815
            $categoriesIdList = [];
816 8
            foreach ($categories as $category) {
817
                $line = $data->key() + 1;
818 4
                if (preg_match('/^\d+$/', $category)) {
819 4
                    $Category = $this->categoryRepository->find($category);
820 4
                    if (!$Category) {
821 4
                        $message = trans('admin.common.csv_invalid_not_found_target', [
822 4
                            '%line%' => $line,
823
                            '%name%' => $headerByKey['product_category'],
824 4
                            '%target_name%' => $category,
825 4
                        ]);
826
                        $this->addErrors($message);
827 4
                    } else {
828 4 View Code Duplication
                        foreach ($Category->getPath() as $ParentCategory) {
829
                            if (!isset($categoriesIdList[$ParentCategory->getId()])) {
830 4
                                $ProductCategory = $this->makeProductCategory($Product, $ParentCategory, $sortNo);
831
                                $this->entityManager->persist($ProductCategory);
832 4
                                $sortNo++;
833
834
                                $Product->addProductCategory($ProductCategory);
835 4
                                $categoriesIdList[$ParentCategory->getId()] = true;
836
                            }
837
                        }
838
                        if (!isset($categoriesIdList[$Category->getId()])) {
839
                            $ProductCategory = $this->makeProductCategory($Product, $Category, $sortNo);
840
                            $sortNo++;
841 4
                            $this->entityManager->persist($ProductCategory);
842
                            $Product->addProductCategory($ProductCategory);
843
                            $categoriesIdList[$Category->getId()] = true;
844
                        }
845
                    }
846 View Code Duplication
                } else {
847
                    $message = trans('admin.common.csv_invalid_not_found_target', [
848
                        '%line%' => $line,
849
                        '%name%' => $headerByKey['product_category'],
850
                        '%target_name%' => $category,
851
                    ]);
852
                    $this->addErrors($message);
853
                }
854
            }
855
        }
856
    }
857
858
    /**
859 8
     * タグの登録
860
     *
861
     * @param array $row
862 8
     * @param Product $Product
863 8
     * @param CsvImportService $data
864 8
     */
865
    protected function createProductTag($row, Product $Product, $data, $headerByKey)
866 8
    {
867 8
        // タグの削除
868 8
        $ProductTags = $Product->getProductTag();
869 8
        foreach ($ProductTags as $ProductTag) {
870 8
            $Product->removeProductTag($ProductTag);
871
            $this->entityManager->remove($ProductTag);
872
        }
873
874 8
        if (isset($row[$headerByKey['product_tag']]) && StringUtil::isNotBlank($row[$headerByKey['product_tag']])) {
875
            // タグの登録
876
            $tags = explode(',', $row[$headerByKey['product_tag']]);
877
            foreach ($tags as $tag_id) {
878 8
                $Tag = null;
879
                if (preg_match('/^\d+$/', $tag_id)) {
880
                    $Tag = $this->tagRepository->find($tag_id);
881
882
                    if ($Tag) {
883
                        $ProductTags = new ProductTag();
884
                        $ProductTags
885 8
                            ->setProduct($Product)
886 8
                            ->setTag($Tag);
887
888 8
                        $Product->addProductTag($ProductTags);
889 3
890 3
                        $this->entityManager->persist($ProductTags);
891 3
                    }
892
                }
893 View Code Duplication
                if (!$Tag) {
894
                    $message = trans('admin.common.csv_invalid_not_found_target', [
895 3
                        '%line%' => $data->key() + 1,
896
                        '%name%' => $headerByKey['product_tag'],
897
                        '%target_name%' => $tag_id,
898
                    ]);
899
                    $this->addErrors($message);
900
                }
901
            }
902
        }
903 8
    }
904 3
905
    /**
906 5
     * 商品規格分類1、商品規格分類2がnullとなる商品規格情報を作成
907
     *
908
     * @param $row
909 8
     * @param Product $Product
910
     * @param CsvImportService $data
911
     * @param $headerByKey
912
     * @param null $ClassCategory1
913 8
     * @param null $ClassCategory2
914 4
     *
915
     * @return ProductClass
916 4
     */
917 4
    protected function createProductClass($row, Product $Product, $data, $headerByKey, $ClassCategory1 = null, $ClassCategory2 = null)
918 4
    {
919 4
        // 規格分類1、規格分類2がnullとなる商品を作成
920
        $ProductClass = new ProductClass();
921
        $ProductClass->setProduct($Product);
922 4
        $ProductClass->setVisible(true);
923
924
        $line = $data->key() + 1;
925
        if (isset($row[$headerByKey['sale_type']]) && StringUtil::isNotBlank($row[$headerByKey['sale_type']])) {
926 4
            if (preg_match('/^\d+$/', $row[$headerByKey['sale_type']])) {
927
                $SaleType = $this->saleTypeRepository->find($row[$headerByKey['sale_type']]);
928 4
                if (!$SaleType) {
929 4
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
930 4
                    $this->addErrors($message);
931
                } else {
932
                    $ProductClass->setSaleType($SaleType);
933
                }
934
            } else {
935
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
936
                $this->addErrors($message);
937 8
            }
938
        } else {
939
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
940
            $this->addErrors($message);
941
        }
942
943
        $ProductClass->setClassCategory1($ClassCategory1);
944
        $ProductClass->setClassCategory2($ClassCategory2);
945
946
        if (isset($row[$headerByKey['delivery_date']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_date']])) {
947 8
            if (preg_match('/^\d+$/', $row[$headerByKey['delivery_date']])) {
948 3
                $DeliveryDuration = $this->deliveryDurationRepository->find($row[$headerByKey['delivery_date']]);
949 3
                if (!$DeliveryDuration) {
950 3
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
951
                    $this->addErrors($message);
952
                } else {
953
                    $ProductClass->setDeliveryDuration($DeliveryDuration);
954
                }
955
            } else {
956
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
957 8
                $this->addErrors($message);
958 8
            }
959 8
        }
960 8
961 View Code Duplication
        if (isset($row[$headerByKey['product_code']]) && StringUtil::isNotBlank($row[$headerByKey['product_code']])) {
962
            $ProductClass->setCode(StringUtil::trimAll($row[$headerByKey['product_code']]));
963 8
        } else {
964
            $ProductClass->setCode(null);
965
        }
966
967 View Code Duplication
        if (!isset($row[$headerByKey['stock_unlimited']])
968
            || StringUtil::isBlank($row[$headerByKey['stock_unlimited']])
969
            || $row[$headerByKey['stock_unlimited']] == (string) Constant::DISABLED
970 8
        ) {
971 3
            $ProductClass->setStockUnlimited(false);
972 3
            // 在庫数が設定されていなければエラー
973 3
            if (isset($row[$headerByKey['stock']]) && StringUtil::isNotBlank($row[$headerByKey['stock']])) {
974
                $stock = str_replace(',', '', $row[$headerByKey['stock']]);
975
                if (preg_match('/^\d+$/', $stock) && $stock >= 0) {
976
                    $ProductClass->setStock($stock);
977
                } else {
978
                    $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
979
                    $this->addErrors($message);
980 8
                }
981 8
            } else {
982 8
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
983 8
                $this->addErrors($message);
984
            }
985 8
        } elseif ($row[$headerByKey['stock_unlimited']] == (string) Constant::ENABLED) {
986 4
            $ProductClass->setStockUnlimited(true);
987
            $ProductClass->setStock(null);
988
        } else {
989 4
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock_unlimited']]);
990
            $this->addErrors($message);
991
        }
992 8
993 8
        if (isset($row[$headerByKey['sale_limit']]) && StringUtil::isNotBlank($row[$headerByKey['sale_limit']])) {
994
            $saleLimit = str_replace(',', '', $row[$headerByKey['sale_limit']]);
995 8
            if (preg_match('/^\d+$/', $saleLimit) && $saleLimit >= 0) {
996
                $ProductClass->setSaleLimit($saleLimit);
997
            } else {
998
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['sale_limit']]);
999
                $this->addErrors($message);
1000
            }
1001
        }
1002
1003
        if (isset($row[$headerByKey['price01']]) && StringUtil::isNotBlank($row[$headerByKey['price01']])) {
1004
            $price01 = str_replace(',', '', $row[$headerByKey['price01']]);
1005
            $errors = $this->validator->validate($price01, new GreaterThanOrEqual(['value' => 0]));
1006
            if ($errors->count() === 0) {
1007
                $ProductClass->setPrice01($price01);
1008 1
            } else {
1009
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price01']]);
1010 1
                $this->addErrors($message);
1011
            }
1012 1
        }
1013 1
1014
        if (isset($row[$headerByKey['price02']]) && StringUtil::isNotBlank($row[$headerByKey['price02']])) {
1015
            $price02 = str_replace(',', '', $row[$headerByKey['price02']]);
1016
            $errors = $this->validator->validate($price02, new GreaterThanOrEqual(['value' => 0]));
1017 1
            if ($errors->count() === 0) {
1018 1
                $ProductClass->setPrice02($price02);
1019 1
            } else {
1020
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1021
                $this->addErrors($message);
1022
            }
1023 1
        } else {
1024
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1025
            $this->addErrors($message);
1026
        }
1027
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', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
1035 1
                $this->addErrors($message);
1036
            }
1037
        }
1038
1039 1
        $Product->addProductClass($ProductClass);
1040
        $ProductStock = new ProductStock();
1041
        $ProductClass->setProductStock($ProductStock);
1042
        $ProductStock->setProductClass($ProductClass);
1043
1044
        if (!$ProductClass->isStockUnlimited()) {
1045
            $ProductStock->setStock($ProductClass->getStock());
1046
        } else {
1047 1
            // 在庫無制限時はnullを設定
1048 1
            $ProductStock->setStock(null);
1049 1
        }
1050 1
1051
        $this->entityManager->persist($ProductClass);
1052
        $this->entityManager->persist($ProductStock);
1053
1054 1
        return $ProductClass;
1055
    }
1056
1057
    /**
1058
     * 商品規格情報を更新
1059
     *
1060
     * @param $row
1061
     * @param Product $Product
1062 1
     * @param ProductClass $ProductClass
1063
     * @param CsvImportService $data
1064
     *
1065
     * @return ProductClass
1066
     */
1067
    protected function updateProductClass($row, Product $Product, ProductClass $ProductClass, $data, $headerByKey)
1068
    {
1069
        $ProductClass->setProduct($Product);
1070
1071
        $line = $data->key() + 1;
1072
        if ($row[$headerByKey['sale_type']] == '') {
1073
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1074
            $this->addErrors($message);
1075
        } else {
1076
            if (preg_match('/^\d+$/', $row[$headerByKey['sale_type']])) {
1077 1
                $SaleType = $this->saleTypeRepository->find($row[$headerByKey['sale_type']]);
1078 1
                if (!$SaleType) {
1079
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1080
                    $this->addErrors($message);
1081
                } else {
1082
                    $ProductClass->setSaleType($SaleType);
1083 1
                }
1084
            } else {
1085
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1086
                $this->addErrors($message);
1087 1
            }
1088 1
        }
1089
1090 1
        // 規格分類1、2をそれぞれセットし作成
1091 View Code Duplication
        if ($row[$headerByKey['class_category1']] != '') {
1092
            if (preg_match('/^\d+$/', $row[$headerByKey['class_category1']])) {
1093
                $ClassCategory = $this->classCategoryRepository->find($row[$headerByKey['class_category1']]);
1094 1
                if (!$ClassCategory) {
1095 1
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
1096 1
                    $this->addErrors($message);
1097
                } else {
1098
                    $ProductClass->setClassCategory1($ClassCategory);
1099 1
                }
1100
            } else {
1101
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
1102 1
                $this->addErrors($message);
1103 1
            }
1104 1
        }
1105
1106 View Code Duplication
        if ($row[$headerByKey['class_category2']] != '') {
1107
            if (preg_match('/^\d+$/', $row[$headerByKey['class_category2']])) {
1108
                $ClassCategory = $this->classCategoryRepository->find($row[$headerByKey['class_category2']]);
1109
                if (!$ClassCategory) {
1110
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
1111 1
                    $this->addErrors($message);
1112 1
                } else {
1113 1
                    $ProductClass->setClassCategory2($ClassCategory);
1114 1
                }
1115
            } else {
1116
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
1117
                $this->addErrors($message);
1118
            }
1119
        }
1120
1121 1 View Code Duplication
        if ($row[$headerByKey['delivery_date']] != '') {
1122 1
            if (preg_match('/^\d+$/', $row[$headerByKey['delivery_date']])) {
1123 1
                $DeliveryDuration = $this->deliveryDurationRepository->find($row[$headerByKey['delivery_date']]);
1124 1
                if (!$DeliveryDuration) {
1125
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
1126
                    $this->addErrors($message);
1127
                } else {
1128
                    $ProductClass->setDeliveryDuration($DeliveryDuration);
1129
                }
1130
            } else {
1131 1
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
1132
                $this->addErrors($message);
1133
            }
1134
        }
1135 1
1136 1
        if (StringUtil::isNotBlank($row[$headerByKey['product_code']])) {
1137 1
            $ProductClass->setCode(StringUtil::trimAll($row[$headerByKey['product_code']]));
1138
        } else {
1139
            $ProductClass->setCode(null);
1140
        }
1141
1142 View Code Duplication
        if (!isset($row[$headerByKey['stock_unlimited']])
1143
            || StringUtil::isBlank($row[$headerByKey['stock_unlimited']])
1144 1
            || $row[$headerByKey['stock_unlimited']] == (string) Constant::DISABLED
1145
        ) {
1146 1
            $ProductClass->setStockUnlimited(false);
1147 1
            // 在庫数が設定されていなければエラー
1148
            if ($row[$headerByKey['stock']] == '') {
1149
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
1150 1
                $this->addErrors($message);
1151
            } else {
1152
                $stock = str_replace(',', '', $row[$headerByKey['stock']]);
1153 1
                if (preg_match('/^\d+$/', $stock) && $stock >= 0) {
1154
                    $ProductClass->setStock($row[$headerByKey['stock']]);
1155
                } else {
1156
                    $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
1157
                    $this->addErrors($message);
1158
                }
1159 7
            }
1160
        } elseif ($row[$headerByKey['stock_unlimited']] == (string) Constant::ENABLED) {
1161 7
            $ProductClass->setStockUnlimited(true);
1162 7
            $ProductClass->setStock(null);
1163
        } else {
1164
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock_unlimited']]);
1165
            $this->addErrors($message);
1166
        }
1167
1168 16
        if ($row[$headerByKey['sale_limit']] != '') {
1169
            $saleLimit = str_replace(',', '', $row[$headerByKey['sale_limit']]);
1170 16
            if (preg_match('/^\d+$/', $saleLimit) && $saleLimit >= 0) {
1171
                $ProductClass->setSaleLimit($saleLimit);
1172
            } else {
1173
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['sale_limit']]);
1174
                $this->addErrors($message);
1175
            }
1176 16
        }
1177
1178 16
        if ($row[$headerByKey['price01']] != '') {
1179
            $price01 = str_replace(',', '', $row[$headerByKey['price01']]);
1180
            $errors = $this->validator->validate($price01, new GreaterThanOrEqual(['value' => 0]));
1181
            if ($errors->count() === 0) {
1182
                $ProductClass->setPrice01($price01);
1183
            } else {
1184
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price01']]);
1185
                $this->addErrors($message);
1186 10
            }
1187
        }
1188
1189 10
        if ($row[$headerByKey['price02']] == '') {
1190
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1191
            $this->addErrors($message);
1192
        } else {
1193
            $price02 = str_replace(',', '', $row[$headerByKey['price02']]);
1194 10
            $errors = $this->validator->validate($price02, new GreaterThanOrEqual(['value' => 0]));
1195
            if ($errors->count() === 0) {
1196
                $ProductClass->setPrice02($price02);
1197
            } else {
1198
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1199 10
                $this->addErrors($message);
1200
            }
1201
        }
1202
1203
        $ProductStock = $ProductClass->getProductStock();
1204 10
1205
        if (!$ProductClass->isStockUnlimited()) {
1206
            $ProductStock->setStock($ProductClass->getStock());
1207
        } else {
1208
            // 在庫無制限時はnullを設定
1209 10
            $ProductStock->setStock(null);
1210
        }
1211
1212
        return $ProductClass;
1213
    }
1214 10
1215
    /**
1216
     * 登録、更新時のエラー画面表示
1217
     */
1218
    protected function addErrors($message)
1219 10
    {
1220
        $this->errors[] = $message;
1221
    }
1222
1223
    /**
1224 10
     * @return array
1225
     */
1226
    protected function getErrors()
1227
    {
1228
        return $this->errors;
1229 10
    }
1230
1231
    /**
1232
     * @return boolean
1233
     */
1234 10
    protected function hasErrors()
1235
    {
1236
        return count($this->getErrors()) > 0;
1237
    }
1238
1239 10
    /**
1240
     * 商品登録CSVヘッダー定義
1241
     *
1242
     * @return array
1243
     */
1244 10
    private function getProductCsvHeader()
1245
    {
1246
        return [
1247
            trans('admin.product.product_csv.product_id_col') => [
1248
                'id' => 'id',
1249 10
                'description' => 'admin.product.product_csv.product_id_description',
1250
                'required' => false,
1251
            ],
1252
            trans('admin.product.product_csv.display_status_col') => [
1253
                'id' => 'status',
1254 10
                'description' => 'admin.product.product_csv.display_status_description',
1255
                'required' => true,
1256
            ],
1257
            trans('admin.product.product_csv.product_name_col') => [
1258
                'id' => 'name',
1259 10
                'description' => 'admin.product.product_csv.product_name_description',
1260
                'required' => true,
1261
            ],
1262
            trans('admin.product.product_csv.shop_memo_col') => [
1263
                'id' => 'note',
1264 10
                'description' => 'admin.product.product_csv.shop_memo_description',
1265
                'required' => false,
1266
            ],
1267
            trans('admin.product.product_csv.description_list_col') => [
1268
                'id' => 'description_list',
1269 10
                'description' => 'admin.product.product_csv.description_list_description',
1270
                'required' => false,
1271
            ],
1272
            trans('admin.product.product_csv.description_detail_col') => [
1273
                'id' => 'description_detail',
1274 10
                'description' => 'admin.product.product_csv.description_detail_description',
1275
                'required' => false,
1276
            ],
1277
            trans('admin.product.product_csv.keyword_col') => [
1278
                'id' => 'search_word',
1279 10
                'description' => 'admin.product.product_csv.keyword_description',
1280
                'required' => false,
1281
            ],
1282
            trans('admin.product.product_csv.free_area_col') => [
1283
                'id' => 'free_area',
1284 10
                'description' => 'admin.product.product_csv.free_area_description',
1285
                'required' => false,
1286
            ],
1287
            trans('admin.product.product_csv.delete_flag_col') => [
1288
                'id' => 'product_del_flg',
1289 10
                'description' => 'admin.product.product_csv.delete_flag_description',
1290
                'required' => false,
1291
            ],
1292
            trans('admin.product.product_csv.product_image_col') => [
1293
                'id' => 'product_image',
1294 10
                'description' => 'admin.product.product_csv.product_image_description',
1295
                'required' => false,
1296
            ],
1297
            trans('admin.product.product_csv.category_col') => [
1298
                'id' => 'product_category',
1299 10
                'description' => 'admin.product.product_csv.category_description',
1300
                'required' => false,
1301
            ],
1302
            trans('admin.product.product_csv.tag_col') => [
1303
                'id' => 'product_tag',
1304
                'description' => 'admin.product.product_csv.tag_description',
1305
                'required' => false,
1306
            ],
1307
            trans('admin.product.product_csv.sale_type_col') => [
1308
                'id' => 'sale_type',
1309
                'description' => 'admin.product.product_csv.sale_type_description',
1310 6
                'required' => true,
1311
            ],
1312
            trans('admin.product.product_csv.class_category1_col') => [
1313 6
                'id' => 'class_category1',
1314
                'description' => 'admin.product.product_csv.class_category1_description',
1315
                'required' => false,
1316
            ],
1317
            trans('admin.product.product_csv.class_category2_col') => [
1318 6
                'id' => 'class_category2',
1319
                'description' => 'admin.product.product_csv.class_category2_description',
1320
                'required' => false,
1321
            ],
1322
            trans('admin.product.product_csv.delivery_duration_col') => [
1323 6
                'id' => 'delivery_date',
1324
                'description' => 'admin.product.product_csv.delivery_duration_description',
1325
                'required' => false,
1326
            ],
1327
            trans('admin.product.product_csv.product_code_col') => [
1328 6
                'id' => 'product_code',
1329
                'description' => 'admin.product.product_csv.product_code_description',
1330
                'required' => false,
1331
            ],
1332
            trans('admin.product.product_csv.stock_col') => [
1333
                'id' => 'stock',
1334
                'description' => 'admin.product.product_csv.stock_description',
1335
                'required' => false,
1336
            ],
1337
            trans('admin.product.product_csv.stock_unlimited_col') => [
1338
                'id' => 'stock_unlimited',
1339
                'description' => 'admin.product.product_csv.stock_unlimited_description',
1340
                'required' => false,
1341
            ],
1342
            trans('admin.product.product_csv.sale_limit_col') => [
1343
                'id' => 'sale_limit',
1344
                'description' => 'admin.product.product_csv.sale_limit_description',
1345 4
                'required' => false,
1346
            ],
1347 4
            trans('admin.product.product_csv.normal_price_col') => [
1348 4
                'id' => 'price01',
1349 4
                'description' => 'admin.product.product_csv.normal_price_description',
1350 4
                'required' => false,
1351 4
            ],
1352 4
            trans('admin.product.product_csv.sale_price_col') => [
1353
                'id' => 'price02',
1354 4
                'description' => 'admin.product.product_csv.sale_price_description',
1355
                'required' => true,
1356
            ],
1357
            trans('admin.product.product_csv.delivery_fee_col') => [
1358
                'id' => 'delivery_fee',
1359
                'description' => 'admin.product.product_csv.delivery_fee_description',
1360
                'required' => false,
1361
            ],
1362
        ];
1363
    }
1364
1365
    /**
1366
     * カテゴリCSVヘッダー定義
1367
     */
1368
    private function getCategoryCsvHeader()
1369
    {
1370
        return [
1371
            trans('admin.product.category_csv.category_id_col') => [
1372
                'id' => 'id',
1373
                'description' => 'admin.product.category_csv.category_id_description',
1374
                'required' => false,
1375
            ],
1376
            trans('admin.product.category_csv.category_name_col') => [
1377
                'id' => 'category_name',
1378
                'description' => 'admin.product.category_csv.category_name_description',
1379
                'required' => true,
1380
            ],
1381
            trans('admin.product.category_csv.parent_category_id_col') => [
1382
                'id' => 'parent_category_id',
1383
                'description' => 'admin.product.category_csv.parent_category_id_description',
1384
                'required' => false,
1385
            ],
1386
            trans('admin.product.category_csv.delete_flag_col') => [
1387
                'id' => 'category_del_flg',
1388
                'description' => 'admin.product.category_csv.delete_flag_description',
1389
                'required' => false,
1390
            ],
1391
        ];
1392
    }
1393
1394
    /**
1395
     * ProductCategory作成
1396
     *
1397
     * @param \Eccube\Entity\Product $Product
1398
     * @param \Eccube\Entity\Category $Category
1399
     * @param int $sortNo
1400
     *
1401
     * @return ProductCategory
1402
     */
1403 View Code Duplication
    private function makeProductCategory($Product, $Category, $sortNo)
1404
    {
1405
        $ProductCategory = new ProductCategory();
1406
        $ProductCategory->setProduct($Product);
1407
        $ProductCategory->setProductId($Product->getId());
1408
        $ProductCategory->setCategory($Category);
1409
        $ProductCategory->setCategoryId($Category->getId());
1410
1411
        return $ProductCategory;
1412
    }
1413
}
1414