ProductController   F
last analyzed

Complexity

Total Complexity 84

Size/Duplication

Total Lines 796
Duplicated Lines 5.65 %

Coupling/Cohesion

Components 0
Dependencies 13

Test Coverage

Coverage 64.43%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 45
loc 796
ccs 279
cts 433
cp 0.6443
rs 1.263
c 3
b 0
f 0
wmc 84
lcom 0
cbo 13

8 Methods

Rating   Name   Duplication   Size   Complexity  
D index() 7 141 13
B addImage() 0 38 6
F edit() 27 284 34
C delete() 0 89 11
C copy() 0 94 9
A display() 0 14 2
C export() 0 102 8
A createProductCategory() 11 11 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ProductController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ProductController, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * This file is part of EC-CUBE
4
 *
5
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
6
 *
7
 * http://www.lockon.co.jp/
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version 2
12
 * of the License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
 */
23
24
25
namespace Eccube\Controller\Admin\Product;
26
27
use Eccube\Application;
28
use Eccube\Common\Constant;
29
use Eccube\Controller\AbstractController;
30
use Eccube\Entity\Master\CsvType;
31
use Eccube\Entity\ProductTag;
32
use Eccube\Event\EccubeEvents;
33
use Eccube\Event\EventArgs;
34
use Eccube\Service\CsvExportService;
35
use Symfony\Component\Filesystem\Filesystem;
36
use Symfony\Component\HttpFoundation\File\File;
37
use Symfony\Component\HttpFoundation\Request;
38
use Symfony\Component\HttpFoundation\StreamedResponse;
39
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
40
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
41
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
42
43
class ProductController extends AbstractController
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
44 7
{
45
    public function index(Application $app, Request $request, $page_no = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
46
    {
47 7
48
        $session = $app['session'];
49 7
50 7
        $builder = $app['form.factory']
51
            ->createBuilder('admin_search_product');
52 7
53
        $event = new EventArgs(
54 7
            array(
55
                'builder' => $builder,
56
            ),
57
            $request
58 7
        );
59
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_INDEX_INITIALIZE, $event);
60 7
61
        $searchForm = $builder->getForm();
62 7
63
        $pagination = array();
64 7
65 7
        $disps = $app['eccube.repository.master.disp']->findAll();
66 7
        $pageMaxis = $app['eccube.repository.master.page_max']->findAll();
67 7
        $page_count = $app['config']['default_page_count'];
68 7
        $page_status = null;
69
        $active = false;
70 7
71
        if ('POST' === $request->getMethod()) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
72 5
73
            $searchForm->handleRequest($request);
74 5
75 5
            if ($searchForm->isValid()) {
76
                $searchData = $searchForm->getData();
77
78 5
                // paginator
79 5
                $qb = $app['eccube.repository.product']->getQueryBuilderBySearchDataForAdmin($searchData);
80
                $page_no = 1;
81 5
82
                $event = new EventArgs(
83 5
                    array(
84 5
                        'qb' => $qb,
85
                        'searchData' => $searchData,
86
                    ),
87
                    $request
88 5
                );
89 5
                $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_INDEX_SEARCH, $event);
90
                $searchData = $event->getArgument('searchData');
91 5
92
                $pagination = $app['paginator']()->paginate(
93
                    $qb,
94
                    $page_no,
95 5
                    $page_count,
96
                    array('wrap-queries' => true)
97
                );
98
99 5
                // sessionのデータ保持
100 5
                $session->set('eccube.admin.product.search', $searchData);
101
                $session->set('eccube.admin.product.search.page_no', $page_no);
102
            }
103 2
        } else {
104
            if (is_null($page_no) && $request->get('resume') != Constant::ENABLED) {
105 2
                // sessionを削除
106 2
                $session->remove('eccube.admin.product.search');
107
                $session->remove('eccube.admin.product.search.page_no');
108
            } else {
109
                // pagingなどの処理
110
                $searchData = $session->get('eccube.admin.product.search');
111
                if (is_null($page_no)) {
112
                    $page_no = intval($session->get('eccube.admin.product.search.page_no'));
113
                } else {
114
                    $session->set('eccube.admin.product.search.page_no', $page_no);
115
                }
116
                if (!is_null($searchData)) {
117
                    // 公開ステータス
118
                    // 1:公開, 2:非公開, 3:在庫なし
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
119
                    $status = $request->get('status');
120
                    if (empty($status)) {
121
                        $searchData['link_status'] = null;
122
                        $searchData['stock_status'] = null;
123
                    } else {
124
                        $searchData['link_status'] = $app['eccube.repository.master.disp']->find($status);
125
                        $searchData['stock_status'] = null;
126
                        if ($status == $app['config']['admin_product_stock_status']) {
127
                            // 在庫なし
128
                            $searchData['link_status'] = null;
129
                            $searchData['stock_status'] = Constant::DISABLED;
130
                        }
131
                        $page_status = $status;
132
                    }
133
                    $session->set('eccube.admin.product.search', $searchData);
134
135
                    // 表示件数
136
                    $page_count = $request->get('page_count', $page_count);
137
138
                    $qb = $app['eccube.repository.product']->getQueryBuilderBySearchDataForAdmin($searchData);
139
140
                    $event = new EventArgs(
141
                        array(
142
                            'qb' => $qb,
143
                            'searchData' => $searchData,
144
                        ),
145
                        $request
146
                    );
147
                    $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_INDEX_SEARCH, $event);
148
                    $searchData = $event->getArgument('searchData');
149
150
                    $pagination = $app['paginator']()->paginate(
151
                        $qb,
152
                        $page_no,
153
                        $page_count,
154
                        array('wrap-queries' => true)
155
                    );
156
157
                    // セッションから検索条件を復元(カテゴリ)
158
                    if (!empty($searchData['category_id'])) {
159
                        $searchData['category_id'] = $app['eccube.repository.category']->find($searchData['category_id']);
160
                    }
161
162
                    // セッションから検索条件を復元(スーテタス)
163 View Code Duplication
                    if (isset($searchData['status']) && count($searchData['status']) > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
164
                        $status_ids = array();
165
                        foreach ($searchData['status'] as $Status) {
166
                            $status_ids[] = $Status->getId();
167
                        }
168
                        $searchData['status'] = $app['eccube.repository.master.disp']->findBy(array('id' => $status_ids));
169
                    }
170
                    $searchForm->setData($searchData);
171
                }
172
            }
