Completed
Pull Request — master (#1398)
by Kentaro
34:58
created

CsvExportService::getOrderQueryBuilder()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 15
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6
Metric Value
dl 15
loc 15
ccs 0
cts 0
cp 0
rs 9.4285
cc 2
eloc 9
nc 2
nop 1
crap 6
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
32
class CsvExportService
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
33
{
34
    /**
35
     * @var
36
     */
37
    protected $fp;
38
39
    /**
40
     * @var
41
     */
42
    protected $closed = false;
43
44
    /**
45
     * @var \Closure
46
     */
47
    protected $convertEncodingCallBack;
48
49
    /**
50
     * @var \Doctrine\ORM\EntityManager
51
     */
52
    protected $em;
53
54
    /**
55
     * @var \Doctrine\ORM\QueryBuilder;
56
     */
57
    protected $qb;
58
59
    /**
60
     * @var array
61
     */
62
    protected $config;
63
64
    /**
65
     * @var \Eccube\Entity\Master\CsvType
66
     */
67
    protected $CsvType;
68
69
    /**
70
     * @var \Eccube\Entity\Csv[]
71
     */
72
    protected $Csvs;
73
74
    /**
75
     * @var \Eccube\Repository\CsvRepository
76
     */
77
    protected $csvRepository;
78
79
    /**
80
     * @var \Eccube\Repository\Master\CsvTypeRepository
81
     */
82
    protected $csvTypeRepository;
83
84
    /**
85
     * @var \Eccube\Repository\OrderRepository
86
     */
87
    protected $orderRepository;
88
89
    /**
90
     * @var \Eccube\Repository\CustomerRepository
91
     */
92
    protected $customerRepository;
93
94
    /**
95
     * @var \Eccube\Repository\ProductRepository
96
     */
97
    protected $productRepository;
98
99
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$config" missing
Loading history...
100
     * @param $config
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
101
     */
102 3
    public function setConfig($config)
103
    {
104 3
        $this->config = $config;
105 3
    }
106
107
    /**
108
     * @param \Eccube\Repository\CsvRepository $csvRepository
109
     */
110 3
    public function setCsvRepository(\Eccube\Repository\CsvRepository $csvRepository)
111
    {
112 3
        $this->csvRepository = $csvRepository;
113
    }
114
115
    /**
116
     * @param \Eccube\Repository\Master\CsvTypeRepository $csvTypeRepository
117
     */
118 3
    public function setCsvTypeRepository(\Eccube\Repository\Master\CsvTypeRepository $csvTypeRepository)
119
    {
120 3
        $this->csvTypeRepository = $csvTypeRepository;
121
    }
122
123
    /**
124
     * @param \Eccube\Repository\OrderRepository $orderRepository
125
     */
126 3
    public function setOrderRepository(\Eccube\Repository\OrderRepository $orderRepository)
127
    {
128 3
        $this->orderRepository = $orderRepository;
129
    }
130
131
    /**
132
     * @param \Eccube\Repository\CustomerRepository $customerRepository
133
     */
134 3
    public function setCustomerRepository(\Eccube\Repository\CustomerRepository $customerRepository)
135
    {
136 3
        $this->customerRepository = $customerRepository;
137
    }
138
139
    /**
140
     * @param \Eccube\Repository\ProductRepository $productRepository
141
     */
142 3
    public function setProductRepository(\Eccube\Repository\ProductRepository $productRepository)
143
    {
144 3
        $this->productRepository = $productRepository;
145
    }
146
147
    /**
148
     * @param \Doctrine\ORM\EntityManager $em
149
     */
150 2
    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...
151
    {
152 2
        $this->em = $em;
153
    }
154
155
    /**
156
     * @return \Doctrine\ORM\EntityManager
157
     */
158
    public function getEntityManager()
159
    {
160
        return $this->em;
161
    }
162
163
    /**
164
     * @param \Doctrine\ORM\QueryBuilder $qb
165
     */
166 2
    public function setExportQueryBuilder(\Doctrine\ORM\QueryBuilder $qb)
167
    {
168 2
        $this->qb = $qb;
169
        $this->setEntityManager($qb->getEntityManager());
170
    }
171
172
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$CsvType" missing
Loading history...
173
     * Csv種別からServiceの初期化を行う.
174
     *
175
     * @param $CsvType|integer
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
176
     */
177 3
    public function initCsvType($CsvType)
178
    {
179 3
        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...
180
            $this->CsvType = $CsvType;
181
        } else {
182
            $this->CsvType = $this->csvTypeRepository->find($CsvType);
183
        }
184
185
        $criteria = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
186
            'CsvType' => $CsvType,
187 3
            'enable_flg' => Constant::ENABLED
188
        );
189
        $orderBy = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
190
            'rank' => 'ASC'
191 3
        );
