ProductController   F
last analyzed

Complexity

Total Complexity 69

Size/Duplication

Total Lines 678
Duplicated Lines 8.41 %

Coupling/Cohesion

Components 0
Dependencies 10

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 69
lcom 0
cbo 10
dl 57
loc 678
rs 1.4894
c 3
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
C index() 7 136 12
B addImage() 0 28 4
F edit() 21 239 28
C delete() 0 80 10
C copy() 0 92 9
A display() 0 14 2
B export() 29 73 4

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\Event\EccubeEvents;
32
use Eccube\Event\EventArgs;
33
use Symfony\Component\Filesystem\Filesystem;
34
use Symfony\Component\HttpFoundation\File\File;
35
use Symfony\Component\HttpFoundation\Request;
36
use Symfony\Component\HttpFoundation\StreamedResponse;
37
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
38
39
class ProductController extends AbstractController
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
40
{
41
    public function index(Application $app, Request $request, $page_no = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
42
    {
43
44
        $session = $app['session'];
45
46
        $builder = $app['form.factory']
47
            ->createBuilder('admin_search_product');
48
49
        $event = new EventArgs(
50
            array(
51
                'builder' => $builder,
52
            ),
53
            $request
54
        );
55
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_INDEX_INITIALIZE, $event);
56
57
        $searchForm = $builder->getForm();
58
59
        $pagination = array();
60
61
        $disps = $app['eccube.repository.master.disp']->findAll();
62
        $pageMaxis = $app['eccube.repository.master.page_max']->findAll();
63
        $page_count = $app['config']['default_page_count'];
64
        $page_status = null;
65
        $active = false;
66
67
        if ('POST' === $request->getMethod()) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
68
69
            $searchForm->handleRequest($request);
70
71
            if ($searchForm->isValid()) {
72
                $searchData = $searchForm->getData();
73
74
                // paginator
75
                $qb = $app['eccube.repository.product']->getQueryBuilderBySearchDataForAdmin($searchData);
76
                $page_no = 1;
77
78
                $event = new EventArgs(
79
                    array(
80
                        'qb' => $qb,
81
                        'searchData' => $searchData,
82
                    ),
83
                    $request
84
                );
85
                $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_INDEX_SEARCH, $event);
86
                $searchData = $event->getArgument('searchData');
87
88
                $pagination = $app['paginator']()->paginate(
89
                    $qb,
90
                    $page_no,
91
                    $page_count,
92
                    array('wrap-queries' => true)
93
                );
94
95
                // sessionのデータ保持
96
                $session->set('eccube.admin.product.search', $searchData);
97
            }
98
        } else {
99
            if (is_null($page_no)) {
100
                // sessionを削除
101
                $session->remove('eccube.admin.product.search');
102
            } else {
103
                // pagingなどの処理
104
                $searchData = $session->get('eccube.admin.product.search');
105
                if (!is_null($searchData)) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
106
107
                    // 公開ステータス
108
                    $status = $request->get('status');
109
                    if (!empty($status)) {
110
                        if ($status != $app['config']['admin_product_stock_status']) {
111
                            $searchData['link_status'] = $app['eccube.repository.master.disp']->find($status);
112
                            $searchData['status'] = null;
113
                            $session->set('eccube.admin.product.search', $searchData);
114
                        } else {
115
                            $searchData['stock_status'] = Constant::DISABLED;
116
                        }
117
                        $page_status = $status;
118
                    } else {
119
                        $searchData['link_status'] = null;
120
                        $searchData['stock_status'] = null;
121
                    }
122
                    // 表示件数
123
                    $pcount = $request->get('page_count');
124
125
                    $page_count = empty($pcount) ? $page_count : $pcount;
126
127
                    $qb = $app['eccube.repository.product']->getQueryBuilderBySearchDataForAdmin($searchData);
128
129
                    $event = new EventArgs(
130
                        array(
131
                            'qb' => $qb,
132
                            'searchData' => $searchData,
133
                        ),
134
                        $request
135
                    );
136
                    $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_INDEX_SEARCH, $event);
137
                    $searchData = $event->getArgument('searchData');
138
139
                    $pagination = $app['paginator']()->paginate(
140
                        $qb,
141
                        $page_no,
142
                        $page_count,
143
                        array('wrap-queries' => true)
144
                    );
145
146
                    // セッションから検索条件を復元
147
                    if (!empty($searchData['category_id'])) {
148
                        $searchData['category_id'] = $app['eccube.repository.category']->find($searchData['category_id']);
149
                    }
150
                    if (empty($status)) {
151 View Code Duplication
                        if (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...
152
                            $status_ids = array();
153
                            foreach ($searchData['status'] as $Status) {
154
                                $status_ids[] = $Status->getId();
155
                            }
156
                            $searchData['status'] = $app['eccube.repository.master.disp']->findBy(array('id' => $status_ids));
157
                        }
158
                        $searchData['link_status'] = null;
159
                        $searchData['stock_status'] = null;
160
                    }
161
                    $searchForm->setData($searchData);
162
                }