173
        }
174 7
175 7
        return $app->render('Product/index.twig', array(
176 7
            'searchForm' => $searchForm->createView(),
177 7
            'pagination' => $pagination,
178 7
            'disps' => $disps,
179 7
            'pageMaxis' => $pageMaxis,
180 7
            'page_no' => $page_no,
181 7
            'page_status' => $page_status,
182 7
            'page_count' => $page_count,
183
            'active' => $active,
184
        ));
185
    }
186
187
    public function addImage(Application $app, Request $request)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
188
    {
189
        if (!$request->isXmlHttpRequest()) {
190
            throw new BadRequestHttpException('リクエストが不正です');
191
        }
192
193
        $images = $request->files->get('admin_product');
194
195
        $files = array();
196
        if (count($images) > 0) {
197
            foreach ($images as $img) {
198
                foreach ($img as $image) {
199
                    //ファイルフォーマット検証
200
                    $mimeType = $image->getMimeType();
201
                    if (0 !== strpos($mimeType, 'image')) {
202
                        throw new UnsupportedMediaTypeHttpException('ファイル形式が不正です');
203
                    }
204
205
                    $extension = $image->getClientOriginalExtension();
206
                    $filename = date('mdHis') . uniqid('_') . '.' . $extension;
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
207
                    $image->move($app['config']['image_temp_realdir'], $filename);
208
                    $files[] = $filename;
209
                }
210
            }
211
        }
212
213
        $event = new EventArgs(
214
            array(
215
                'images' => $images,
216
                'files' => $files,
217
            ),
218
            $request
219
        );
220
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_ADD_IMAGE_COMPLETE, $event);
221
        $files = $event->getArgument('files');
222
223
        return $app->json(array('files' => $files), 200);
224
    }
