Completed
Pull Request — 4.0 (#4805)
by chihiro
05:28
created

CsvImportController::splitCsv()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
nc 8
nop 1
dl 0
loc 47
ccs 0
cts 0
cp 0
crap 56
rs 8.223
c 0
b 0
f 0
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\ProductImageRepository;
35
use Eccube\Repository\ProductRepository;
36
use Eccube\Repository\TagRepository;
37
use Eccube\Repository\TaxRuleRepository;
38
use Eccube\Service\CsvImportService;
39
use Eccube\Util\CacheUtil;
40
use Eccube\Util\StringUtil;
41
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
42
use Symfony\Component\Filesystem\Filesystem;
43
use Symfony\Component\Finder\Finder;
44
use Symfony\Component\Form\FormInterface;
45
use Symfony\Component\HttpFoundation\File\UploadedFile;
46
use Symfony\Component\HttpFoundation\Request;
47
use Symfony\Component\HttpFoundation\StreamedResponse;
48
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
49
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
50
use Symfony\Component\Routing\Annotation\Route;
51
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
52
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
53
use Symfony\Component\Validator\Validator\ValidatorInterface;
54
55
class CsvImportController extends AbstractCsvImportController
56
{
57
    /**
58
     * @var DeliveryDurationRepository
59
     */
60
    protected $deliveryDurationRepository;
61
62
    /**
63
     * @var SaleTypeRepository
64
     */
65
    protected $saleTypeRepository;
66
67
    /**
68
     * @var TagRepository
69
     */
70
    protected $tagRepository;
71
72
    /**
73
     * @var CategoryRepository
74
     */
75
    protected $categoryRepository;
76
77
    /**
78
     * @var ClassCategoryRepository
79
     */
80
    protected $classCategoryRepository;
81
82
    /**
83
     * @var ProductImageRepository
84
     */
85
    protected $productImageRepository;
86
87
    /**
88
     * @var ProductStatusRepository
89
     */
90
    protected $productStatusRepository;
91
92
    /**
93
     * @var ProductRepository
94
     */
95
    protected $productRepository;
96
97
    /**
98
     * @var TaxRuleRepository
99
     */
100
    private $taxRuleRepository;
101 16
102
    /**
103 16
     * @var BaseInfo
104 16
     */
105 16
    protected $BaseInfo;
106 16
107 16
    /**
108 16
     * @var ValidatorInterface
109 16
     */
110 16
    protected $validator;
111
112
    private $errors = [];
113
114
    protected $isXmlHttpRequest = false;
115
116
    protected $csvFileNo = 1;
117
118
    protected $currentLineNo = 1;
119 10
120
    /**
121 10
     * CsvImportController constructor.
122 10
     *
123 10
     * @param DeliveryDurationRepository $deliveryDurationRepository
124 10
     * @param SaleTypeRepository $saleTypeRepository
125 10
     * @param TagRepository $tagRepository
126 10
     * @param CategoryRepository $categoryRepository
127 10
     * @param ClassCategoryRepository $classCategoryRepository
128 10
     * @param ProductImageRepository $productImageRepository
129 10
     * @param ProductStatusRepository $productStatusRepository
130 10
     * @param ProductRepository $productRepository
131
     * @param TaxRuleRepository $taxRuleRepository
132
     * @param BaseInfoRepository $baseInfoRepository
133
     * @param ValidatorInterface $validator
134
     * @throws \Exception
135 10
     */
136 10 View Code Duplication
    public function __construct(
0 ignored issues
show
Duplication introduced by
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...
137 10
        DeliveryDurationRepository $deliveryDurationRepository,
138 10
        SaleTypeRepository $saleTypeRepository,
139 10
        TagRepository $tagRepository,
140 10
        CategoryRepository $categoryRepository,
141
        ClassCategoryRepository $classCategoryRepository,
142 10
        ProductImageRepository $productImageRepository,
143
        ProductStatusRepository $productStatusRepository,
144 10
        ProductRepository $productRepository,
145
        TaxRuleRepository $taxRuleRepository,
146
        BaseInfoRepository $baseInfoRepository,
147
        ValidatorInterface $validator
148
    ) {
149
        $this->deliveryDurationRepository = $deliveryDurationRepository;
150 10
        $this->saleTypeRepository = $saleTypeRepository;
151
        $this->tagRepository = $tagRepository;
152 10
        $this->categoryRepository = $categoryRepository;
153
        $this->classCategoryRepository = $classCategoryRepository;
154
        $this->productImageRepository = $productImageRepository;
155
        $this->productStatusRepository = $productStatusRepository;
156
        $this->productRepository = $productRepository;
157
        $this->taxRuleRepository = $taxRuleRepository;
158 10
        $this->BaseInfo = $baseInfoRepository->get();
159 10
        $this->validator = $validator;
160
    }
161 10
162 10
    /**
163
     * 商品登録CSVアップロード
164 10
     *
165 10
     * @Route("/%eccube_admin_route%/product/product_csv_upload", name="admin_product_csv_import")
166 10
     * @Template("@admin/Product/csv_product.twig")
167
     *
168
     * @return array
169
     *
170
     * @throws \Doctrine\DBAL\ConnectionException
171
     * @throws \Doctrine\ORM\NoResultException
172
     */
173 10
    public function csvProduct(Request $request, CacheUtil $cacheUtil)
174 7
    {
175 7
        $form = $this->formFactory->createBuilder(CsvImportType::class)->getForm();
176
        $headers = $this->getProductCsvHeader();
177 4
        if ('POST' === $request->getMethod()) {
178 3
            $form->handleRequest($request);
179 3
            if ($form->isValid()) {
180 1
                $this->isXmlHttpRequest = $form['is_xml_http_request']->getData();
181 1
                $this->csvFileNo = $form['csv_file_no']->getData();
182
183 3
                $formFile = $form['import_file']->getData();
184
                if (!empty($formFile)) {
185
                    log_info('商品CSV登録開始');
186 1
                    $data = $this->getImportData($formFile);
187 1 View Code Duplication
                    if ($data === false) {
188
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
189 1
190
                        return $this->renderWithError($form, $headers, false);
191
                    }
192
                    $getId = function ($item) {
193 8
                        return $item['id'];
194 1
                    };
195 1
                    $requireHeader = array_keys(array_map($getId, array_filter($headers, function ($value) {
196
                        return $value['required'];
197 7
                    })));
198 6
199 6
                    $columnHeaders = $data->getColumnHeaders();
200 1
201 1 View Code Duplication
                    if (count(array_diff($requireHeader, $columnHeaders)) > 0) {
202
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
203 6
204
                        return $this->renderWithError($form, $headers, false);
205
                    }
206 1
207 1
                    $size = count($data);
208
209 View Code Duplication
                    if ($size < 1) {
210
                        $this->addErrors(trans('admin.common.csv_invalid_no_data'));
211 8
212
                        return $this->renderWithError($form, $headers, false);
213
                    }
214
215
                    $headerSize = count($columnHeaders);
216
                    $headerByKey = array_flip(array_map($getId, $headers));
217 8
                    $deleteImages = [];
218
219
                    $this->entityManager->getConfiguration()->setSQLLogger(null);
220 8
                    $this->entityManager->getConnection()->beginTransaction();
221 3
                    // CSVファイルの登録処理
222
                    foreach ($data as $row) {
223 5
                        $line = $this->convertLineNo($data->key() + 1);
224
                        $this->currentLineNo = $line;
225
                        if ($headerSize != count($row)) {
226 8
                            $message = trans('admin.common.csv_invalid_format_line', ['%line%' => $line]);
227 4
                            $this->addErrors($message);
228
229 5
                            return $this->renderWithError($form, $headers);
230
                        }
231
232 8
                        if (!isset($row[$headerByKey['id']]) || StringUtil::isBlank($row[$headerByKey['id']])) {
233 4
                            $Product = new Product();
234
                            $this->entityManager->persist($Product);
235 4
                        } else {
236
                            if (preg_match('/^\d+$/', $row[$headerByKey['id']])) {
237
                                $Product = $this->productRepository->find($row[$headerByKey['id']]);
238 8
                                if (!$Product) {
239 3
                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['id']]);
240
                                    $this->addErrors($message);
241 5
242
                                    return $this->renderWithError($form, $headers);
243
                                }
244 8
                            } else {
245 3
                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['id']]);
246
                                $this->addErrors($message);
247 5
248
                                return $this->renderWithError($form, $headers);
249
                            }
250
251 8
                            if (isset($row[$headerByKey['product_del_flg']])) {
252
                                if (StringUtil::isNotBlank($row[$headerByKey['product_del_flg']]) && $row[$headerByKey['product_del_flg']] == (string) Constant::ENABLED) {
253 8
                                    // 商品を物理削除
254
                                    $deleteImages[] = $Product->getProductImage();
255
256 8
                                    try {
257
                                        $this->productRepository->delete($Product);
258
                                        $this->entityManager->flush();
259 8
260
                                        continue;
261
                                    } catch (ForeignKeyConstraintViolationException $e) {
262
                                        $message = trans('admin.common.csv_invalid_foreign_key', ['%line%' => $line, '%name%' => $Product->getName()]);
263 8
                                        $this->addErrors($message);
264 8
265
                                        return $this->renderWithError($form, $headers);
266 7
                                    }
267 7
                                }
268
                            }
269
                        }
270
271
                        if (StringUtil::isBlank($row[$headerByKey['status']])) {
272
                            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['status']]);
273
                            $this->addErrors($message);
274
                        } else {
275
                            if (preg_match('/^\d+$/', $row[$headerByKey['status']])) {
276
                                $ProductStatus = $this->productStatusRepository->find($row[$headerByKey['status']]);
277
                                if (!$ProductStatus) {
278
                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['status']]);
279 7
                                    $this->addErrors($message);
280 2
                                } else {
281
                                    $Product->setStatus($ProductStatus);
282
                                }
283
                            } else {
284
                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['status']]);
