Failed Conditions
Pull Request — master (#1429)
by Kentaro
43:16
created

CsvExportService::findDeserializeObjects()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
ccs 0
cts 0
cp 0
rs 9.2
cc 4
eloc 10
nc 4
nop 2
crap 20
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\Service;
26
27
use Eccube\Common\Constant;
28
use Eccube\Util\EntityUtil;
29
use Symfony\Component\Form\FormFactory;
30
use Symfony\Component\HttpFoundation\Request;
31
use Doctrine\Common\Collections\ArrayCollection;
32
33
class CsvExportService
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
34
{
35
    /**
36
     * @var
37
     */
38
    protected $fp;
39
40
    /**
41
     * @var
42
     */
43
    protected $closed = false;
44
45
    /**
46
     * @var \Closure
47
     */
48
    protected $convertEncodingCallBack;
49
50
    /**
51
     * @var \Doctrine\ORM\EntityManager
52
     */
53
    protected $em;
54
55
    /**
56
     * @var \Doctrine\ORM\QueryBuilder;
57
     */
58
    protected $qb;
59
60
    /**
61
     * @var array
62
     */
63
    protected $config;
64
65
    /**
66
     * @var \Eccube\Entity\Master\CsvType
67
     */
68
    protected $CsvType;
69
70
    /**
71
     * @var \Eccube\Entity\Csv[]
72
     */
73
    protected $Csvs;
74
75
    /**
76
     * @var \Eccube\Repository\CsvRepository
77
     */
78
    protected $csvRepository;
79
80
    /**
81
     * @var \Eccube\Repository\Master\CsvTypeRepository
82
     */
83
    protected $csvTypeRepository;
84
85
    /**
86
     * @var \Eccube\Repository\OrderRepository
87
     */
88
    protected $orderRepository;
89
90
    /**
91
     * @var \Eccube\Repository\CustomerRepository
92
     */
93
    protected $customerRepository;
94
95
    /**
96
     * @var \Eccube\Repository\ProductRepository
97
     */
98
    protected $productRepository;
99
100
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$config" missing
Loading history...
101
     * @param $config
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
102 5
     */
103
    public function setConfig($config)
104 5
    {
105 5
        $this->config = $config;
106
    }
107
108
    /**
109
     * @param \Eccube\Repository\CsvRepository $csvRepository
110 5
     */
111
    public function setCsvRepository(\Eccube\Repository\CsvRepository $csvRepository)
112 5
    {
113
        $this->csvRepository = $csvRepository;
114
    }
115
116
    /**
117
     * @param \Eccube\Repository\Master\CsvTypeRepository $csvTypeRepository
118 5
     */
119
    public function setCsvTypeRepository(\Eccube\Repository\Master\CsvTypeRepository $csvTypeRepository)
120 5
    {
121
        $this->csvTypeRepository = $csvTypeRepository;
122
    }
123
124
    /**
125
     * @param \Eccube\Repository\OrderRepository $orderRepository
126 5
     */
127
    public function setOrderRepository(\Eccube\Repository\OrderRepository $orderRepository)
128 5
    {
129
        $this->orderRepository = $orderRepository;
130
    }
131
132
    /**
133
     * @param \Eccube\Repository\CustomerRepository $customerRepository
134 5
     */
135
    public function setCustomerRepository(\Eccube\Repository\CustomerRepository $customerRepository)
136 5
    {
137
        $this->customerRepository = $customerRepository;
138
    }
139
140
    /**
141
     * @param \Eccube\Repository\ProductRepository $productRepository
142 5
     */
143
    public function setProductRepository(\Eccube\Repository\ProductRepository $productRepository)
144 5
    {
145
        $this->productRepository = $productRepository;
146
    }
147
148
    /**
149
     * @param \Doctrine\ORM\EntityManager $em
150 4
     */
151
    public function setEntityManager(\Doctrine\ORM\EntityManager $em)
0 ignored issues
show
Bug introduced by
You have injected the EntityManager via parameter $em. This is generally not recommended as it might get closed and become unusable. Instead, it is recommended to inject the ManagerRegistry and retrieve the EntityManager via getManager() each time you need it.

The EntityManager might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:

function someFunction(ManagerRegistry $registry) {
    $em = $registry->getManager();
    $em->getConnection()->beginTransaction();
    try {
        // Do something.
        $em->getConnection()->commit();
    } catch (\Exception $ex) {
        $em->getConnection()->rollback();
        $em->close();

        throw $ex;
    }
}

If that code throws an exception and the EntityManager is closed. Any other code which depends on the same instance of the EntityManager during this request will fail.

On the other hand, if you instead inject the ManagerRegistry, the getManager() method guarantees that you will always get a usable manager instance.

Loading history...
152 4
    {
153
        $this->em = $em;
154
    }
155
156
    /**
157
     * @return \Doctrine\ORM\EntityManager
158
     */
159
    public function getEntityManager()
160
    {
161
        return $this->em;
162
    }
163
164
    /**
165
     * @param \Doctrine\ORM\QueryBuilder $qb
166 4
     */
167
    public function setExportQueryBuilder(\Doctrine\ORM\QueryBuilder $qb)
168 4
    {
169
        $this->qb = $qb;
170
        $this->setEntityManager($qb->getEntityManager());
171
    }
172
173
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$CsvType" missing
Loading history...
174
     * Csv種別からServiceの初期化を行う.
175
     *
176
     * @param $CsvType|integer
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
177 5
     */
178
    public function initCsvType($CsvType)
179 5
    {
180
        if ($CsvType instanceof \Eccube\Entity\Master\CsvType) {
0 ignored issues
show
Bug introduced by
The class Eccube\Entity\Master\CsvType 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...
181
            $this->CsvType = $CsvType;
182
        } else {
183
            $this->CsvType = $this->csvTypeRepository->find($CsvType);
184
        }
185
186
        $criteria = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
187 5
            'CsvType' => $CsvType,
188
            'enable_flg' => Constant::ENABLED
189
        );
190
        $orderBy = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
191 5
            'rank' => 'ASC'
192
        );
193 5
        $this->Csvs = $this->csvRepository->findBy($criteria, $orderBy);
194
    }