163
            }
164
        }
165
166
        return $app->render('Product/index.twig', array(
167
            'searchForm' => $searchForm->createView(),
168
            'pagination' => $pagination,
169
            'disps' => $disps,
170
            'pageMaxis' => $pageMaxis,
171
            'page_no' => $page_no,
172
            'page_status' => $page_status,
173
            'page_count' => $page_count,
174
            'active' => $active,
175
        ));
176
    }
177
178
    public function addImage(Application $app, Request $request)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
179
    {
180
        $images = $request->files->get('admin_product');
181
182
        $files = array();
183
        if (count($images) > 0) {
184
            foreach ($images as $img) {
185
                foreach ($img as $image) {
186
                    $extension = $image->getClientOriginalExtension();
187
                    $filename = date('mdHis') . uniqid('_') . '.' . $extension;
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
188
                    $image->move($app['config']['image_temp_realdir'], $filename);
189
                    $files[] = $filename;
190
                }
191
            }
192
        }
193
194
        $event = new EventArgs(
195
            array(
196
                'images' => $images,
197
                'files' => $files,
198
            ),
199
            $request
200
        );
201
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_ADD_IMAGE_COMPLETE, $event);
202
        $files = $event->getArgument('files');
203
204
        return $app->json(array('files' => $files), 200);
205
    }
206
207
    public function edit(Application $app, Request $request, $id = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
208
    {
209
        $has_class = false;
210
        if (is_null($id)) {
211
            $Product = new \Eccube\Entity\Product();
212
            $ProductClass = new \Eccube\Entity\ProductClass();
213
            $Disp = $app['eccube.repository.master.disp']->find(\Eccube\Entity\Master\Disp::DISPLAY_HIDE);
214
            $Product
215
                ->setDelFlg(Constant::DISABLED)
216
                ->addProductClass($ProductClass)
217
                ->setStatus($Disp);
218
            $ProductClass
219
                ->setDelFlg(Constant::DISABLED)
220
                ->setStockUnlimited(true)
221
                ->setProduct($Product);
222
            $ProductStock = new \Eccube\Entity\ProductStock();
223
            $ProductClass->setProductStock($ProductStock);
224
            $ProductStock->setProductClass($ProductClass);
225
        } else {
226
            $Product = $app['eccube.repository.product']->find($id);
227
            if (!$Product) {
228
                throw new NotFoundHttpException();
229
            }
230
            // 規格あり商品か
231
            $has_class = $Product->hasProductClass();
232
            if (!$has_class) {
233
                $ProductClasses = $Product->getProductClasses();
234
                $ProductClass = $ProductClasses[0];
235
                $BaseInfo = $app['eccube.repository.base_info']->get();
236 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...
237
                    $ProductClass->setTaxRate($ProductClass->getTaxRule()->getTaxRate());
238
                }
239
                $ProductStock = $ProductClasses[0]->getProductStock();
240
            }
241
        }
242
243
        $builder = $app['form.factory']
244
            ->createBuilder('admin_product', $Product);
245
246
        // 規格あり商品の場合、規格関連情報をFormから除外
247
        if ($has_class) {
248
            $builder->remove('class');
249
        }
250
251
        $event = new EventArgs(
252
            array(
253
                'builder' => $builder,
254
                'Product' => $Product,
255
            ),
256
            $request
257
        );
258
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_INITIALIZE, $event);
259
260
        $form = $builder->getForm();
261
262
        if (!$has_class) {
263
            $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...
264
            $form['class']->setData($ProductClass);
265
        }