285
                                $this->addErrors($message);
286
                            }
287
                        }
288
289
                        if (StringUtil::isBlank($row[$headerByKey['name']])) {
290 2
                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['name']]);
291 2
                            $this->addErrors($message);
292
293
                            return $this->renderWithError($form, $headers);
294 2
                        } else {
295
                            $Product->setName(StringUtil::trimAll($row[$headerByKey['name']]));
296
                        }
297 2
298 2 View Code Duplication
                        if (isset($row[$headerByKey['note']])) {
299 2
                            if (StringUtil::isNotBlank($row[$headerByKey['note']])) {
300 2
                                $Product->setNote(StringUtil::trimAll($row[$headerByKey['note']]));
301
                            } else {
302
                                $Product->setNote(null);
303
                            }
304 2
                        }
305
306 View Code Duplication
                        if (isset($row[$headerByKey['description_list']])) {
307
                            if (StringUtil::isNotBlank($row[$headerByKey['description_list']])) {
308
                                $Product->setDescriptionList(StringUtil::trimAll($row[$headerByKey['description_list']]));
309
                            } else {
310
                                $Product->setDescriptionList(null);
311 2
                            }
312 2
                        }
313 2
314 2
                        if (isset($row[$headerByKey['description_detail']])) {
315
                            if (StringUtil::isNotBlank($row[$headerByKey['description_detail']])) {
316
                                if (mb_strlen($row[$headerByKey['description_detail']]) > $this->eccubeConfig['eccube_ltext_len']) {
317
                                    $message = trans('admin.common.csv_invalid_description_detail_upper_limit', [
318 2
                                        '%line%' => $line,
319 2
                                        '%name%' => $headerByKey['description_detail'],
320
                                        '%max%' => $this->eccubeConfig['eccube_ltext_len'],
321
                                    ]);
322
                                    $this->addErrors($message);
323
324 2
                                    return $this->renderWithError($form, $headers);
325
                                } else {
326
                                    $Product->setDescriptionDetail(StringUtil::trimAll($row[$headerByKey['description_detail']]));
327
                                }
328
                            } else {
329
                                $Product->setDescriptionDetail(null);
330
                            }
331
                        }
332 2
333 2 View Code Duplication
                        if (isset($row[$headerByKey['search_word']])) {
334
                            if (StringUtil::isNotBlank($row[$headerByKey['search_word']])) {
335 2
                                $Product->setSearchWord(StringUtil::trimAll($row[$headerByKey['search_word']]));
336 2
                            } else {
337
                                $Product->setSearchWord(null);
338
                            }
339 5
                        }
340
341 7 View Code Duplication
                        if (isset($row[$headerByKey['free_area']])) {
342
                            if (StringUtil::isNotBlank($row[$headerByKey['free_area']])) {
343
                                $Product->setFreeArea(StringUtil::trimAll($row[$headerByKey['free_area']]));
344
                            } else {
345
                                $Product->setFreeArea(null);
346 2
                            }
347 2
                        }
348 2
349
                        // 商品画像登録
350 2
                        $this->createProductImage($row, $Product, $data, $headerByKey);
351 2
352 2
                        $this->entityManager->flush();
353
354
                        // 商品カテゴリ登録
355 2
                        $this->createProductCategory($row, $Product, $data, $headerByKey);
356 2
357
                        //タグ登録
358 1
                        $this->createProductTag($row, $Product, $data, $headerByKey);
359
360 1
                        // 商品規格が存在しなければ新規登録
361
                        /** @var ProductClass[] $ProductClasses */
362
                        $ProductClasses = $Product->getProductClasses();
363
                        if ($ProductClasses->count() < 1) {
0 ignored issues
show
Bug introduced by
The method count cannot be called on $ProductClasses (of type array<integer,object<Eccube\Entity\ProductClass>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
364
                            // 規格分類1(ID)がセットされていると規格なし商品、規格あり商品を作成
365
                            $ProductClassOrg = $this->createProductClass($row, $Product, $data, $headerByKey);
366 View Code Duplication
                            if ($this->BaseInfo->isOptionProductDeliveryFee()) {
367
                                if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
368
                                    $deliveryFee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
369
                                    $errors = $this->validator->validate($deliveryFee, new GreaterThanOrEqual(['value' => 0]));
370
                                    if ($errors->count() === 0) {
371
                                        $ProductClassOrg->setDeliveryFee($deliveryFee);
372 1
                                    } else {
373 2
                                        $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
374
                                        $this->addErrors($message);
375
                                    }
376
                                }
377
                            }
378 2
379 1
                            // 商品別税率機能が有効の場合に税率を更新
380 1 View Code Duplication
                            if ($this->BaseInfo->isOptionProductTaxRule()) {
381 1
                                if (isset($row[$headerByKey['tax_rate']]) && StringUtil::isNotBlank($row[$headerByKey['tax_rate']])) {
382
                                    $taxRate = $row[$headerByKey['tax_rate']];
383
                                    $errors = $this->validator->validate($taxRate, new GreaterThanOrEqual(['value' => 0]));
384 1
                                    if ($errors->count() === 0) {
385
                                        if ($ProductClassOrg->getTaxRule()) {
386
                                            // 商品別税率の設定があれば税率を更新
387 1
                                            $ProductClassOrg->getTaxRule()->setTaxRate($taxRate);
388 1
                                        } else {
389
                                            // 商品別税率の設定がなければ新規作成
390
                                            $TaxRule = $this->taxRuleRepository->newTaxRule();
391
                                            $TaxRule->setTaxRate($taxRate);
392
                                            $TaxRule->setApplyDate(new \DateTime());
393
                                            $TaxRule->setProduct($Product);
394
                                            $TaxRule->setProductClass($ProductClassOrg);
395
                                            $ProductClassOrg->setTaxRule($TaxRule);
396
                                        }
397
                                    } else {
398 1
                                        $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['tax_rate']]);
399 1
                                        $this->addErrors($message);
400 1
                                    }
401 1
                                } else {
402
                                    // 税率の入力がなければ税率の設定を削除
403 1
                                    if ($ProductClassOrg->getTaxRule()) {
404
                                        $this->taxRuleRepository->delete($ProductClassOrg->getTaxRule());
405
                                        $ProductClassOrg->setTaxRule(null);
406
                                    }
407
                                }
408
                            }
409
410 1
                            if (isset($row[$headerByKey['class_category1']]) && StringUtil::isNotBlank($row[$headerByKey['class_category1']])) {
411 1
                                if (isset($row[$headerByKey['class_category2']]) && $row[$headerByKey['class_category1']] == $row[$headerByKey['class_category2']]) {
412 1
                                    $message = trans('admin.common.csv_invalid_not_same', [
413
                                        '%line%' => $line,
414
                                        '%name1%' => $headerByKey['class_category1'],
415
                                        '%name2%' => $headerByKey['class_category2'],
416 1
                                    ]);
417 1
                                    $this->addErrors($message);
418 1
                                } else {
419
                                    // 商品規格あり
420
                                    // 規格分類あり商品を作成
421
                                    $ProductClass = clone $ProductClassOrg;
422 1
                                    $ProductStock = clone $ProductClassOrg->getProductStock();
423 1
424
                                    // 規格分類1、規格分類2がnullであるデータを非表示
425
                                    $ProductClassOrg->setVisible(false);
426
427
                                    // 規格分類1、2をそれぞれセットし作成
428
                                    $ClassCategory1 = null;
429
                                    if (preg_match('/^\d+$/', $row[$headerByKey['class_category1']])) {
430 1
                                        $ClassCategory1 = $this->classCategoryRepository->find($row[$headerByKey['class_category1']]);
431
                                        if (!$ClassCategory1) {
432
                                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
433
                                            $this->addErrors($message);
434
                                        } else {
435 1
                                            $ProductClass->setClassCategory1($ClassCategory1);
436
                                        }
437
                                    } else {
438
                                        $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
439
                                        $this->addErrors($message);
440
                                    }
441
442
                                    if (isset($row[$headerByKey['class_category2']]) && StringUtil::isNotBlank($row[$headerByKey['class_category2']])) {
443
                                        if (preg_match('/^\d+$/', $row[$headerByKey['class_category2']])) {
444 1
                                            $ClassCategory2 = $this->classCategoryRepository->find($row[$headerByKey['class_category2']]);
445 View Code Duplication
                                            if (!$ClassCategory2) {
446 1
                                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
447
                                                $this->addErrors($message);
448
                                            } else {
449
                                                if ($ClassCategory1 &&
450
                                                    ($ClassCategory1->getClassName()->getId() == $ClassCategory2->getClassName()->getId())
451
                                                ) {
452
                                                    $message = trans('admin.common.csv_invalid_not_same', ['%line%' => $line, '%name1%' => $headerByKey['class_category1'], '%name2%' => $headerByKey['class_category2']]);
453
                                                    $this->addErrors($message);
454
                                                } else {
455
                                                    $ProductClass->setClassCategory2($ClassCategory2);
456
                                                }
457 1
                                            }
458
                                        } else {
459
                                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
460
                                            $this->addErrors($message);
461 8
                                        }
462 3
                                    }
463
                                    $ProductClass->setProductStock($ProductStock);
464 5
                                    $ProductStock->setProductClass($ProductClass);
465
466 5
                                    $this->entityManager->persist($ProductClass);
467 5
                                    $this->entityManager->persist($ProductStock);
468 5
                                }
469 5
                            } else {
470 5
                                if (isset($row[$headerByKey['class_category2']]) && StringUtil::isNotBlank($row[$headerByKey['class_category2']])) {
471
                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
472
                                    $this->addErrors($message);
473
                                }
474
                            }