225 19
226
    public function edit(Application $app, Request $request, $id = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
227 19
    {
228 19
        $has_class = false;
229 6
        if (is_null($id)) {
230 6
            $Product = new \Eccube\Entity\Product();
231 6
            $ProductClass = new \Eccube\Entity\ProductClass();
232
            $Disp = $app['eccube.repository.master.disp']->find(\Eccube\Entity\Master\Disp::DISPLAY_HIDE);
233 6
            $Product
234 6
                ->setDelFlg(Constant::DISABLED)
235 6
                ->addProductClass($ProductClass)
236
                ->setStatus($Disp);
237 6
            $ProductClass
238 6
                ->setDelFlg(Constant::DISABLED)
239 6
                ->setStockUnlimited(true)
240 6
                ->setProduct($Product);
241 6
            $ProductStock = new \Eccube\Entity\ProductStock();
242 6
            $ProductClass->setProductStock($ProductStock);
243
            $ProductStock->setProductClass($ProductClass);
244 13
        } else {
245 13
            $Product = $app['eccube.repository.product']->find($id);
246
            if (!$Product) {
247
                throw new NotFoundHttpException();
248
            }
249 13
            // 規格あり商品か
250 13
            $has_class = $Product->hasProductClass();
251 11
            if (!$has_class) {
252 11
                $ProductClasses = $Product->getProductClasses();
253 11
                $ProductClass = $ProductClasses[0];
254 11
                $BaseInfo = $app['eccube.repository.base_info']->get();
255 6 View Code Duplication
                if ($BaseInfo->getOptionProductTaxRule() == Constant::ENABLED && $ProductClass->getTaxRule() && !$ProductClass->getTaxRule()->getDelFlg()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
256
                    $ProductClass->setTaxRate($ProductClass->getTaxRule()->getTaxRate());
257 11
                }
258
                $ProductStock = $ProductClasses[0]->getProductStock();
259
            }
260
        }
261 19
262 19
        $builder = $app['form.factory']
263
            ->createBuilder('admin_product', $Product);
264
265 19
        // 規格あり商品の場合、規格関連情報をFormから除外
266 2
        if ($has_class) {
267
            $builder->remove('class');
268
        }
269 19
270
        $event = new EventArgs(
271 19
            array(
272 19
                'builder' => $builder,
273
                'Product' => $Product,
274
            ),
275
            $request
276 19
        );
277
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_INITIALIZE, $event);
278 19
279
        $form = $builder->getForm();
280 19
281 17
        if (!$has_class) {
282 17
            $ProductClass->setStockUnlimited((boolean)$ProductClass->getStockUnlimited());
0 ignored issues
show
Bug introduced by
The variable $ProductClass does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Coding Style introduced by
As per coding-style, a cast statement should be followed by a single space.
Loading history...
283
            $form['class']->setData($ProductClass);
284
        }
285
286 19
        // ファイルの登録
287 19
        $images = array();
288 19
        $ProductImages = $Product->getProductImage();
289 19
        foreach ($ProductImages as $ProductImage) {
290
            $images[] = $ProductImage->getFileName();
291 19
        }
292
        $form['images']->setData($images);
293 19
294 19
        $categories = array();
295 19
        $ProductCategories = $Product->getProductCategories();
296
        foreach ($ProductCategories as $ProductCategory) {
297 19
            /* @var $ProductCategory \Eccube\Entity\ProductCategory */
298
            $categories[] = $ProductCategory->getCategory();
299 19
        }
300
        $form['Category']->setData($categories);
301 19
302 19
        $Tags = array();
303 19
        $ProductTags = $Product->getProductTag();
304 19
        foreach ($ProductTags as $ProductTag) {
305
            $Tags[] = $ProductTag->getTag();
306 19
        }
307
        $form['Tag']->setData($Tags);
308 19
309 14
        if ('POST' === $request->getMethod()) {
310 14
            $form->handleRequest($request);
311 14
            if ($form->isValid()) {
312 14
                log_info('商品登録開始', array($id));
313
                $Product = $form->getData();
314 14
315 14
                if (!$has_class) {
316
                    $ProductClass = $form['class']->getData();
317
318 14
                    // 個別消費税
319 14
                    $BaseInfo = $app['eccube.repository.base_info']->get();
320 12
                    if ($BaseInfo->getOptionProductTaxRule() == Constant::ENABLED) {
321 8
                        if ($ProductClass->getTaxRate() !== null) {
322 4 View Code Duplication
                            if ($ProductClass->getTaxRule()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
323
                                if ($ProductClass->getTaxRule()->getDelFlg() == Constant::ENABLED) {
324
                                    $ProductClass->getTaxRule()->setDelFlg(Constant::DISABLED);
325
                                }
326 4
327
                                $ProductClass->getTaxRule()->setTaxRate($ProductClass->getTaxRate());
328 4
                            } else {
329 4
                                $taxrule = $app['eccube.repository.tax_rule']->newTaxRule();
330 4
                                $taxrule->setTaxRate($ProductClass->getTaxRate());
331 4
                                $taxrule->setApplyDate(new \DateTime());
332 4
                                $taxrule->setProduct($Product);
333 8
                                $taxrule->setProductClass($ProductClass);
334
                                $ProductClass->setTaxRule($taxrule);
335
                            }
336 4
                        } else {
337 2
                            if ($ProductClass->getTaxRule()) {
338
                                $ProductClass->getTaxRule()->setDelFlg(Constant::ENABLED);
339
                            }
340
                        }
341 14
                    }
342
                    $app['orm.em']->persist($ProductClass);
343
344 14
                    // 在庫情報を作成
345
                    if (!$ProductClass->getStockUnlimited()) {
346
                        $ProductStock->setStock($ProductClass->getStock());
0 ignored issues
show
Bug introduced by
The variable $ProductStock does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
347
                    } else {
348 14
                        // 在庫無制限時はnullを設定
349
                        $ProductStock->setStock(null);
350 14
                    }
351
                    $app['orm.em']->persist($ProductStock);
352
                }
353
354
                // カテゴリの登録
355
                // 一度クリア
356 14
                /* @var $Product \Eccube\Entity\Product */
357 11
                foreach ($Product->getProductCategories() as $ProductCategory) {
358 14
                    $Product->removeProductCategory($ProductCategory);
359
                    $app['orm.em']->remove($ProductCategory);
360 14
                }
361 14
                $app['orm.em']->persist($Product);
362
                $app['orm.em']->flush();
363 14
364 14
                $count = 1;
365 14
                $Categories = $form->get('Category')->getData();
366 14
                $categoriesIdList = array();
367
                foreach ($Categories as $Category) {
368 View Code Duplication
                    foreach($Category->getPath() as $ParentCategory){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
369
                        if (!isset($categoriesIdList[$ParentCategory->getId()])){
370
                            $ProductCategory = $this->createProductCategory($Product, $ParentCategory, $count);
371
                            $app['orm.em']->persist($ProductCategory);
372
                            $count++;
373
                            /* @var $Product \Eccube\Entity\Product */
374
                            $Product->addProductCategory($ProductCategory);
375
                            $categoriesIdList[$ParentCategory->getId()] = true;
376
                        }
377
                    }
378
                    if (!isset($categoriesIdList[$Category->getId()])){
379
                        $ProductCategory = $this->createProductCategory($Product, $Category, $count);
380
                        $app['orm.em']->persist($ProductCategory);
381
                        $count++;
382
                        /* @var $Product \Eccube\Entity\Product */
383 14
                        $Product->addProductCategory($ProductCategory);
384
                        $categoriesIdList[$Category->getId()] = true;
385
                    }
386
                }
387
388 14
                // 画像の登録
389 14
                $add_images = $form->get('add_images')->getData();
390
                foreach ($add_images as $add_image) {
391
                    $ProductImage = new \Eccube\Entity\ProductImage();
392
                    $ProductImage
393
                        ->setFileName($add_image)
394
                        ->setProduct($Product)
395
                        ->setRank(1);
396
                    $Product->addProductImage($ProductImage);
397
                    $app['orm.em']->persist($ProductImage);
398
399
                    // 移動
400 14
                    $file = new File($app['config']['image_temp_realdir'] . '/' . $add_image);
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
401
                    $file->move($app['config']['image_save_realdir']);
402
                }
403
404 14
                // 画像の削除
405 14
                $delete_images = $form->get('delete_images')->getData();
406
                foreach ($delete_images as $delete_image) {
407
                    $ProductImage = $app['eccube.repository.product_image']
408
                        ->findOneBy(array('file_name' => $delete_image));
409
410
                    // 追加してすぐに削除した画像は、Entityに追加されない
411
                    if ($ProductImage instanceof \Eccube\Entity\ProductImage) {
0 ignored issues
show
Bug introduced by
The class Eccube\Entity\ProductImage does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
412
                        $Product->removeProductImage($ProductImage);
413
                        $app['orm.em']->remove($ProductImage);
414
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
415
                    }
416
                    $app['orm.em']->persist($Product);
417
418
                    // 削除
419 14
                    $fs = new Filesystem();
420
                    $fs->remove($app['config']['image_save_realdir'] . '/' . $delete_image);
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
421 14
                }
422 14
                $app['orm.em']->persist($Product);
423
                $app['orm.em']->flush();
424
425 14
426 14
                $ranks = $request->get('rank_images');
427
                if ($ranks) {
428
                    foreach ($ranks as $rank) {
429
                        list($filename, $rank_val) = explode('//', $rank);
430
                        $ProductImage = $app['eccube.repository.product_image']
431
                            ->findOneBy(array(
432
                                'file_name' => $filename,
433
                                'Product' => $Product,
434
                            ));
435
                        $ProductImage->setRank($rank_val);
436
                        $app['orm.em']->persist($ProductImage);
437
                    }
438 14
                }
439
                $app['orm.em']->flush();
440
441
                // 商品タグの登録
442 14
                // 商品タグを一度クリア
443 14
                $ProductTags = $Product->getProductTag();
444
                foreach ($ProductTags as $ProductTag) {
445 14
                    $Product->removeProductTag($ProductTag);
446
                    $app['orm.em']->remove($ProductTag);
447
                }
448
449 14
                // 商品タグの登録
450 14
                $Tags = $form->get('Tag')->getData();
451 14
                foreach ($Tags as $Tag) {
452
                    $ProductTag = new ProductTag();
453 14
                    $ProductTag
454 14
                        ->setProduct($Product)
455 14
                        ->setTag($Tag);
456 14
                    $Product->addProductTag($ProductTag);
457
                    $app['orm.em']->persist($ProductTag);
458
                }
459 14
460 14
                $Product->setUpdateDate(new \DateTime());
461
                $app['orm.em']->flush();
462 14
463
                log_info('商品登録完了', array($id));
464 14
465
                $event = new EventArgs(
466 14
                    array(
467 14
                        'form' => $form,
468
                        'Product' => $Product,
469
                    ),
470
                    $request
471 14
                );
472
                $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_COMPLETE, $event);
473 14
474
                $app->addSuccess('admin.register.complete', 'admin');
475 14
476
                return $app->redirect($app->url('admin_product_product_edit', array('id' => $Product->getId())));
477
            } else {
478
                log_info('商品登録チェックエラー', array($id));
479
                $app->addError('admin.register.failed', 'admin');
480
            }
481
        }