195
196
    /**
197
     * @return \Eccube\Entity\Csv[]
198
     */
199
    public function getCsvs()
200
    {
201
        return $this->Csvs;
202
    }
203
204
    /**
205
     * ヘッダ行を出力する.
206
     * このメソッドを使う場合は, 事前にinitCsvType($CsvType)で初期化しておく必要がある.
207 4
     */
208
    public function exportHeader()
209
    {
210
        if (is_null($this->CsvType) || is_null($this->Csvs)) {
211
            throw new \LogicException('init csv type incomplete.');
212
        }
213 4
214 4
        $row = array();
215
        foreach ($this->Csvs as $Csv) {
216
            $row[] = $Csv->getDispName();
217
        }
218
219
        $this->fopen();
220
        $this->fputcsv($row);
221 4
        $this->fclose();
222
    }
223
224
    /**
225
     * クエリビルダにもとづいてデータ行を出力する.
226
     * このメソッドを使う場合は, 事前にsetExportQueryBuilder($qb)で出力対象のクエリビルダをわたしておく必要がある.
227
     *
228
     * @param \Closure $closure
229 4
     */
230
    public function exportData(\Closure $closure)
231
    {
232
        if (is_null($this->qb) || is_null($this->em)) {
233
            throw new \LogicException('query builder not set.');
234
        }
235
236
        $this->fopen();
237
238 4
        $query = $this->qb->getQuery();
239
        foreach ($query->getResult() as $iteratableResult) {
240
            $closure($iteratableResult, $this);
241
            $this->em->detach($iteratableResult);
242
            $this->em->clear();
243
            $query->free();
244
            flush();
245
        }
246
247
        $this->fclose();
248
    }
249
250
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$entity" missing
Loading history...
251
     * CSV出力項目と比較し, 合致するデータを返す.
252
     *
253
     * @param \Eccube\Entity\Csv $Csv
254
     * @param $entity
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
255
     * @return mixed|null|string|void
256
     */
257
    public function getData(\Eccube\Entity\Csv $Csv, $entity)
258
    {
259
        // エンティティ名が一致するかどうかチェック.
260
        $csvEntityName = str_replace('\\\\', '\\', $Csv->getEntityName());
261
        $entityName = str_replace('\\\\', '\\', get_class($entity));
262
        if ($csvEntityName !== $entityName) {
263
            return null;
264
        }
265
266
        // カラム名がエンティティに存在するかどうかをチェック.
267
        if (!$entity->offsetExists($Csv->getFieldName())) {
268
            return null;
269
        }
270
271
        // データを取得.
272
        $data = $entity->offsetGet($Csv->getFieldName());
273
274
        // one to one の場合は, dtb_csv.referece_field_nameと比較し, 合致する結果を取得する.
275
        if ($data instanceof \Eccube\Entity\AbstractEntity) {
0 ignored issues
show
Bug introduced by
The class Eccube\Entity\AbstractEntity 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...
276
            if (EntityUtil::isNotEmpty($data)) {
277
                return $data->offsetGet($Csv->getReferenceFieldName());
278
            }
279
        } elseif ($data instanceof \Doctrine\Common\Collections\Collection) {
280
            // one to manyの場合は, カンマ区切りに変換する.
281
            $array = array();
282
            foreach ($data as $elem) {
283
                if (EntityUtil::isNotEmpty($elem)) {
284
                    $array[] = $elem->offsetGet($Csv->getReferenceFieldName());
285
                }
286
            }
287
            return implode($this->config['csv_export_multidata_separator'], $array);
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
288
289
        } elseif ($data instanceof \DateTime) {
290
            // datetimeの場合は文字列に変換する.
291
            return $data->format($this->config['csv_export_date_format']);
292
293
        } else {
294
            // スカラ値の場合はそのまま.
295
            return $data;
296
        }
297
298
        return null;
299
    }