475 5
                        } else {
476
                            // 商品規格の更新
477
                            $flag = false;
478
                            $classCategoryId1 = StringUtil::isBlank($row[$headerByKey['class_category1']]) ? null : $row[$headerByKey['class_category1']];
479
                            $classCategoryId2 = StringUtil::isBlank($row[$headerByKey['class_category2']]) ? null : $row[$headerByKey['class_category2']];
480
481
                            foreach ($ProductClasses as $pc) {
482
                                $classCategory1 = is_null($pc->getClassCategory1()) ? null : $pc->getClassCategory1()->getId();
483
                                $classCategory2 = is_null($pc->getClassCategory2()) ? null : $pc->getClassCategory2()->getId();
484 6
485
                                // 登録されている商品規格を更新
486 6
                                if ($classCategory1 == $classCategoryId1 &&
487
                                    $classCategory2 == $classCategoryId2
488 6
                                ) {
489 6
                                    $this->updateProductClass($row, $Product, $pc, $data, $headerByKey);
490 6
491 6 View Code Duplication
                                    if ($this->BaseInfo->isOptionProductDeliveryFee()) {
492 6
                                        if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
493 6
                                            $deliveryFee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
494 6
                                            $errors = $this->validator->validate($deliveryFee, new GreaterThanOrEqual(['value' => 0]));
495 6
                                            if ($errors->count() === 0) {
496 6
                                                $pc->setDeliveryFee($deliveryFee);
497
                                            } else {
498
                                                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
499
                                                $this->addErrors($message);
500
                                            }
501
                                        }
502
                                    }
503
504
                                    // 商品別税率機能が有効の場合に税率を更新
505 6 View Code Duplication
                                    if ($this->BaseInfo->isOptionProductTaxRule()) {
506
                                        if (isset($row[$headerByKey['tax_rate']]) && StringUtil::isNotBlank($row[$headerByKey['tax_rate']])) {
507 6
                                            $taxRate = $row[$headerByKey['tax_rate']];
508 6
                                            $errors = $this->validator->validate($taxRate, new GreaterThanOrEqual(['value' => 0]));
509 1
                                            if ($errors->count() === 0) {
510
                                                if ($pc->getTaxRule()) {
511 1
                                                    // 商品別税率の設定があれば税率を更新
512
                                                    $pc->getTaxRule()->setTaxRate($taxRate);
513
                                                } else {
514 5
                                                    // 商品別税率の設定がなければ新規作成
515 5
                                                    $TaxRule = $this->taxRuleRepository->newTaxRule();
516
                                                    $TaxRule->setTaxRate($taxRate);
517
                                                    $TaxRule->setApplyDate(new \DateTime());
518
                                                    $TaxRule->setProduct($Product);
519
                                                    $TaxRule->setProductClass($pc);
520 5
                                                    $pc->setTaxRule($TaxRule);
521 5
                                                }
522
                                            } else {
523 5
                                                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['tax_rate']]);
524
                                                $this->addErrors($message);
525 5
                                            }
526 5
                                        } else {
527 1
                                            // 税率の入力がなければ税率の設定を削除
528
                                            if ($pc->getTaxRule()) {
529
                                                $this->taxRuleRepository->delete($pc->getTaxRule());
530
                                                $pc->setTaxRule(null);
531
                                            }
532 1
                                        }
533 1
                                    }
534
535
                                    $flag = true;
536
                                    break;
537
                                }
538 1
                            }
539
540
                            // 商品規格を登録
541
                            if (!$flag) {
542
                                $pc = $ProductClasses[0];
543
                                if ($pc->getClassCategory1() == null &&
544
                                    $pc->getClassCategory2() == null
545 5
                                ) {
546 1
                                    // 規格分類1、規格分類2がnullであるデータを非表示
547
                                    $pc->setVisible(false);
548
                                }
549
550
                                if (isset($row[$headerByKey['class_category1']]) && isset($row[$headerByKey['class_category2']])
551
                                    && $row[$headerByKey['class_category1']] == $row[$headerByKey['class_category2']]) {
552
                                    $message = trans('admin.common.csv_invalid_not_same', [
553
                                        '%line%' => $line,
554
                                        '%name1%' => $headerByKey['class_category1'],
555
                                        '%name2%' => $headerByKey['class_category2'],
556
                                    ]);
557
                                    $this->addErrors($message);
558
                                } else {
559
                                    // 必ず規格分類1がセットされている
560
                                    // 規格分類1、2をそれぞれセットし作成
561
                                    $ClassCategory1 = null;
562
                                    if (preg_match('/^\d+$/', $classCategoryId1)) {
563
                                        $ClassCategory1 = $this->classCategoryRepository->find($classCategoryId1);
564
                                        if (!$ClassCategory1) {
565 5
                                            $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
566 1
                                            $this->addErrors($message);
567
                                        }
568 1
                                    } else {
569
                                        $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
570 4
                                        $this->addErrors($message);
571
                                    }
572
573 4
                                    $ClassCategory2 = null;
574 4
                                    if (isset($row[$headerByKey['class_category2']]) && StringUtil::isNotBlank($row[$headerByKey['class_category2']])) {
575 1
                                        if ($pc->getClassCategory1() != null && $pc->getClassCategory2() == null) {
576
                                            $message = trans('admin.common.csv_invalid_can_not', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
577
                                            $this->addErrors($message);
578
                                        } else {
579
                                            if (preg_match('/^\d+$/', $classCategoryId2)) {
580
                                                $ClassCategory2 = $this->classCategoryRepository->find($classCategoryId2);
581 View Code Duplication
                                                if (!$ClassCategory2) {
582 1
                                                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
583 1
                                                    $this->addErrors($message);
584
                                                } else {
585
                                                    if ($ClassCategory1 &&
586
                                                        ($ClassCategory1->getClassName()->getId() == $ClassCategory2->getClassName()->getId())
587
                                                    ) {
588
                                                        $message = trans('admin.common.csv_invalid_not_same', [
589 4
                                                            '%line%' => $line,
590
                                                            '%name1%' => $headerByKey['class_category1'],
591
                                                            '%name2%' => $headerByKey['class_category2'],
592 4
                                                        ]);
593
                                                        $this->addErrors($message);
594
                                                    }
595
                                                }
596
                                            } else {
597
                                                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
598
                                                $this->addErrors($message);
599
                                            }
600 4
                                        }
601 4
                                    } else {
602 1
                                        if ($pc->getClassCategory1() != null && $pc->getClassCategory2() != null) {
603
                                            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
604
                                            $this->addErrors($message);
605
                                        }
606 4
                                    }
607
                                    $ProductClass = $this->createProductClass($row, $Product, $data, $headerByKey, $ClassCategory1, $ClassCategory2);
0 ignored issues
show
Bug introduced by
It seems like $ClassCategory1 defined by $this->classCategoryRepo...find($classCategoryId1) on line 563 can also be of type object; however, Eccube\Controller\Admin\...r::createProductClass() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
It seems like $ClassCategory2 defined by $this->classCategoryRepo...find($classCategoryId2) on line 580 can also be of type object; however, Eccube\Controller\Admin\...r::createProductClass() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
608 4
609 View Code Duplication
                                    if ($this->BaseInfo->isOptionProductDeliveryFee()) {
610
                                        if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
611
                                            $deliveryFee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
612
                                            $errors = $this->validator->validate($deliveryFee, new GreaterThanOrEqual(['value' => 0]));
613
                                            if ($errors->count() === 0) {
614 4
                                                $ProductClass->setDeliveryFee($deliveryFee);
615
                                            } else {
616
                                                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
617 4
                                                $this->addErrors($message);
618 4
                                            }
619
                                        }
620
                                    }
621 4
622 4
                                    // 商品別税率機能が有効の場合に税率を更新
623 4
                                    if ($this->BaseInfo->isOptionProductTaxRule()) {
624 4
                                        if (isset($row[$headerByKey['tax_rate']]) && StringUtil::isNotBlank($row[$headerByKey['tax_rate']])) {
625
                                            $taxRate = $row[$headerByKey['tax_rate']];
626
                                            $errors = $this->validator->validate($taxRate, new GreaterThanOrEqual(['value' => 0]));
627
                                            if ($errors->count() === 0) {
628
                                                $TaxRule = $this->taxRuleRepository->newTaxRule();
629 4
                                                $TaxRule->setTaxRate($taxRate);
630
                                                $TaxRule->setApplyDate(new \DateTime());
631
                                                $TaxRule->setProduct($Product);
632
                                                $TaxRule->setProductClass($ProductClass);
633
                                                $ProductClass->setTaxRule($TaxRule);
634
                                            } else {
635
                                                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['tax_rate']]);
636
                                                $this->addErrors($message);
637
                                            }
638
                                        }
639
                                    }