192
        $this->Csvs = $this->csvRepository->findBy($criteria, $orderBy);
193 3
    }
194
195
    /**
196
     * @return \Eccube\Entity\Csv[]
197
     */
198
    public function getCsvs()
199
    {
200
        return $this->Csvs;
201
    }
202
203
    /**
204
     * ヘッダ行を出力する.
205
     * このメソッドを使う場合は, 事前にinitCsvType($CsvType)で初期化しておく必要がある.
206
     */
207 2
    public function exportHeader()
208
    {
209
        if (is_null($this->CsvType) || is_null($this->Csvs)) {
210
            throw new \LogicException('init csv type incomplete.');
211
        }
212
213 2
        $row = array();
214 2
        foreach ($this->Csvs as $Csv) {
215
            $row[] = $Csv->getDispName();
216
        }
217
218
        $this->fopen();
219
        $this->fputcsv($row);
220
        $this->fclose();
221 2
    }
222
223
    /**
224
     * クエリビルダにもとづいてデータ行を出力する.
225
     * このメソッドを使う場合は, 事前にsetExportQueryBuilder($qb)で出力対象のクエリビルダをわたしておく必要がある.
226
     *
227
     * @param \Closure $closure
228
     */
229 2
    public function exportData(\Closure $closure)
230
    {
231
        if (is_null($this->qb) || is_null($this->em)) {
232
            throw new \LogicException('query builder not set.');
233
        }
234
235
        $this->fopen();
236
237
        $query = $this->qb->getQuery();
238 2
        foreach ($query->getResult() as $iteratableResult) {
239
            $closure($iteratableResult, $this);
240
            $this->em->detach($iteratableResult);
241
            $this->em->clear();
242
            $query->free();
243
            flush();
244
        }
245
246
        $this->fclose();
247
    }
248
249
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$entity" missing
Loading history...
250
     * CSV出力項目と比較し, 合致するデータを返す.
251
     *
252
     * @param \Eccube\Entity\Csv $Csv
253
     * @param $entity
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
254
     * @return mixed|null|string|void
255
     */
256
    public function getData(\Eccube\Entity\Csv $Csv, $entity)
257
    {
258
        // エンティティ名が一致するかどうかチェック.
259
        $csvEntityName = str_replace('\\\\', '\\', $Csv->getEntityName());
260
        $entityName = str_replace('\\\\', '\\', get_class($entity));
261
        if ($csvEntityName !== $entityName) {
262
            return null;
263
        }
264
265
        // カラム名がエンティティに存在するかどうかをチェック.
266
        if (!$entity->offsetExists($Csv->getFieldName())) {
267
            return null;
268
        }
269
270
        // データを取得.
271
        $data = $entity->offsetGet($Csv->getFieldName());
272
273
        // one to one の場合は, dtb_csv.referece_field_nameと比較し, 合致する結果を取得する.
274
        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...
275
            if (EntityUtil::isNotEmpty($data)) {
276
                return $data->offsetGet($Csv->getReferenceFieldName());
277
            }
278
        } elseif ($data instanceof \Doctrine\Common\Collections\Collection) {
279
            // one to manyの場合は, カンマ区切りに変換する.
280
            $array = array();
281
            foreach ($data as $elem) {
282
                if (EntityUtil::isNotEmpty($elem)) {
283
                    $array[] = $elem->offsetGet($Csv->getReferenceFieldName());
284
                }
285
            }
286
            return implode($this->config['csv_export_multidata_separator'], $array);
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
287
288
        } elseif ($data instanceof \DateTime) {
289
            // datetimeの場合は文字列に変換する.
290
            return $data->format($this->config['csv_export_date_format']);
291
292
        } else {
293
            // スカラ値の場合はそのまま.
294
            return $data;
295
        }
