Failed Conditions
Push — master ( 5ac99f...ce75f7 )
by Kentaro
22s
created

ProductController   F

Complexity

Total Complexity 77

Size/Duplication

Total Lines 727
Duplicated Lines 7.84 %

Coupling/Cohesion

Components 0
Dependencies 12

Test Coverage

Coverage 57.88%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 77
c 2
b 0
f 0
lcom 0
cbo 12
dl 57
loc 727
ccs 235
cts 406
cp 0.5788
rs 1.4117

7 Methods

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