640
641
                                    $Product->addProductClass($ProductClass);
642
                                }
643
                            }
644
                        }
645
                        if ($this->hasErrors()) {
646
                            return $this->renderWithError($form, $headers);
647
                        }
648
                        $this->entityManager->persist($Product);
649
                    }
650
                    $this->entityManager->flush();
651
                    $this->entityManager->getConnection()->commit();
652
653
                    // 画像ファイルの削除(commit後に削除させる)
654 View Code Duplication
                    foreach ($deleteImages as $images) {
655
                        /** @var ProductImage $image */
656
                        foreach ($images as $image) {
657
                            if ($this->productImageRepository->findOneBy(['file_name' => $image->getFileName()])) {
658
                                continue;
659
                            }
660
                            try {
661
                                $fs = new Filesystem();
662
                                $fs->remove($this->eccubeConfig['eccube_save_image_dir'].'/'.$image);
663 16
                            } catch (\Exception $e) {
664
                                // エラーが発生しても無視する
665 16
                            }
666 7
                        }
667 6
                    }
668
669
                    log_info('商品CSV登録完了');
670
                    if (!$this->isXmlHttpRequest) {
671 16
                        $message = 'admin.common.csv_upload_complete';
672
                        $this->session->getFlashBag()->add('eccube.admin.success', $message);
673
                    }
674 16
675 16
                    $cacheUtil->clearDoctrineCache();
676 16
                }
677
            }
678
        }
679
680
        return $this->renderWithError($form, $headers);
681
    }
682
683
    /**
684
     * カテゴリ登録CSVアップロード
685
     *
686
     * @Route("/%eccube_admin_route%/product/category_csv_upload", name="admin_product_category_csv_import")
687 8
     * @Template("@admin/Product/csv_category.twig")
688
     */
689 8
    public function csvCategory(Request $request, CacheUtil $cacheUtil)
690
    {
691 4
        $form = $this->formFactory->createBuilder(CsvImportType::class)->getForm();
692 4
693 2
        $headers = $this->getCategoryCsvHeader();
694 2
        if ('POST' === $request->getMethod()) {
695
            $form->handleRequest($request);
696
            if ($form->isValid()) {
697
                $formFile = $form['import_file']->getData();
698 4
                if (!empty($formFile)) {
699
                    log_info('カテゴリCSV登録開始');
700 4
                    $data = $this->getImportData($formFile);
701 View Code Duplication
                    if ($data === false) {
702 4
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
703 4
704 4
                        return $this->renderWithError($form, $headers, false);
705
                    }
706
707 4
                    $getId = function ($item) {
708
                        return $item['id'];
709
                    };
710
                    $requireHeader = array_keys(array_map($getId, array_filter($headers, function ($value) {
711
                        return $value['required'];
712 4
                    })));
713 4
714 4
                    $headerByKey = array_flip(array_map($getId, $headers));
715 4
716 4
                    $columnHeaders = $data->getColumnHeaders();
717 View Code Duplication
                    if (count(array_diff($requireHeader, $columnHeaders)) > 0) {
718 4
                        $this->addErrors(trans('admin.common.csv_invalid_format'));
719 4
720 4
                        return $this->renderWithError($form, $headers, false);
721
                    }
722
723
                    $size = count($data);
724 View Code Duplication
                    if ($size < 1) {
725
                        $this->addErrors(trans('admin.common.csv_invalid_no_data'));
726
727
                        return $this->renderWithError($form, $headers, false);
728
                    }
729
                    $this->entityManager->getConfiguration()->setSQLLogger(null);
730
                    $this->entityManager->getConnection()->beginTransaction();
731
                    // CSVファイルの登録処理
732
                    foreach ($data as $row) {
733
                        /** @var $Category Category */
734
                        $Category = new Category();
735 8
                        if (isset($row[$headerByKey['id']]) && strlen($row[$headerByKey['id']]) > 0) {
736 View Code Duplication
                            if (!preg_match('/^\d+$/', $row[$headerByKey['id']])) {
737
                                $this->addErrors(($data->key() + 1).'行目のカテゴリIDが存在しません。');
738 8
739 8
                                return $this->renderWithError($form, $headers);
740 2
                            }
741 2
                            $Category = $this->categoryRepository->find($row[$headerByKey['id']]);
742 2
                            if (!$Category) {
743
                                $this->addErrors(($data->key() + 1).'行目の更新対象のカテゴリIDが存在しません。新規登録の場合は、カテゴリIDの値を空で登録してください。');
744
745 8
                                return $this->renderWithError($form, $headers);
746
                            }
747 4
                            if ($row[$headerByKey['id']] == $row[$headerByKey['parent_category_id']]) {
748 4
                                $this->addErrors(($data->key() + 1).'行目のカテゴリIDと親カテゴリIDが同じです。');
749 4
750 4
                                return $this->renderWithError($form, $headers);
751 4
                            }
752 4
                        }
753 4
754 4
                        if (isset($row[$headerByKey['category_del_flg']]) && StringUtil::isNotBlank($row[$headerByKey['category_del_flg']])) {
755
                            if (StringUtil::trimAll($row[$headerByKey['category_del_flg']]) == 1) {
756
                                if ($Category->getId()) {
757
                                    log_info('カテゴリ削除開始', [$Category->getId()]);
758
                                    try {
759
                                        $this->categoryRepository->delete($Category);
760
                                        log_info('カテゴリ削除完了', [$Category->getId()]);
761
                                    } catch (ForeignKeyConstraintViolationException $e) {
762 4
                                        log_info('カテゴリ削除エラー', [$Category->getId(), $e]);
763 4
                                        $message = trans('admin.common.delete_error_foreign_key', ['%name%' => $Category->getName()]);
764 4
                                        $this->addError($message, 'admin');
765 4
766 4
                                        return $this->renderWithError($form, $headers);
767
                                    }
768 4
                                }
769 4
770
                                continue;
771
                            }
772 4
                        }
773
774
                        if (!isset($row[$headerByKey['category_name']]) || StringUtil::isBlank($row[$headerByKey['category_name']])) {
775
                            $this->addErrors(($data->key() + 1).'行目のカテゴリ名が設定されていません。');
776
777
                            return $this->renderWithError($form, $headers);
778
                        } else {
779
                            $Category->setName(StringUtil::trimAll($row[$headerByKey['category_name']]));
780
                        }
781 4
782
                        $ParentCategory = null;
783
                        if (isset($row[$headerByKey['parent_category_id']]) && StringUtil::isNotBlank($row[$headerByKey['parent_category_id']])) {
784 View Code Duplication
                            if (!preg_match('/^\d+$/', $row[$headerByKey['parent_category_id']])) {
785
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
786 4
787
                                return $this->renderWithError($form, $headers);
788
                            }
789
790
                            /** @var $ParentCategory Category */
791
                            $ParentCategory = $this->categoryRepository->find($row[$headerByKey['parent_category_id']]);
792
                            if (!$ParentCategory) {
793
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
794 4
795
                                return $this->renderWithError($form, $headers);
796
                            }
797
                        }
798
                        $Category->setParent($ParentCategory);
799
800
                        // Level
801
                        if (isset($row['階層']) && StringUtil::isNotBlank($row['階層'])) {
802 View Code Duplication
                            if ($ParentCategory == null && $row['階層'] != 1) {
803
                                $this->addErrors(($data->key() + 1).'行目の親カテゴリIDが存在しません。');
804
805
                                return $this->renderWithError($form, $headers);
806
                            }
807 8
                            $level = StringUtil::trimAll($row['階層']);
808
                        } else {
809
                            $level = 1;
810 8
                            if ($ParentCategory) {
811 8
                                $level = $ParentCategory->getHierarchy() + 1;
812 1
                            }
813 1
                        }
814
815
                        $Category->setHierarchy($level);
816 8
817
                        if ($this->eccubeConfig['eccube_category_nest_level'] < $Category->getHierarchy()) {
818 4
                            $this->addErrors(($data->key() + 1).'行目のカテゴリが最大レベルを超えているため設定できません。');
819 4
820 4
                            return $this->renderWithError($form, $headers);
821 4
                        }
822 4
823
                        if ($this->hasErrors()) {
824 4
                            return $this->renderWithError($form, $headers);
825 4
                        }
826
                        $this->entityManager->persist($Category);
827 4
                        $this->categoryRepository->save($Category);
828 4
                    }
829
830 4
                    $this->entityManager->getConnection()->commit();
831
                    log_info('カテゴリCSV登録完了');
832 4
                    $message = 'admin.common.csv_upload_complete';
833
                    $this->session->getFlashBag()->add('eccube.admin.success', $message);
834
835 4
                    $cacheUtil->clearDoctrineCache();
836
                }
837
            }
838
        }
839
840
        return $this->renderWithError($form, $headers);
841 4
    }