266
267
        // ファイルの登録
268
        $images = array();
269
        $ProductImages = $Product->getProductImage();
270
        foreach ($ProductImages as $ProductImage) {
271
            $images[] = $ProductImage->getFileName();
272
        }
273
        $form['images']->setData($images);
274
275
        $categories = array();
276
        $ProductCategories = $Product->getProductCategories();
277
        foreach ($ProductCategories as $ProductCategory) {
278
            /* @var $ProductCategory \Eccube\Entity\ProductCategory */
279
            $categories[] = $ProductCategory->getCategory();
280
        }
281
        $form['Category']->setData($categories);
282
283
        if ('POST' === $request->getMethod()) {
284
            $form->handleRequest($request);
285
            if ($form->isValid()) {
286
                $Product = $form->getData();
287
288
                if (!$has_class) {
289
                    $ProductClass = $form['class']->getData();
290
291
                    // 個別消費税
292
                    $BaseInfo = $app['eccube.repository.base_info']->get();
293 View Code Duplication
                    if ($BaseInfo->getOptionProductTaxRule() == Constant::ENABLED) {
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...
294
                        if ($ProductClass->getTaxRate()) {
295
                            if ($ProductClass->getTaxRule() && !$ProductClass->getTaxRule()->getDelFlg()) {
296
                                $ProductClass->getTaxRule()->setTaxRate($ProductClass->getTaxRate());
297
                            } else {
298
                                $taxrule = $app['eccube.repository.tax_rule']->newTaxRule();
299
                                $taxrule->setTaxRate($ProductClass->getTaxRate());
300
                                $taxrule->setApplyDate(new \DateTime());
301
                                $taxrule->setProduct($Product);
302
                                $taxrule->setProductClass($ProductClass);
303
                                $ProductClass->setTaxRule($taxrule);
304
                            }
305
                        } else {
306
                            if ($ProductClass->getTaxRule()) {
307
                                $ProductClass->getTaxRule()->setDelFlg(Constant::ENABLED);
308
                            }
309
                        }
310
                    }
311
                    $app['orm.em']->persist($ProductClass);
312
313
                    // 在庫情報を作成
314
                    if (!$ProductClass->getStockUnlimited()) {
315
                        $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...
316
                    } else {
317
                        // 在庫無制限時はnullを設定
318
                        $ProductStock->setStock(null);
319
                    }
320
                    $app['orm.em']->persist($ProductStock);
321
                }
322
323
                // カテゴリの登録
324
                // 一度クリア
325
                /* @var $Product \Eccube\Entity\Product */
326
                foreach ($Product->getProductCategories() as $ProductCategory) {
327
                    $Product->removeProductCategory($ProductCategory);
328
                    $app['orm.em']->remove($ProductCategory);
329
                }
330
                $app['orm.em']->persist($Product);
331
                $app['orm.em']->flush();
332
333
                $count = 1;
334
                $Categories = $form->get('Category')->getData();
335
                foreach ($Categories as $Category) {
336
                    $ProductCategory = new \Eccube\Entity\ProductCategory();
337
                    $ProductCategory
338
                        ->setProduct($Product)
339
                        ->setProductId($Product->getId())
340
                        ->setCategory($Category)
341
                        ->setCategoryId($Category->getId())
342
                        ->setRank($count);
343
                    $app['orm.em']->persist($ProductCategory);
344
                    $count++;
345
                    /* @var $Product \Eccube\Entity\Product */
346
                    $Product->addProductCategory($ProductCategory);
347
                }
348
349
                // 画像の登録
350
                $add_images = $form->get('add_images')->getData();
351
                foreach ($add_images as $add_image) {
352
                    $ProductImage = new \Eccube\Entity\ProductImage();
353
                    $ProductImage
354
                        ->setFileName($add_image)
355
                        ->setProduct($Product)
356
                        ->setRank(1);
357
                    $Product->addProductImage($ProductImage);
358
                    $app['orm.em']->persist($ProductImage);
359
360
                    // 移動
361
                    $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...
362
                    $file->move($app['config']['image_save_realdir']);
363
                }
364
365
                // 画像の削除
366
                $delete_images = $form->get('delete_images')->getData();
367
                foreach ($delete_images as $delete_image) {
368
                    $ProductImage = $app['eccube.repository.product_image']
369
                        ->findOneBy(array('file_name' => $delete_image));
370
371
                    // 追加してすぐに削除した画像は、Entityに追加されない
372
                    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...
373
                        $Product->removeProductImage($ProductImage);
374
                        $app['orm.em']->remove($ProductImage);
375
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
376
                    }
377
                    $app['orm.em']->persist($Product);
378
379
                    // 削除
380
                    $fs = new Filesystem();
381
                    $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...
382
                }
383
                $app['orm.em']->persist($Product);
384
                $app['orm.em']->flush();
385
386
387
                $ranks = $request->get('rank_images');
388
                if ($ranks) {
389
                    foreach ($ranks as $rank) {
390
                        list($filename, $rank_val) = explode('//', $rank);
391
                        $ProductImage = $app['eccube.repository.product_image']
392
                            ->findOneBy(array(
393
                                'file_name' => $filename,
394
                                'Product' => $Product,
395
                            ));
396
                        $ProductImage->setRank($rank_val);
397
                        $app['orm.em']->persist($ProductImage);
398
                    }
399
                }
400
                $app['orm.em']->flush();
401
402
                $event = new EventArgs(
403
                    array(
404
                        'form' => $form,
405
                        'Product' => $Product,
406
                    ),
407
                    $request
408
                );
409
                $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_COMPLETE, $event);