482
483 5
        // 検索結果の保持
484 5
        $builder = $app['form.factory']
485
            ->createBuilder('admin_search_product');
486 5
487
        $event = new EventArgs(
488 5
            array(
489 5
                'builder' => $builder,
490
                'Product' => $Product,
491
            ),
492
            $request
493 5
        );
494
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_SEARCH, $event);
495 5
496
        $searchForm = $builder->getForm();
497 5
498
        if ('POST' === $request->getMethod()) {
499
            $searchForm->handleRequest($request);
500
        }
501 5
502 5
        return $app->render('Product/product.twig', array(
503 5
            'Product' => $Product,
504 5
            'form' => $form->createView(),
505 5
            'searchForm' => $searchForm->createView(),
506 5
            'has_class' => $has_class,
507
            'id' => $id,
508
        ));
509
    }
510 2
511
    public function delete(Application $app, Request $request, $id = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
512 2
    {
513 2
        $this->isTokenValid($app);
514 2
        $session = $request->getSession();
515 2
        $page_no = intval($session->get('eccube.admin.product.search.page_no'));
516
        $page_no = $page_no ? $page_no : Constant::ENABLED;
517 2
518
        if (!is_null($id)) {
519 2
            /* @var $Product \Eccube\Entity\Product */
520 2
            $Product = $app['eccube.repository.product']->find($id);
521
            if (!$Product) {
522
                $app->deleteMessage();
523
                return $app->redirect($app->url('admin_product_page', array('page_no' => $page_no)).'?resume='.Constant::ENABLED);
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
524
            }
525 2
526 2
            if ($Product instanceof \Eccube\Entity\Product) {
0 ignored issues
show
Bug introduced by
The class Eccube\Entity\Product does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
527
                log_info('商品削除開始', array($id));
528 2
529
                $Product->setDelFlg(Constant::ENABLED);
530 2
531 2
                $ProductClasses = $Product->getProductClasses();
532 2
                $deleteImages = array();
533 2
                foreach ($ProductClasses as $ProductClass) {
534 2
                    $ProductClass->setDelFlg(Constant::ENABLED);
535
                    $Product->removeProductClass($ProductClass);
536 2
537 2
                    $ProductClasses = $Product->getProductClasses();
538 2
                    foreach ($ProductClasses as $ProductClass) {
539 2
                        $ProductClass->setDelFlg(Constant::ENABLED);
540
                        $Product->removeProductClass($ProductClass);
541 2
542 2
                        $ProductStock = $ProductClass->getProductStock();
543
                        $app['orm.em']->remove($ProductStock);
544
                    }
545 2
546 2
                    $ProductImages = $Product->getProductImage();
547 2
                    foreach ($ProductImages as $ProductImage) {
548 2
                        $Product->removeProductImage($ProductImage);
549 2
                        $deleteImages[] = $ProductImage->getFileName();
550
                        $app['orm.em']->remove($ProductImage);
551
                    }
552 2
553 2
                    $ProductCategories = $Product->getProductCategories();
554 2
                    foreach ($ProductCategories as $ProductCategory) {
555 2
                        $Product->removeProductCategory($ProductCategory);
556
                        $app['orm.em']->remove($ProductCategory);
557
                    }
558
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
559
                }
560 2
561
                $app['orm.em']->persist($Product);
562 2
563
                $app['orm.em']->flush();
564 2
565
                $event = new EventArgs(
566 2
                    array(
567 2
                        'Product' => $Product,
568 2
                        'ProductClass' => $ProductClasses,
569
                        'deleteImages' => $deleteImages,
570
                    ),
571
                    $request
572 2
                );
573 2
                $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_DELETE_COMPLETE, $event);
574
                $deleteImages = $event->getArgument('deleteImages');
575
576 2
                // 画像ファイルの削除(commit後に削除させる)
577
                foreach ($deleteImages as $deleteImage) {
578 2
                    try {
579 2
                        $fs = new Filesystem();
580 2
                        $fs->remove($app['config']['image_save_realdir'] . '/' . $deleteImage);
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
581
                    } catch (\Exception $e) {
582
                        // エラーが発生しても無視する
583
                    }
584
                }
585 2
586
                log_info('商品削除完了', array($id));
587 2
588
                $app->addSuccess('admin.delete.complete', 'admin');
589
            } else {
590 2
                log_info('商品削除エラー', array($id));
591
                $app->addError('admin.delete.failed', 'admin');
592
            }
593
        } else {
594
            log_info('商品削除エラー', array($id));
595
            $app->addError('admin.delete.failed', 'admin');
596
        }
597 2
598
        return $app->redirect($app->url('admin_product_page', array('page_no' => $page_no)).'?resume='.Constant::ENABLED);
599
    }