842
843
    /**
844
     * アップロード用CSV雛形ファイルダウンロード
845
     *
846
     * @Route("/%eccube_admin_route%/product/csv_template/{type}", requirements={"type" = "\w+"}, name="admin_product_csv_template")
847
     *
848
     * @param $type
849
     *
850
     * @return StreamedResponse
851
     */
852
    public function csvTemplate(Request $request, $type)
853
    {
854
        if ($type == 'product') {
855
            $headers = $this->getProductCsvHeader();
856
            $filename = 'product.csv';
857
        } elseif ($type == 'category') {
858
            $headers = $this->getCategoryCsvHeader();
859 8
            $filename = 'category.csv';
860
        } else {
861
            throw new NotFoundHttpException();
862 8
        }
863 8
864 8
        return $this->sendTemplateResponse($request, array_keys($headers), $filename);
865
    }
866 8
867 8
    /**
868 8
     * 登録、更新時のエラー画面表示
869 8
     *
870 8
     * @param FormInterface $form
871
     * @param array $headers
872
     * @param bool $rollback
873
     *
874 8
     * @return array
875
     *
876
     * @throws \Doctrine\DBAL\ConnectionException
877
     */
878 8
    protected function renderWithError($form, $headers, $rollback = true)
879
    {
880
        if ($this->hasErrors()) {
881
            if ($rollback) {
882
                $this->entityManager->getConnection()->rollback();
883
            }
884
        }
885 8
886 8
        $this->removeUploadedFile();
887
888 8
        if ($this->isXmlHttpRequest) {
889 3
            return $this->json([
890 3
                'success' => !$this->hasErrors(),
891 3
                'success_message' => trans('admin.common.csv_upload_line_success', [
892
                    '%from%' => $this->convertLineNo(2),
893
                    '%to%' => $this->currentLineNo]),
894
                'errors' => $this->errors,
895 3
                'error_message' => trans('admin.common.csv_upload_line_error',[
896
                    '%from%' => $this->convertLineNo(2),
897
                    '%to%' => $this->currentLineNo])
898
            ]);
899
        }
900
901
        return [
902
            'form' => $form->createView(),
903 8
            'headers' => $headers,
904 3
            'errors' => $this->errors,
905
        ];
906 5
    }
907
908
    /**
909 8
     * 商品画像の削除、登録
910
     *
911
     * @param $row
912
     * @param Product $Product
913 8
     * @param CsvImportService $data
914 4
     * @param $headerByKey
915
     */
916 4
    protected function createProductImage($row, Product $Product, $data, $headerByKey)
917 4
    {
918 4
        if (!isset($row[$headerByKey['product_image']])) {
919 4
            return;
920
        }
921
        if (StringUtil::isNotBlank($row[$headerByKey['product_image']])) {
922 4
            // 画像の削除
923
            $ProductImages = $Product->getProductImage();
924
            foreach ($ProductImages as $ProductImage) {
925
                $Product->removeProductImage($ProductImage);
926 4
                $this->entityManager->remove($ProductImage);
927
            }
928 4
929 4
            // 画像の登録
930 4
            $images = explode(',', $row[$headerByKey['product_image']]);
931
932
            $sortNo = 1;
933
934
            $pattern = "/\\$|^.*.\.\\\.*|\/$|^.*.\.\/\.*/";
935
            foreach ($images as $image) {
936
                $fileName = StringUtil::trimAll($image);
937 8
938
                // 商品画像名のフォーマットチェック
939
                if (strlen($fileName) > 0 && preg_match($pattern, $fileName)) {
940
                    $message = trans('admin.common.csv_invalid_image', ['%line%' => $data->key() + 1, '%name%' => $headerByKey['product_image']]);
941
                    $this->addErrors($message);
942
                } else {
943
                    // 空文字は登録対象外
944
                    if (!empty($fileName)) {
945
                        $ProductImage = new ProductImage();
946
                        $ProductImage->setFileName($fileName);
947 8
                        $ProductImage->setProduct($Product);
948 3
                        $ProductImage->setSortNo($sortNo);
949 3
950 3
                        $Product->addProductImage($ProductImage);
951
                        $sortNo++;
952
                        $this->entityManager->persist($ProductImage);
953
                    }
954
                }
955
            }
956
        }
957 8
    }
958 8
959 8
    /**
960 8
     * 商品カテゴリの削除、登録
961
     *
962
     * @param $row
963 8
     * @param Product $Product
964
     * @param CsvImportService $data
965
     * @param $headerByKey
966
     */
967
    protected function createProductCategory($row, Product $Product, $data, $headerByKey)