410
411
                $app->addSuccess('admin.register.complete', 'admin');
412
413
                return $app->redirect($app->url('admin_product_product_edit', array('id' => $Product->getId())));
414
            } else {
415
                $app->addError('admin.register.failed', 'admin');
416
            }
417
        }
418
419
        // 検索結果の保持
420
        $builder = $app['form.factory']
421
            ->createBuilder('admin_search_product');
422
423
        $event = new EventArgs(
424
            array(
425
                'builder' => $builder,
426
                'Product' => $Product,
427
            ),
428
            $request
429
        );
430
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_SEARCH, $event);
431
432
        $searchForm = $builder->getForm();
433
434
        if ('POST' === $request->getMethod()) {
435
            $searchForm->handleRequest($request);
436
        }
437
438
        return $app->render('Product/product.twig', array(
439
            'Product' => $Product,
440
            'form' => $form->createView(),
441
            'searchForm' => $searchForm->createView(),
442
            'has_class' => $has_class,
443
            'id' => $id,
444
        ));
445
    }
446
447
    public function delete(Application $app, Request $request, $id = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
448
    {
449
        $this->isTokenValid($app);
450
451
        if (!is_null($id)) {
452
            /* @var $Product \Eccube\Entity\Product */
453
            $Product = $app['eccube.repository.product']->find($id);
454
            if (!$Product) {
455
                $app->deleteMessage();
456
                return $app->redirect($app->url('admin_product'));
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
457
            }
458
459
            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...
460
                $Product->setDelFlg(Constant::ENABLED);
461
462
                $ProductClasses = $Product->getProductClasses();
463
                $deleteImages = array();
464
                foreach ($ProductClasses as $ProductClass) {
465
                    $ProductClass->setDelFlg(Constant::ENABLED);
466
                    $Product->removeProductClass($ProductClass);
467
468
                    $ProductClasses = $Product->getProductClasses();
469
                    foreach ($ProductClasses as $ProductClass) {
470
                        $ProductClass->setDelFlg(Constant::ENABLED);
471
                        $Product->removeProductClass($ProductClass);
472
473
                        $ProductStock = $ProductClass->getProductStock();
474
                        $app['orm.em']->remove($ProductStock);
475
                    }
476
477
                    $ProductImages = $Product->getProductImage();
478
                    foreach ($ProductImages as $ProductImage) {
479
                        $Product->removeProductImage($ProductImage);
480
                        $deleteImages[] = $ProductImage->getFileName();
481
                        $app['orm.em']->remove($ProductImage);
482
                    }
483
484
                    $ProductCategories = $Product->getProductCategories();
485
                    foreach ($ProductCategories as $ProductCategory) {
486
                        $Product->removeProductCategory($ProductCategory);
487
                        $app['orm.em']->remove($ProductCategory);
488
                    }
489
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
490
                }
491
492
                $app['orm.em']->persist($Product);
493
494
                $app['orm.em']->flush();
495
496
                $event = new EventArgs(
497
                    array(
498
                        'Product' => $Product,
499
                        'ProductClass' => $ProductClasses,
500
                        'deleteImages' => $deleteImages,
501
                    ),
502
                    $request
503
                );
504
                $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_DELETE_COMPLETE, $event);
505
                $deleteImages = $event->getArgument('deleteImages');
506
507
                // 画像ファイルの削除(commit後に削除させる)
508
                foreach ($deleteImages as $deleteImage) {
509
                    try {
510
                        $fs = new Filesystem();
511
                        $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...
512
                    } catch (\Exception $e) {
513
                        // エラーが発生しても無視する
514
                    }
515
                }
516
517
                $app->addSuccess('admin.delete.complete', 'admin');
518
            } else {
519
                $app->addError('admin.delete.failed', 'admin');
520
            }
521
        } else {
522
            $app->addError('admin.delete.failed', 'admin');
523
        }