600 2
601
    public function copy(Application $app, Request $request, $id = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
602 2
    {
603
        $this->isTokenValid($app);
604 2
605 2
        if (!is_null($id)) {
606 2
            $Product = $app['eccube.repository.product']->find($id);
607 2
            if ($Product instanceof \Eccube\Entity\Product) {
0 ignored issues
show
Bug introduced by
The class Eccube\Entity\Product does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
608 2
                $CopyProduct = clone $Product;
609 2
                $CopyProduct->copy();
610 2
                $Disp = $app['eccube.repository.master.disp']->find(\Eccube\Entity\Master\Disp::DISPLAY_HIDE);
611
                $CopyProduct->setStatus($Disp);
612 2
613 2
                $CopyProductCategories = $CopyProduct->getProductCategories();
614 2
                foreach ($CopyProductCategories as $Category) {
615
                    $app['orm.em']->persist($Category);
616
                }
617
618 2
                // 規格あり商品の場合は, デフォルトの商品規格を取得し登録する.
619 2
                if ($CopyProduct->hasProductClass()) {
620 2
                    $softDeleteFilter = $app['orm.em']->getFilters()->getFilter('soft_delete');
621
                    $softDeleteFilter->setExcludes(array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
622 2
                        'Eccube\Entity\ProductClass'
623 2
                    ));
624 2
                    $dummyClass = $app['eccube.repository.product_class']->findOneBy(array(
625
                        'del_flg' => \Eccube\Common\Constant::ENABLED,
626
                        'ClassCategory1' => null,
627 2
                        'ClassCategory2' => null,
628
                        'Product' => $Product,
629 2
                    ));
630 2
                    $dummyClass = clone $dummyClass;
631 2
                    $dummyClass->setProduct($CopyProduct);
632 2
                    $CopyProduct->addProductClass($dummyClass);
633
                    $softDeleteFilter->setExcludes(array());
634
                }
635 2
636 2
                $CopyProductClasses = $CopyProduct->getProductClasses();
637 2
                foreach ($CopyProductClasses as $Class) {
638 2
                    $Stock = $Class->getProductStock();
639 2
                    $CopyStock = clone $Stock;
640 2
                    $CopyStock->setProductClass($Class);
641
                    $app['orm.em']->persist($CopyStock);
642 2
643
                    $app['orm.em']->persist($Class);
644 2
                }
645 2
                $Images = $CopyProduct->getProductImage();
646
                foreach ($Images as $Image) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
647
648 2
                    // 画像ファイルを新規作成
649 2
                    $extension = pathinfo($Image->getFileName(), PATHINFO_EXTENSION);
650
                    $filename = date('mdHis') . uniqid('_') . '.' . $extension;
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
651 2
                    try {
652 2
                        $fs = new Filesystem();
653 2
                        $fs->copy($app['config']['image_save_realdir'] . '/' . $Image->getFileName(), $app['config']['image_save_realdir'] . '/' . $filename);
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
654
                    } catch (\Exception $e) {
655
                        // エラーが発生しても無視する
656 2
                    }
657
                    $Image->setFileName($filename);
658 2
659
                    $app['orm.em']->persist($Image);
660 2
                }
661 2
                $Tags = $CopyProduct->getProductTag();
662 2
                foreach ($Tags as $Tag) {
663
                    $app['orm.em']->persist($Tag);
664
                }
665 2
666
                $app['orm.em']->persist($CopyProduct);
667 2
668
                $app['orm.em']->flush();
669 2
670
                $event = new EventArgs(
671 2
                    array(
672 2
                        'Product' => $Product,
673 2
                        'CopyProduct' => $CopyProduct,
674 2
                        'CopyProductCategories' => $CopyProductCategories,
675 2
                        'CopyProductClasses' => $CopyProductClasses,
676 2
                        'images' => $Images,
677
                        'Tags' => $Tags,
678
                    ),
679
                    $request
680 2
                );
681
                $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_COPY_COMPLETE, $event);
682 2
683
                $app->addSuccess('admin.product.copy.complete', 'admin');
684 2
685
                return $app->redirect($app->url('admin_product_product_edit', array('id' => $CopyProduct->getId())));
686
            } else {
687
                $app->addError('admin.product.copy.failed', 'admin');
688
            }