968
    {
969
        if (!isset($row[$headerByKey['product_category']])) {
970 8
            return;
971 3
        }
972 3
        // カテゴリの削除
973 3
        $ProductCategories = $Product->getProductCategories();
974
        foreach ($ProductCategories as $ProductCategory) {
975
            $Product->removeProductCategory($ProductCategory);
976
            $this->entityManager->remove($ProductCategory);
977
            $this->entityManager->flush();
978
        }
979
980 8
        if (StringUtil::isNotBlank($row[$headerByKey['product_category']])) {
981 8
            // カテゴリの登録
982 8
            $categories = explode(',', $row[$headerByKey['product_category']]);
983 8
            $sortNo = 1;
984
            $categoriesIdList = [];
985 8
            foreach ($categories as $category) {
986 4
                $line = $data->key() + 1;
987
                if (preg_match('/^\d+$/', $category)) {
988
                    $Category = $this->categoryRepository->find($category);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $Category is correct as $this->categoryRepository->find($category) (which targets Doctrine\ORM\EntityRepository::find()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
989 4
                    if (!$Category) {
990
                        $message = trans('admin.common.csv_invalid_not_found_target', [
991
                            '%line%' => $line,
992 8
                            '%name%' => $headerByKey['product_category'],
993 8
                            '%target_name%' => $category,
994
                        ]);
995 8
                        $this->addErrors($message);
996
                    } else {
997 View Code Duplication
                        foreach ($Category->getPath() as $ParentCategory) {
998
                            if (!isset($categoriesIdList[$ParentCategory->getId()])) {
999
                                $ProductCategory = $this->makeProductCategory($Product, $ParentCategory, $sortNo);
1000
                                $this->entityManager->persist($ProductCategory);
1001
                                $sortNo++;
1002
1003
                                $Product->addProductCategory($ProductCategory);
1004
                                $categoriesIdList[$ParentCategory->getId()] = true;
1005
                            }
1006
                        }
1007
                        if (!isset($categoriesIdList[$Category->getId()])) {
1008 1
                            $ProductCategory = $this->makeProductCategory($Product, $Category, $sortNo);
1009
                            $sortNo++;
1010 1
                            $this->entityManager->persist($ProductCategory);
1011
                            $Product->addProductCategory($ProductCategory);
1012 1
                            $categoriesIdList[$Category->getId()] = true;
1013 1
                        }
1014
                    }
1015 View Code Duplication
                } else {
1016
                    $message = trans('admin.common.csv_invalid_not_found_target', [
1017 1
                        '%line%' => $line,
1018 1
                        '%name%' => $headerByKey['product_category'],
1019 1
                        '%target_name%' => $category,
1020
                    ]);
1021
                    $this->addErrors($message);
1022
                }
1023 1
            }
1024
        }
1025
    }
1026
1027
    /**
1028
     * タグの登録
1029
     *
1030
     * @param array $row
1031
     * @param Product $Product
1032 1
     * @param CsvImportService $data
1033 1
     */
1034 1
    protected function createProductTag($row, Product $Product, $data, $headerByKey)
1035 1
    {
1036
        if (!isset($row[$headerByKey['product_tag']])) {
1037
            return;
1038
        }
1039 1
        // タグの削除
1040
        $ProductTags = $Product->getProductTag();
1041
        foreach ($ProductTags as $ProductTag) {
1042
            $Product->removeProductTag($ProductTag);
1043
            $this->entityManager->remove($ProductTag);
1044
        }
1045
1046
        if (StringUtil::isNotBlank($row[$headerByKey['product_tag']])) {
1047 1
            // タグの登録
1048 1
            $tags = explode(',', $row[$headerByKey['product_tag']]);
1049 1
            foreach ($tags as $tag_id) {
1050 1
                $Tag = null;
1051
                if (preg_match('/^\d+$/', $tag_id)) {
1052
                    $Tag = $this->tagRepository->find($tag_id);
1053
1054 1
                    if ($Tag) {
1055
                        $ProductTags = new ProductTag();
1056
                        $ProductTags
1057
                            ->setProduct($Product)
1058
                            ->setTag($Tag);
1059
1060
                        $Product->addProductTag($ProductTags);
1061
1062 1
                        $this->entityManager->persist($ProductTags);
1063
                    }
1064
                }
1065 View Code Duplication
                if (!$Tag) {
1066
                    $message = trans('admin.common.csv_invalid_not_found_target', [
1067
                        '%line%' => $data->key() + 1,
1068
                        '%name%' => $headerByKey['product_tag'],
1069
                        '%target_name%' => $tag_id,
1070
                    ]);
1071
                    $this->addErrors($message);
1072
                }
1073
            }
1074
        }
1075
    }
1076
1077 1
    /**
1078 1
     * 商品規格分類1、商品規格分類2がnullとなる商品規格情報を作成
1079
     *
1080
     * @param $row
1081
     * @param Product $Product
1082
     * @param CsvImportService $data
1083 1
     * @param $headerByKey
1084
     * @param null $ClassCategory1
1085
     * @param null $ClassCategory2
1086
     *
1087 1
     * @return ProductClass
1088 1
     */
1089
    protected function createProductClass($row, Product $Product, $data, $headerByKey, $ClassCategory1 = null, $ClassCategory2 = null)
1090 1
    {
1091
        // 規格分類1、規格分類2がnullとなる商品を作成
1092
        $ProductClass = new ProductClass();
1093
        $ProductClass->setProduct($Product);
1094 1
        $ProductClass->setVisible(true);
1095 1
1096 1
        $line = $data->key() + 1;
1097 View Code Duplication
        if (isset($row[$headerByKey['sale_type']]) && StringUtil::isNotBlank($row[$headerByKey['sale_type']])) {
1098
            if (preg_match('/^\d+$/', $row[$headerByKey['sale_type']])) {
1099 1
                $SaleType = $this->saleTypeRepository->find($row[$headerByKey['sale_type']]);
1100
                if (!$SaleType) {
1101
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1102 1
                    $this->addErrors($message);
1103 1
                } else {
1104 1
                    $ProductClass->setSaleType($SaleType);
1105
                }
1106
            } else {
1107
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1108
                $this->addErrors($message);
1109
            }
1110
        } else {
1111 1
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1112 1
            $this->addErrors($message);
1113 1
        }
1114 1
1115
        $ProductClass->setClassCategory1($ClassCategory1);
1116
        $ProductClass->setClassCategory2($ClassCategory2);
1117
1118 View Code Duplication
        if (isset($row[$headerByKey['delivery_date']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_date']])) {
1119
            if (preg_match('/^\d+$/', $row[$headerByKey['delivery_date']])) {
1120
                $DeliveryDuration = $this->deliveryDurationRepository->find($row[$headerByKey['delivery_date']]);
1121 1
                if (!$DeliveryDuration) {
1122 1
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
1123 1
                    $this->addErrors($message);
1124 1
                } else {
1125
                    $ProductClass->setDeliveryDuration($DeliveryDuration);
1126
                }
1127
            } else {
1128
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
1129
                $this->addErrors($message);
1130
            }
1131 1
        }
1132
1133 View Code Duplication
        if (isset($row[$headerByKey['product_code']]) && StringUtil::isNotBlank($row[$headerByKey['product_code']])) {
1134
            $ProductClass->setCode(StringUtil::trimAll($row[$headerByKey['product_code']]));
1135 1
        } else {
1136 1
            $ProductClass->setCode(null);
1137 1
        }
1138
1139 View Code Duplication
        if (!isset($row[$headerByKey['stock_unlimited']])
1140
            || StringUtil::isBlank($row[$headerByKey['stock_unlimited']])
1141
            || $row[$headerByKey['stock_unlimited']] == (string) Constant::DISABLED
1142
        ) {
1143
            $ProductClass->setStockUnlimited(false);
1144 1
            // 在庫数が設定されていなければエラー
1145
            if (isset($row[$headerByKey['stock']]) && StringUtil::isNotBlank($row[$headerByKey['stock']])) {
1146 1
                $stock = str_replace(',', '', $row[$headerByKey['stock']]);
1147 1
                if (preg_match('/^\d+$/', $stock) && $stock >= 0) {
1148
                    $ProductClass->setStock($stock);
1149
                } else {
1150 1
                    $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
1151
                    $this->addErrors($message);
1152
                }
1153 1
            } else {
1154
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
1155
                $this->addErrors($message);
1156
            }
1157
        } elseif ($row[$headerByKey['stock_unlimited']] == (string) Constant::ENABLED) {
1158
            $ProductClass->setStockUnlimited(true);
1159 7
            $ProductClass->setStock(null);
1160
        } else {
1161 7
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock_unlimited']]);
1162 7
            $this->addErrors($message);
1163
        }
1164
1165 View Code Duplication
        if (isset($row[$headerByKey['sale_limit']]) && StringUtil::isNotBlank($row[$headerByKey['sale_limit']])) {
1166
            $saleLimit = str_replace(',', '', $row[$headerByKey['sale_limit']]);
1167
            if (preg_match('/^\d+$/', $saleLimit) && $saleLimit >= 0) {
1168 16
                $ProductClass->setSaleLimit($saleLimit);
1169
            } else {
1170 16
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['sale_limit']]);
1171
                $this->addErrors($message);
1172
            }
1173
        }
1174
1175
        if (isset($row[$headerByKey['price01']]) && StringUtil::isNotBlank($row[$headerByKey['price01']])) {
1176 16
            $price01 = str_replace(',', '', $row[$headerByKey['price01']]);
1177
            $errors = $this->validator->validate($price01, new GreaterThanOrEqual(['value' => 0]));
1178 16
            if ($errors->count() === 0) {
1179
                $ProductClass->setPrice01($price01);
1180
            } else {
1181
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price01']]);
1182
                $this->addErrors($message);
1183
            }
1184
        }
1185
1186 10 View Code Duplication
        if (isset($row[$headerByKey['price02']]) && StringUtil::isNotBlank($row[$headerByKey['price02']])) {
1187
            $price02 = str_replace(',', '', $row[$headerByKey['price02']]);
1188
            $errors = $this->validator->validate($price02, new GreaterThanOrEqual(['value' => 0]));
1189 10
            if ($errors->count() === 0) {
1190
                $ProductClass->setPrice02($price02);
1191
            } else {
1192
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1193
                $this->addErrors($message);
1194 10
            }
1195
        } else {
1196
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1197
            $this->addErrors($message);
1198
        }
1199 10
1200 View Code Duplication
        if ($this->BaseInfo->isOptionProductDeliveryFee()) {
1201
            if (isset($row[$headerByKey['delivery_fee']]) && StringUtil::isNotBlank($row[$headerByKey['delivery_fee']])) {
1202
                $delivery_fee = str_replace(',', '', $row[$headerByKey['delivery_fee']]);
1203
                $errors = $this->validator->validate($delivery_fee, new GreaterThanOrEqual(['value' => 0]));
1204 10
                if ($errors->count() === 0) {
1205
                    $ProductClass->setDeliveryFee($delivery_fee);
1206
                } else {
1207
                    $message = trans('admin.common.csv_invalid_greater_than_zero',
1208
                        ['%line%' => $line, '%name%' => $headerByKey['delivery_fee']]);
1209 10
                    $this->addErrors($message);
1210
                }
1211
            }
1212
        }
1213
1214 10
        $Product->addProductClass($ProductClass);
1215
        $ProductStock = new ProductStock();
1216
        $ProductClass->setProductStock($ProductStock);
1217
        $ProductStock->setProductClass($ProductClass);
1218
1219 10
        if (!$ProductClass->isStockUnlimited()) {
1220
            $ProductStock->setStock($ProductClass->getStock());
1221
        } else {
1222
            // 在庫無制限時はnullを設定
1223
            $ProductStock->setStock(null);
1224 10
        }
1225
1226
        $this->entityManager->persist($ProductClass);
1227
        $this->entityManager->persist($ProductStock);
1228
1229 10
        return $ProductClass;
1230
    }
1231
1232
    /**
1233
     * 商品規格情報を更新
1234 10
     *
1235
     * @param $row
1236
     * @param Product $Product
1237
     * @param ProductClass $ProductClass
1238
     * @param CsvImportService $data
1239 10
     *
1240
     * @return ProductClass
1241
     */
1242
    protected function updateProductClass($row, Product $Product, ProductClass $ProductClass, $data, $headerByKey)
1243
    {
1244 10
        $ProductClass->setProduct($Product);
1245
1246
        $line = $data->key() + 1;
1247 View Code Duplication
        if (!isset($row[$headerByKey['sale_type']]) || $row[$headerByKey['sale_type']] == '') {
1248
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1249 10
            $this->addErrors($message);
1250
        } else {
1251
            if (preg_match('/^\d+$/', $row[$headerByKey['sale_type']])) {
1252
                $SaleType = $this->saleTypeRepository->find($row[$headerByKey['sale_type']]);
1253
                if (!$SaleType) {
1254 10
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1255
                    $this->addErrors($message);
1256
                } else {
1257
                    $ProductClass->setSaleType($SaleType);
1258
                }
1259 10
            } else {
1260
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['sale_type']]);
1261
                $this->addErrors($message);
1262
            }
1263
        }
1264 10
1265
        // 規格分類1、2をそれぞれセットし作成