524
525
        return $app->redirect($app->url('admin_product'));
526
    }
527
528
    public function copy(Application $app, Request $request, $id = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
529
    {
530
        if (!is_null($id)) {
531
            $Product = $app['eccube.repository.product']->find($id);
532
            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...
533
                $CopyProduct = clone $Product;
534
                $CopyProduct->copy();
535
                $Disp = $app['eccube.repository.master.disp']->find(\Eccube\Entity\Master\Disp::DISPLAY_HIDE);
536
                $CopyProduct->setStatus($Disp);
537
538
                $CopyProductCategories = $CopyProduct->getProductCategories();
539
                foreach ($CopyProductCategories as $Category) {
540
                    $app['orm.em']->persist($Category);
541
                }
542
543
                // 規格あり商品の場合は, デフォルトの商品規格を取得し登録する.
544
                if ($CopyProduct->hasProductClass()) {
545
                    $softDeleteFilter = $app['orm.em']->getFilters()->getFilter('soft_delete');
546
                    $softDeleteFilter->setExcludes(array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
547
                        'Eccube\Entity\ProductClass'
548
                    ));
549
                    $dummyClass = $app['eccube.repository.product_class']->findOneBy(array(
550
                        'del_flg' => \Eccube\Common\Constant::ENABLED,
551
                        'ClassCategory1' => null,
552
                        'ClassCategory2' => null,
553
                        'Product' => $Product,
554
                    ));
555
                    $dummyClass = clone $dummyClass;
556
                    $dummyClass->setProduct($CopyProduct);
557
                    $CopyProduct->addProductClass($dummyClass);
558
                    $softDeleteFilter->setExcludes(array());
559
                }
560
561
                $CopyProductClasses = $CopyProduct->getProductClasses();
562
                foreach ($CopyProductClasses as $Class) {
563
                    $Stock = $Class->getProductStock();
564
                    $CopyStock = clone $Stock;
565
                    $CopyStock->setProductClass($Class);
566
                    $app['orm.em']->persist($CopyStock);
567
568
                    $app['orm.em']->persist($Class);
569
                }
570
                $Images = $CopyProduct->getProductImage();
571
                foreach ($Images as $Image) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
572
573
                    // 画像ファイルを新規作成
574
                    $extension = pathinfo($Image->getFileName(), PATHINFO_EXTENSION);
575
                    $filename = date('mdHis') . uniqid('_') . '.' . $extension;
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
576
                    try {
577
                        $fs = new Filesystem();
578
                        $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...
579
                    } catch (\Exception $e) {
580
                        // エラーが発生しても無視する
581
                    }
582
                    $Image->setFileName($filename);
583
584
                    $app['orm.em']->persist($Image);
585
                }
586
                $Tags = $CopyProduct->getProductTag();
587
                foreach ($Tags as $Tag) {
588
                    $app['orm.em']->persist($Tag);
589
                }
590
591
                $app['orm.em']->persist($CopyProduct);
592
593
                $app['orm.em']->flush();
594
595
                $event = new EventArgs(
596
                    array(
597
                        'Product' => $Product,
598
                        'CopyProduct' => $CopyProduct,
599
                        'CopyProductCategories' => $CopyProductCategories,
600
                        'CopyProductClasses' => $CopyProductClasses,
601
                        'images' => $Images,
602
                        'Tags' => $Tags,
603
                    ),
604
                    $request
605
                );
606
                $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_COPY_COMPLETE, $event);