296
297
        return null;
298
    }
299
300
    /**
301
     * 文字エンコーディングの変換を行うコールバック関数を返す.
302
     *
303
     * @return \Closure
304
     */
305 3
    public function getConvertEncodhingCallback()
306
    {
307 3
        $config = $this->config;
308
309 3
        return function ($value) use ($config) {
310
            return mb_convert_encoding(
311
                (string) $value, $config['csv_export_encoding'], 'UTF-8'
312
            );
313 3
        };
314
    }
315
316
    /**
317
     *
318
     */
319 2
    public function fopen()
320
    {
321
        if (is_null($this->fp) || $this->closed) {
322
            $this->fp = fopen('php://output', 'w');
323
        }
324 2
    }
325
326
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$row" missing
Loading history...
327
     * @param $row
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
328
     * @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...
329
     */
330 1
    public function fputcsv($row)
331
    {
332
        if (is_null($this->convertEncodingCallBack)) {
333
            $this->convertEncodingCallBack = $this->getConvertEncodhingCallback();
334
        }
335
336
        fputcsv($this->fp, array_map($this->convertEncodingCallBack, $row), $this->config['csv_export_separator']);
337 1
    }
338
339
    /**
340
     *
341
     */
342 3
    public function fclose()
343
    {
344 2
        if (!$this->closed) {
345
            fclose($this->fp);
346 3
            $this->closed = true;
347
        }
348 2
    }
349
350
    /**
351
     * 受注検索用のクエリビルダを返す.
352
     *
353
     * @param Request $request
354
     * @return \Doctrine\ORM\QueryBuilder
355
     */
356 View Code Duplication
    public function getOrderQueryBuilder(Request $request)
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...
357
    {
358
        $session = $request->getSession();
359
        if ($session->has('eccube.admin.order.search')) {
360
            $searchData = $session->get('eccube.admin.order.search');
361
        } else {
362
            $searchData = array();
363
        }
364
365
        // 受注データのクエリビルダを構築.
366
        $qb = $this->orderRepository
367
            ->getQueryBuilderBySearchDataForAdmin($searchData);
368
369
        return $qb;
370
    }
371
372
    /**
373
     * 会員検索用のクエリビルダを返す.
374
     *
375
     * @param Request $request
376
     * @return \Doctrine\ORM\QueryBuilder
377
     */
378 1
    public function getCustomerQueryBuilder(Request $request)
379
    {
380
        $session = $request->getSession();
381
        if ($session->has('eccube.admin.customer.search')) {
382
            $searchData = $session->get('eccube.admin.customer.search');
383
        } else {
384 1
            $searchData = array();
385
        }
386
387
        // 会員データのクエリビルダを構築.
388 1
        $qb = $this->customerRepository
389
            ->getQueryBuilderBySearchData($searchData);
390
391 1
        return $qb;
392 1
    }
393
394
    /**
395
     * 商品検索用のクエリビルダを返す.
396
     *
397
     * @param Request $request
398
     * @return \Doctrine\ORM\QueryBuilder
399
     */
400 View Code Duplication
    public function getProductQueryBuilder(Request $request)
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...
401
    {
402
        $session = $request->getSession();
403
        if ($session->has('eccube.admin.product.search')) {
404
            $searchData = $session->get('eccube.admin.product.search');
405
        } else {
406
            $searchData = array();
407
        }
408
409
        // 商品データのクエリビルダを構築.
410
        $qb = $this->productRepository
411
            ->getQueryBuilderBySearchDataForAdmin($searchData);
412
413
        return $qb;
414
    }
415
}
416