689
        } else {
690
            $app->addError('admin.product.copy.failed', 'admin');
691
        }
692
693
        return $app->redirect($app->url('admin_product'));
694
    }
695 1
696
    public function display(Application $app, Request $request, $id = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
697 1
    {
698 1
        $event = new EventArgs(
699
            array(),
700
            $request
701 1
        );
702
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_DISPLAY_COMPLETE, $event);
703 1
704 1
        if (!is_null($id)) {
705
            return $app->redirect($app->url('product_detail', array('id' => $id, 'admin' => '1')));
706
        }
707
708
        return $app->redirect($app->url('admin_product'));
709
    }
710
711
    /**
712
     * 商品CSVの出力.
713
     *
714
     * @param Application $app
715
     * @param Request $request
0 ignored issues
show
introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
716
     * @return StreamedResponse
717
     */
718
    public function export(Application $app, Request $request)
719
    {
720
        // タイムアウトを無効にする.
721
        set_time_limit(0);
722
723
        // sql loggerを無効にする.
724
        $em = $app['orm.em'];
725
        $em->getConfiguration()->setSQLLogger(null);
726
727
        $response = new StreamedResponse();
728
        $response->setCallback(function () use ($app, $request) {
729
730
            // CSV種別を元に初期化.
731
            $app['eccube.service.csv.export']->initCsvType(CsvType::CSV_TYPE_PRODUCT);
732
733
            // ヘッダ行の出力.
734
            $app['eccube.service.csv.export']->exportHeader();
735
736
            // 商品データ検索用のクエリビルダを取得.
737
            $qb = $app['eccube.service.csv.export']
738
                ->getProductQueryBuilder($request);
739
740
            // Get stock status
741
            $isOutOfStock = 0;
742
            $session = $request->getSession();
743
            if ($session->has('eccube.admin.product.search')) {
744
                $searchData = $session->get('eccube.admin.product.search', array());
745
                if (isset($searchData['stock_status']) && $searchData['stock_status'] === 0) {
746
                    $isOutOfStock = 1;
747
                }
748
            }
749
750
            // joinする場合はiterateが使えないため, select句をdistinctする.
751
            // http://qiita.com/suin/items/2b1e98105fa3ef89beb7
752
            // distinctのmysqlとpgsqlの挙動をあわせる.
753
            // http://uedatakeshi.blogspot.jp/2010/04/distinct-oeder-by-postgresmysql.html
754
            $qb->resetDQLPart('select')
755
                ->resetDQLPart('orderBy')
756
                ->orderBy('p.update_date', 'DESC');
757
758
            if ($isOutOfStock) {
759
                $qb->select('p, pc')
760
                    ->distinct();
761
            } else {
762
                $qb->select('p')
763
                    ->distinct();
764
            }
765
            // データ行の出力.
766
            $app['eccube.service.csv.export']->setExportQueryBuilder($qb);
767
768
            $app['eccube.service.csv.export']->exportData(function ($entity, CsvExportService $csvService) use ($app, $request) {
769
                $Csvs = $csvService->getCsvs();
770
771
                /** @var $Product \Eccube\Entity\Product */
772
                $Product = $entity;
773
774
                /** @var $ProductClassess \Eccube\Entity\ProductClass[] */
775
                $ProductClassess = $Product->getProductClasses();
776
777
                foreach ($ProductClassess as $ProductClass) {
778
                    $ExportCsvRow = new \Eccube\Entity\ExportCsvRow();
779
780
                    // CSV出力項目と合致するデータを取得.
781
                    foreach ($Csvs as $Csv) {
782
                        // 商品データを検索.
783
                        $ExportCsvRow->setData($csvService->getData($Csv, $Product));
784
                        if ($ExportCsvRow->isDataNull()) {
785
                            // 商品規格情報を検索.
786
                            $ExportCsvRow->setData($csvService->getData($Csv, $ProductClass));
787
                        }
788
789
                        $event = new EventArgs(
790
                            array(
791
                                'csvService' => $csvService,
792
                                'Csv' => $Csv,
793
                                'ProductClass' => $ProductClass,
794
                                'ExportCsvRow' => $ExportCsvRow,
795
                            ),
796
                            $request
797
                        );
798
                        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_CSV_EXPORT, $event);
799
800
                        $ExportCsvRow->pushData();
801
                    }
802
803
                    // $row[] = number_format(memory_get_usage(true));
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
804
                    // 出力.
805
                    $csvService->fputcsv($ExportCsvRow->getRow());
806
                }
807
            });
808
        });
