Issues (2687)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Controller/Admin/Product/ProductController.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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