1266 View Code Duplication
        if (isset($row[$headerByKey['class_category1']]) && $row[$headerByKey['class_category1']] != '') {
1267
            if (preg_match('/^\d+$/', $row[$headerByKey['class_category1']])) {
1268
                $ClassCategory = $this->classCategoryRepository->find($row[$headerByKey['class_category1']]);
1269 10
                if (!$ClassCategory) {
1270
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
1271
                    $this->addErrors($message);
1272
                } else {
1273
                    $ProductClass->setClassCategory1($ClassCategory);
1274 10
                }
1275
            } else {
1276
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category1']]);
1277
                $this->addErrors($message);
1278
            }
1279 10
        }
1280
1281 View Code Duplication
        if (isset($row[$headerByKey['class_category2']]) && $row[$headerByKey['class_category2']] != '') {
1282
            if (preg_match('/^\d+$/', $row[$headerByKey['class_category2']])) {
1283
                $ClassCategory = $this->classCategoryRepository->find($row[$headerByKey['class_category2']]);
1284 10
                if (!$ClassCategory) {
1285
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
1286
                    $this->addErrors($message);
1287
                } else {
1288
                    $ProductClass->setClassCategory2($ClassCategory);
1289 10
                }
1290
            } else {
1291
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['class_category2']]);
1292
                $this->addErrors($message);
1293
            }
1294 10
        }
1295
1296 View Code Duplication
        if (isset($row[$headerByKey['delivery_date']]) && $row[$headerByKey['delivery_date']] != '') {
1297
            if (preg_match('/^\d+$/', $row[$headerByKey['delivery_date']])) {
1298
                $DeliveryDuration = $this->deliveryDurationRepository->find($row[$headerByKey['delivery_date']]);
1299 10
                if (!$DeliveryDuration) {
1300
                    $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
1301
                    $this->addErrors($message);
1302
                } else {
1303
                    $ProductClass->setDeliveryDuration($DeliveryDuration);
1304
                }
1305
            } else {
1306
                $message = trans('admin.common.csv_invalid_not_found', ['%line%' => $line, '%name%' => $headerByKey['delivery_date']]);
1307
                $this->addErrors($message);
1308
            }
1309
        }
1310 6
1311 View Code Duplication
        if (isset($row[$headerByKey['product_code']]) && StringUtil::isNotBlank($row[$headerByKey['product_code']])) {
1312
            $ProductClass->setCode(StringUtil::trimAll($row[$headerByKey['product_code']]));
1313 6
        } else {
1314
            $ProductClass->setCode(null);
1315
        }
1316
1317 View Code Duplication
        if (!isset($row[$headerByKey['stock_unlimited']])
1318 6
            || StringUtil::isBlank($row[$headerByKey['stock_unlimited']])
1319
            || $row[$headerByKey['stock_unlimited']] == (string) Constant::DISABLED
1320
        ) {
1321
            $ProductClass->setStockUnlimited(false);
1322
            // 在庫数が設定されていなければエラー
1323 6
            if ($row[$headerByKey['stock']] == '') {
1324
                $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
1325
                $this->addErrors($message);
1326
            } else {
1327
                $stock = str_replace(',', '', $row[$headerByKey['stock']]);
1328 6
                if (preg_match('/^\d+$/', $stock) && $stock >= 0) {
1329
                    $ProductClass->setStock($row[$headerByKey['stock']]);
1330
                } else {
1331
                    $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['stock']]);
1332
                    $this->addErrors($message);
1333
                }
1334
            }
1335
        } elseif ($row[$headerByKey['stock_unlimited']] == (string) Constant::ENABLED) {
1336
            $ProductClass->setStockUnlimited(true);
1337
            $ProductClass->setStock(null);
1338
        } else {
1339
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['stock_unlimited']]);
1340
            $this->addErrors($message);
1341
        }
1342
1343 View Code Duplication
        if (isset($row[$headerByKey['sale_limit']]) && $row[$headerByKey['sale_limit']] != '') {
1344
            $saleLimit = str_replace(',', '', $row[$headerByKey['sale_limit']]);
1345 4
            if (preg_match('/^\d+$/', $saleLimit) && $saleLimit >= 0) {
1346
                $ProductClass->setSaleLimit($saleLimit);
1347 4
            } else {
1348 4
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['sale_limit']]);
1349 4
                $this->addErrors($message);
1350 4
            }
1351 4
        }
1352 4
1353
        if (isset($row[$headerByKey['price01']]) && $row[$headerByKey['price01']] != '') {
1354 4
            $price01 = str_replace(',', '', $row[$headerByKey['price01']]);
1355
            $errors = $this->validator->validate($price01, new GreaterThanOrEqual(['value' => 0]));
1356
            if ($errors->count() === 0) {
1357
                $ProductClass->setPrice01($price01);
1358
            } else {
1359
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price01']]);
1360
                $this->addErrors($message);
1361
            }
1362
        }
1363
1364 View Code Duplication
        if (!isset($row[$headerByKey['price02']]) || $row[$headerByKey['price02']] == '') {
1365
            $message = trans('admin.common.csv_invalid_required', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1366
            $this->addErrors($message);
1367
        } else {
1368
            $price02 = str_replace(',', '', $row[$headerByKey['price02']]);
1369
            $errors = $this->validator->validate($price02, new GreaterThanOrEqual(['value' => 0]));
1370
            if ($errors->count() === 0) {
1371
                $ProductClass->setPrice02($price02);
1372
            } else {
1373
                $message = trans('admin.common.csv_invalid_greater_than_zero', ['%line%' => $line, '%name%' => $headerByKey['price02']]);
1374
                $this->addErrors($message);
1375
            }
1376
        }
1377
1378
        $ProductStock = $ProductClass->getProductStock();
1379
1380
        if (!$ProductClass->isStockUnlimited()) {
1381
            $ProductStock->setStock($ProductClass->getStock());
1382
        } else {
1383
            // 在庫無制限時はnullを設定
1384
            $ProductStock->setStock(null);
1385
        }
1386
1387
        return $ProductClass;
1388
    }
1389
1390
    /**
1391
     * 登録、更新時のエラー画面表示
1392
     */
1393
    protected function addErrors($message)
1394
    {
1395
        $this->errors[] = $message;
1396
    }
1397
1398
    /**
1399
     * @return array
1400
     */
1401
    protected function getErrors()
1402
    {
1403
        return $this->errors;
1404
    }
1405
1406
    /**
1407
     * @return boolean
1408
     */
1409
    protected function hasErrors()
1410
    {
1411
        return count($this->getErrors()) > 0;
1412
    }
1413
1414
    /**
1415
     * 商品登録CSVヘッダー定義
1416
     *
1417
     * @return array
1418
     */
1419
    protected function getProductCsvHeader()