607
608
                $app->addSuccess('admin.product.copy.complete', 'admin');
609
610
                return $app->redirect($app->url('admin_product_product_edit', array('id' => $CopyProduct->getId())));
611
            } else {
612
                $app->addError('admin.product.copy.failed', 'admin');
613
            }
614
        } else {
615
            $app->addError('admin.product.copy.failed', 'admin');
616
        }
617
618
        return $app->redirect($app->url('admin_product'));
619
    }
620
621
    public function display(Application $app, Request $request, $id = null)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
622
    {
623
        $event = new EventArgs(
624
            array(),
625
            $request
626
        );
627
        $app['eccube.event.dispatcher']->dispatch(EccubeEvents::ADMIN_PRODUCT_DISPLAY_COMPLETE, $event);
628
629
        if (!is_null($id)) {
630
            return $app->redirect($app->url('product_detail', array('id' => $id, 'admin' => '1')));
631
        }
632
633
        return $app->redirect($app->url('admin_product'));
634
    }
635
636
    /**
637
     * 商品CSVの出力.
638
     *
639
     * @param Application $app
640
     * @param Request $request
0 ignored issues
show
introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
641
     * @return StreamedResponse
642
     */
643
    public function export(Application $app, Request $request)
644
    {
645
        // タイムアウトを無効にする.
646
        set_time_limit(0);
647
648
        // sql loggerを無効にする.
649
        $em = $app['orm.em'];
650
        $em->getConfiguration()->setSQLLogger(null);
651
652
        $response = new StreamedResponse();
653
        $response->setCallback(function () use ($app, $request) {
654
655
            // CSV種別を元に初期化.
656
            $app['eccube.service.csv.export']->initCsvType(CsvType::CSV_TYPE_PRODUCT);
657
658
            // ヘッダ行の出力.
659
            $app['eccube.service.csv.export']->exportHeader();
660
661
            // 商品データ検索用のクエリビルダを取得.
662
            $qb = $app['eccube.service.csv.export']
663
                ->getProductQueryBuilder($request);
664
665
            // joinする場合はiterateが使えないため, select句をdistinctする.
666
            // http://qiita.com/suin/items/2b1e98105fa3ef89beb7
667
            // distinctのmysqlとpgsqlの挙動をあわせる.
668
            // http://uedatakeshi.blogspot.jp/2010/04/distinct-oeder-by-postgresmysql.html
669
            $qb->resetDQLPart('select')
670
                ->resetDQLPart('orderBy')
671
                ->select('p')
672
                ->orderBy('p.update_date', 'DESC')
673
                ->distinct();
674
675
            // データ行の出力.
676
            $app['eccube.service.csv.export']->setExportQueryBuilder($qb);
677 View Code Duplication
            $app['eccube.service.csv.export']->exportData(function ($entity, $csvService) {
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...
678
679
                $Csvs = $csvService->getCsvs();
680
681
                /** @var $Product \Eccube\Entity\Product */
682
                $Product = $entity;
683
684
                /** @var $Product \Eccube\Entity\ProductClass[] */
685
                $ProductClassess = $Product->getProductClasses();
0 ignored issues
show
Bug introduced by
The method getProductClasses cannot be called on $Product (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...
686
687
                foreach ($ProductClassess as $ProductClass) {
688
                    $row = array();
689
690
                    // CSV出力項目と合致するデータを取得.
691
                    foreach ($Csvs as $Csv) {
692
                        // 商品データを検索.
693
                        $data = $csvService->getData($Csv, $Product);
694
                        if (is_null($data)) {
695
                            // 商品規格情報を検索.
696
                            $data = $csvService->getData($Csv, $ProductClass);
697
                        }
698
                        $row[] = $data;
699
                    }
700
701
                    //$row[] = number_format(memory_get_usage(true));
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% 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...
702
                    // 出力.
703
                    $csvService->fputcsv($row);
704
                }
705
            });
706
        });
707
708
        $now = new \DateTime();
709
        $filename = 'product_' . $now->format('YmdHis') . '.csv';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
710
        $response->headers->set('Content-Type', 'application/octet-stream');
711
        $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...
712
        $response->send();
713
714
        return $response;
715
    }
716
}
717