300
301
    /**
302
     * 文字エンコーディングの変換を行うコールバック関数を返す.
303
     *
304
     * @return \Closure
305 5
     */
306
    public function getConvertEncodhingCallback()
307 5
    {
308
        $config = $this->config;
309 5
310
        return function ($value) use ($config) {
311
            return mb_convert_encoding(
312
                (string) $value, $config['csv_export_encoding'], 'UTF-8'
313 5
            );
314
        };
315
    }
316
317
    /**
318
     *
319 2
     */
320
    public function fopen()
321
    {
322
        if (is_null($this->fp) || $this->closed) {
323
            $this->fp = fopen('php://output', 'w');
324 2
        }
325
    }
326
327
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$row" missing
Loading history...
328
     * @param $row
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
329
     * @param null $callback
0 ignored issues
show
Bug introduced by
There is no parameter named $callback. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
introduced by
Superfluous parameter comment
Loading history...
330 1
     */
331
    public function fputcsv($row)
332
    {
333
        if (is_null($this->convertEncodingCallBack)) {
334
            $this->convertEncodingCallBack = $this->getConvertEncodhingCallback();
335
        }
336
337 1
        fputcsv($this->fp, array_map($this->convertEncodingCallBack, $row), $this->config['csv_export_separator']);
338
    }
339
340
    /**
341
     *
342 5
     */
343
    public function fclose()
344 2
    {
345
        if (!$this->closed) {
346 5
            fclose($this->fp);
347
            $this->closed = true;
348 2
        }
349
    }
350
351
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$em" missing
Loading history...
352
     * 受注検索用のクエリビルダを返す.
353
     *
354
     * @param Request $request
355
     * @return \Doctrine\ORM\QueryBuilder
356 2
     */
357 View Code Duplication
    public function getOrderQueryBuilder(Request $request, $em)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
358
    {
359
        $session = $request->getSession();
360
        if ($session->has('eccube.admin.order.search')) {
361
            $searchData = $session->get('eccube.admin.order.search');
362
            $this->findDeserializeObjects($searchData, $em);
363 2
        } else {
364
            $searchData = array();
365
        }
366 2
367
        // 受注データのクエリビルダを構築.
368
        $qb = $this->orderRepository
369 2
            ->getQueryBuilderBySearchDataForAdmin($searchData);
370 2
371
        return $qb;
372
    }
373
374
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$em" missing
Loading history...
375
     * 会員検索用のクエリビルダを返す.
376
     *
377
     * @param Request $request
378 1
     * @return \Doctrine\ORM\QueryBuilder
379
     */
380 View Code Duplication
    public function getCustomerQueryBuilder(Request $request, $em)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
381
    {
382
        $session = $request->getSession();
383
        if ($session->has('eccube.admin.customer.search')) {
384 1
            $searchData = $session->get('eccube.admin.customer.search');
385
            $this->findDeserializeObjects($searchData, $em);
386
        } else {
387
            $searchData = array();
388 1
        }
389
390
        // 会員データのクエリビルダを構築.
391 1
        $qb = $this->customerRepository
392 1
            ->getQueryBuilderBySearchData($searchData);
393
394
        return $qb;
395
    }
396
397
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$em" missing
Loading history...
398
     * 商品検索用のクエリビルダを返す.
399
     *
400
     * @param Request $request
401
     * @return \Doctrine\ORM\QueryBuilder
402
     */
403 View Code Duplication
    public function getProductQueryBuilder(Request $request, $em)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
404
    {
405
        $session = $request->getSession();
406
        if ($session->has('eccube.admin.product.search')) {
407
            $searchData = $session->get('eccube.admin.product.search');
408
            $this->findDeserializeObjects($searchData, $em);
409
        } else {
410
            $searchData = array();
411
        }
412
413
        // 商品データのクエリビルダを構築.
414
        $qb = $this->productRepository
415
            ->getQueryBuilderBySearchDataForAdmin($searchData);
416
417
        return $qb;
418
    }
419
420
    /**
421
     * セッションでシリアライズされた Doctrine のオブジェクトを取得し直す.
422
     *
423
     * XXX self::setExportQueryBuilder() をコールする前に EntityManager を取得したいので、引数で渡している
424
     *
425
     * @param array $searchData セッションから取得した検索条件の配列
426
     * @param EntityManager $em
427
     */
428
    protected function findDeserializeObjects(array &$searchData, $em)
429
    {
430
        foreach ($searchData as &$Conditions) {
431
            if ($Conditions instanceof ArrayCollection) {
432
                $Conditions = new ArrayCollection(
433
                    array_map(
434
                        function ($Entity) use ($em) {
435
                            return $em->getRepository(get_class($Entity))->find($Entity->getId());
436
                        }, $Conditions->toArray()
437
                    )
438
                );
439
            } elseif ($Conditions instanceof \Eccube\Entity\AbstractEntity) {
0 ignored issues
show
Bug introduced by
The class Eccube\Entity\AbstractEntity 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...
440
                $Conditions = $em->getRepository(get_class($Conditions))->find($Conditions->getId());
441
            }
442
        }
443
    }
444
}
445