1420
    {
1421
        return [
1422
            trans('admin.product.product_csv.product_id_col') => [
1423
                'id' => 'id',
1424
                'description' => 'admin.product.product_csv.product_id_description',
1425
                'required' => false,
1426
            ],
1427
            trans('admin.product.product_csv.display_status_col') => [
1428
                'id' => 'status',
1429
                'description' => 'admin.product.product_csv.display_status_description',
1430
                'required' => true,
1431
            ],
1432
            trans('admin.product.product_csv.product_name_col') => [
1433
                'id' => 'name',
1434
                'description' => 'admin.product.product_csv.product_name_description',
1435
                'required' => true,
1436
            ],
1437
            trans('admin.product.product_csv.shop_memo_col') => [
1438
                'id' => 'note',
1439
                'description' => 'admin.product.product_csv.shop_memo_description',
1440
                'required' => false,
1441
            ],
1442
            trans('admin.product.product_csv.description_list_col') => [
1443
                'id' => 'description_list',
1444
                'description' => 'admin.product.product_csv.description_list_description',
1445
                'required' => false,
1446
            ],
1447
            trans('admin.product.product_csv.description_detail_col') => [
1448
                'id' => 'description_detail',
1449
                'description' => 'admin.product.product_csv.description_detail_description',
1450
                'required' => false,
1451
            ],
1452
            trans('admin.product.product_csv.keyword_col') => [
1453
                'id' => 'search_word',
1454
                'description' => 'admin.product.product_csv.keyword_description',
1455
                'required' => false,
1456
            ],
1457
            trans('admin.product.product_csv.free_area_col') => [
1458
                'id' => 'free_area',
1459
                'description' => 'admin.product.product_csv.free_area_description',
1460
                'required' => false,
1461
            ],
1462
            trans('admin.product.product_csv.delete_flag_col') => [
1463
                'id' => 'product_del_flg',
1464
                'description' => 'admin.product.product_csv.delete_flag_description',
1465
                'required' => false,
1466
            ],
1467
            trans('admin.product.product_csv.product_image_col') => [
1468
                'id' => 'product_image',
1469
                'description' => 'admin.product.product_csv.product_image_description',
1470
                'required' => false,
1471
            ],
1472
            trans('admin.product.product_csv.category_col') => [
1473
                'id' => 'product_category',
1474
                'description' => 'admin.product.product_csv.category_description',
1475
                'required' => false,
1476
            ],
1477
            trans('admin.product.product_csv.tag_col') => [
1478
                'id' => 'product_tag',
1479
                'description' => 'admin.product.product_csv.tag_description',
1480
                'required' => false,
1481
            ],
1482
            trans('admin.product.product_csv.sale_type_col') => [
1483
                'id' => 'sale_type',
1484
                'description' => 'admin.product.product_csv.sale_type_description',
1485
                'required' => true,
1486
            ],
1487
            trans('admin.product.product_csv.class_category1_col') => [
1488
                'id' => 'class_category1',
1489
                'description' => 'admin.product.product_csv.class_category1_description',
1490
                'required' => false,
1491
            ],
1492
            trans('admin.product.product_csv.class_category2_col') => [
1493
                'id' => 'class_category2',
1494
                'description' => 'admin.product.product_csv.class_category2_description',
1495
                'required' => false,
1496
            ],
1497
            trans('admin.product.product_csv.delivery_duration_col') => [
1498
                'id' => 'delivery_date',
1499
                'description' => 'admin.product.product_csv.delivery_duration_description',
1500
                'required' => false,
1501
            ],
1502
            trans('admin.product.product_csv.product_code_col') => [
1503
                'id' => 'product_code',
1504
                'description' => 'admin.product.product_csv.product_code_description',
1505
                'required' => false,
1506
            ],
1507
            trans('admin.product.product_csv.stock_col') => [
1508
                'id' => 'stock',
1509
                'description' => 'admin.product.product_csv.stock_description',
1510
                'required' => false,
1511
            ],
1512
            trans('admin.product.product_csv.stock_unlimited_col') => [
1513
                'id' => 'stock_unlimited',
1514
                'description' => 'admin.product.product_csv.stock_unlimited_description',
1515
                'required' => false,
1516
            ],
1517
            trans('admin.product.product_csv.sale_limit_col') => [
1518
                'id' => 'sale_limit',
1519
                'description' => 'admin.product.product_csv.sale_limit_description',
1520
                'required' => false,
1521
            ],
1522
            trans('admin.product.product_csv.normal_price_col') => [
1523
                'id' => 'price01',
1524
                'description' => 'admin.product.product_csv.normal_price_description',
1525
                'required' => false,
1526
            ],
1527
            trans('admin.product.product_csv.sale_price_col') => [
1528
                'id' => 'price02',
1529
                'description' => 'admin.product.product_csv.sale_price_description',
1530
                'required' => true,
1531
            ],
1532
            trans('admin.product.product_csv.delivery_fee_col') => [
1533
                'id' => 'delivery_fee',
1534
                'description' => 'admin.product.product_csv.delivery_fee_description',
1535
                'required' => false,
1536
            ],
1537
            trans('admin.product.product_csv.tax_rate_col') => [
1538
                'id' => 'tax_rate',
1539
                'description' => 'admin.product.product_csv.tax_rate_description',
1540
                'required' => false,
1541
            ],
1542
        ];
1543
    }
1544
1545
    /**
1546
     * カテゴリCSVヘッダー定義
1547
     */
1548
    protected function getCategoryCsvHeader()
1549
    {
1550
        return [
1551
            trans('admin.product.category_csv.category_id_col') => [
1552
                'id' => 'id',
1553
                'description' => 'admin.product.category_csv.category_id_description',
1554
                'required' => false,
1555
            ],
1556
            trans('admin.product.category_csv.category_name_col') => [
1557
                'id' => 'category_name',
1558
                'description' => 'admin.product.category_csv.category_name_description',
1559
                'required' => true,
1560
            ],
1561
            trans('admin.product.category_csv.parent_category_id_col') => [
1562
                'id' => 'parent_category_id',
1563
                'description' => 'admin.product.category_csv.parent_category_id_description',
1564
                'required' => false,
1565
            ],
1566
            trans('admin.product.category_csv.delete_flag_col') => [
1567
                'id' => 'category_del_flg',
1568
                'description' => 'admin.product.category_csv.delete_flag_description',
1569
                'required' => false,
1570
            ],
1571
        ];
1572
    }
1573
1574
    /**
1575
     * ProductCategory作成
1576
     *
1577
     * @param \Eccube\Entity\Product $Product
1578
     * @param \Eccube\Entity\Category $Category
1579
     * @param int $sortNo
1580
     *
1581
     * @return ProductCategory
1582
     */
1583 View Code Duplication
    private function makeProductCategory($Product, $Category, $sortNo)
0 ignored issues
show
Unused Code introduced by
The parameter $sortNo is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
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...
1584
    {
1585
        $ProductCategory = new ProductCategory();
1586
        $ProductCategory->setProduct($Product);
1587
        $ProductCategory->setProductId($Product->getId());
1588
        $ProductCategory->setCategory($Category);
1589
        $ProductCategory->setCategoryId($Category->getId());
1590
1591
        return $ProductCategory;
1592
    }
1593
1594
    /**
1595
     * @Route("/%eccube_admin_route%/product/csv_split", name="admin_product_csv_split")
1596
     * @param Request $request
1597
     * @return \Symfony\Component\HttpFoundation\JsonResponse
1598
     */
1599
    public function splitCsv(Request $request)
1600
    {
1601
        $this->isTokenValid();
1602
1603
        if (!$request->isXmlHttpRequest()) {
1604
            throw new BadRequestHttpException();
1605
        }
1606
1607
        $form = $this->formFactory->createBuilder(CsvImportType::class)->getForm();
1608
        $form->handleRequest($request);
1609
1610
        if ($form->isSubmitted() && $form->isValid()) {
1611
1612
            $dir = $this->eccubeConfig['eccube_csv_temp_realdir'];
1613
            if (!file_exists($dir)) {
1614
                $fs = new Filesystem();
1615
                $fs->mkdir($dir);
1616
            }
1617
1618
            $data = $form['import_file']->getData();
1619
            $src = new \SplFileObject($data->getRealPath());
1620
            $src->setFlags(\SplFileObject::READ_CSV | \SplFileObject::READ_AHEAD | \SplFileObject::SKIP_EMPTY | \SplFileObject::DROP_NEW_LINE);
1621
1622
            $fileNo = 1;
1623
            $fileName = StringUtil::random(8);
1624
1625
            $dist = new \SplFileObject($dir.'/'.$fileName.$fileNo.'.csv', 'w');
1626
            $header = $src->current();
1627
            $src->next();
1628
            $dist->fputcsv($header);
1629
1630
            while ($row = $src->current()) {
1631
                $dist->fputcsv($row);
1632
                if (($src->key() + $fileNo) % $this->eccubeConfig['eccube_csv_split_lines'] === 0) {
1633
                    \error_log($dir.'/'.$fileName.$fileNo.'.csv');
1634
                    $fileNo++;
1635
                    $dist = new \SplFileObject($dir.'/'.$fileName.$fileNo.'.csv', 'w');
1636
                    $dist->fputcsv($header);
1637
                }
1638
                $src->next();
1639
            }
1640
1641
            return $this->json(['success' => true, 'file_name' => $fileName, 'max_file_no' => $fileNo]);
1642
        }
1643
1644
        return $this->json(['success' => false, 'message' => $form->getErrors(true ,true)]);
1645
    }
1646
1647
    /**
1648
     * @Route("/%eccube_admin_route%/product/csv_split_import", name="admin_product_csv_split_import")
1649
     * @param Request $request
1650
     * @return \Symfony\Component\HttpFoundation\JsonResponse
1651
     */
1652
    public function importCsv(Request $request, CsrfTokenManagerInterface $tokenManager)
1653
    {
1654
        $this->isTokenValid();
1655
1656
        if (!$request->isXmlHttpRequest()) {
1657
            throw new BadRequestHttpException();
1658
        }
1659
1660
        $files = Finder::create()
1661
            ->in($this->eccubeConfig['eccube_csv_temp_realdir'])
1662
            ->name('*.csv')
1663
            ->files();
1664
1665
        $choices = [];
1666
        foreach ($files as $file) {
1667
            $choices[$file->getBaseName()] = true;
1668
        }
1669
1670
        $filename = $request->get('file_name');
1671
        if (!isset($choices[$filename])) {
1672
            throw new BadRequestHttpException();
1673
        }
1674
1675
        $path = $this->eccubeConfig['eccube_csv_temp_realdir'].'/'.$filename;
1676
        $request->files->set('admin_csv_import', ['import_file' => new UploadedFile(
1677
            $path,
1678
            'import.csv',
1679
            'text/csv',
1680
            filesize($path),
1681
            null,
1682
            true
1683
        )]);
1684
1685
        $request->setMethod('POST');
1686
        $request->request->set('admin_csv_import', [
1687
            Constant::TOKEN_NAME => $tokenManager->getToken('admin_csv_import')->getValue(),
1688
            'is_xml_http_request' => true,
1689
            'csv_file_no' => $request->get('file_no'),
1690
        ]);
1691
1692
        return $this->forwardToRoute('admin_product_csv_import');
1693
    }
1694
1695
    protected function convertLineNo($currentLineNo) {
1696
        if ($this->isXmlHttpRequest) {
1697
            return ($this->eccubeConfig['eccube_csv_split_lines'] - 1) * ($this->csvFileNo - 1) + $currentLineNo;
1698
        }
1699
1700
        return $currentLineNo;
1701
    }
1702
}
1703