809
810
        $now = new \DateTime();
811
        $filename = 'product_' . $now->format('YmdHis') . '.csv';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
812
        $response->headers->set('Content-Type', 'application/octet-stream');
813
        $response->headers->set('Content-Disposition', 'attachment; filename=' . $filename);
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
814
        $response->send();
815
816
        log_info('商品CSV出力ファイル名', array($filename));
817
818
        return $response;
819
    }
820
    
0 ignored issues
show
introduced by
Please trim any trailing whitespace
Loading history...
821
    /**
822
     * ProductCategory作成
823
     * @param \Eccube\Entity\Product $Product
824
     * @param \Eccube\Entity\Category $Category
825
     * @return \Eccube\Entity\ProductCategory
826
     */
827 View Code Duplication
    private function createProductCategory($Product, $Category, $count)
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...
828
    {
829
        $ProductCategory = new \Eccube\Entity\ProductCategory();
830
        $ProductCategory->setProduct($Product);
831
        $ProductCategory->setProductId($Product->getId());
832
        $ProductCategory->setCategory($Category);
833
        $ProductCategory->setCategoryId($Category->getId());
834
        $ProductCategory->setRank($count);
835
        
0 ignored issues
show
introduced by
Please trim any trailing whitespace
Loading history...
836
        return $ProductCategory;
837
    }
838
}
839