Failed Conditions
Push — experimental/sf ( ef9148...a8c20b )
by Ryo
1419:13 queued 1408:28
created

src/Eccube/Service/CsvExportService.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
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.co.jp/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Eccube\Service;
15
16
use Doctrine\Common\Util\ClassUtils;
17
use Doctrine\ORM\EntityManagerInterface;
18
use Eccube\Common\EccubeConfig;
19
use Eccube\Form\Type\Admin\SearchProductType;
20
use Eccube\Repository\CsvRepository;
21
use Eccube\Repository\CustomerRepository;
22
use Eccube\Repository\Master\CsvTypeRepository;
23
use Eccube\Repository\OrderRepository;
24
use Eccube\Repository\ProductRepository;
25
use Eccube\Repository\ShippingRepository;
26
use Eccube\Util\EntityUtil;
27
use Eccube\Util\FormUtil;
28
use Symfony\Component\Form\FormFactoryInterface;
29
use Symfony\Component\HttpFoundation\Request;
30
use Doctrine\ORM\QueryBuilder;
31
use Eccube\Entity\Master\CsvType;
32
use Eccube\Entity\Csv;
33
34
class CsvExportService
35
{
36
    /**
37
     * @var resource
38
     */
39
    protected $fp;
40
41
    /**
42
     * @var boolean
43
     */
44
    protected $closed = false;
45
46
    /**
47
     * @var \Closure
48
     */
49
    protected $convertEncodingCallBack;
50
51
    /**
52
     * @var EntityManagerInterface
53
     */
54
    protected $entityManager;
55
56
    /**
57
     * @var QueryBuilder;
58
     */
59
    protected $qb;
60
61
    /**
62
     * @var EccubeConfig
63
     */
64
    protected $eccubeConfig;
65
66
    /**
67
     * @var CsvType
68
     */
69
    protected $CsvType;
70
71
    /**
72
     * @var Csv[]
73
     */
74
    protected $Csvs;
75
76
    /**
77
     * @var CsvRepository
78
     */
79
    protected $csvRepository;
80
81
    /**
82
     * @var CsvTypeRepository
83
     */
84
    protected $csvTypeRepository;
85
86
    /**
87
     * @var OrderRepository
88
     */
89
    protected $orderRepository;
90
91
    /**
92
     * @var ShippingRepository
93
     */
94
    protected $shippingRepository;
95
96
    /**
97
     * @var CustomerRepository
98
     */
99
    protected $customerRepository;
100
101
    /**
102
     * @var ProductRepository
103
     */
104
    protected $productRepository;
105
106
    /**
107
     * @var FormFactoryInterface
108
     */
109
    protected $formFactory;
110
111
    /**
112
     * CsvExportService constructor.
113
     *
114
     * @param EntityManagerInterface $entityManager
115
     * @param CsvRepository $csvRepository
116
     * @param CsvTypeRepository $csvTypeRepository
117
     * @param OrderRepository $orderRepository
118
     * @param CustomerRepository $customerRepository
119
     * @param EccubeConfig $eccubeConfig
120
     */
121 58
    public function __construct(
122
        EntityManagerInterface $entityManager,
123
        CsvRepository $csvRepository,
124
        CsvTypeRepository $csvTypeRepository,
125
        OrderRepository $orderRepository,
126
        ShippingRepository $shippingRepository,
127
        CustomerRepository $customerRepository,
128
        ProductRepository $productRepository,
129
        EccubeConfig $eccubeConfig,
130
        FormFactoryInterface $formFactory
131
    ) {
132 58
        $this->entityManager = $entityManager;
133 58
        $this->csvRepository = $csvRepository;
134 58
        $this->csvTypeRepository = $csvTypeRepository;
135 58
        $this->orderRepository = $orderRepository;
136 58
        $this->shippingRepository = $shippingRepository;
137 58
        $this->customerRepository = $customerRepository;
138 58
        $this->eccubeConfig = $eccubeConfig;
139 58
        $this->productRepository = $productRepository;
140 58
        $this->formFactory = $formFactory;
141
    }
142
143
    /**
144
     * @param $config
145
     */
146
    public function setConfig($config)
147
    {
148
        $this->eccubeConfig = $config;
149
    }
150
151
    /**
152
     * @param CsvRepository $csvRepository
153
     */
154
    public function setCsvRepository(CsvRepository $csvRepository)
155
    {
156
        $this->csvRepository = $csvRepository;
157
    }
158
159
    /**
160
     * @param CsvTypeRepository $csvTypeRepository
161
     */
162
    public function setCsvTypeRepository(CsvTypeRepository $csvTypeRepository)
163
    {
164
        $this->csvTypeRepository = $csvTypeRepository;
165
    }
166
167
    /**
168
     * @param OrderRepository $orderRepository
169
     */
170
    public function setOrderRepository(OrderRepository $orderRepository)
171
    {
172
        $this->orderRepository = $orderRepository;
173
    }
174
175
    /**
176
     * @param CustomerRepository $customerRepository
177
     */
178
    public function setCustomerRepository(CustomerRepository $customerRepository)
179
    {
180
        $this->customerRepository = $customerRepository;
181
    }
182
183
    /**
184
     * @param ProductRepository $productRepository
185
     */
186
    public function setProductRepository(ProductRepository $productRepository)
187
    {
188
        $this->productRepository = $productRepository;
189
    }
190
191
    /**
192
     * @param EntityManagerInterface $entityManager
193
     */
194
    public function setEntityManager(EntityManagerInterface $entityManager)
195
    {
196
        $this->entityManager = $entityManager;
197
    }
198
199
    /**
200
     * @return EntityManagerInterface
201
     */
202
    public function getEntityManager()
203
    {
204
        return $this->entityManager;
205
    }
206
207
    /**
208
     * @param QueryBuilder $qb
209
     */
210
    public function setExportQueryBuilder(QueryBuilder $qb)
211
    {
212
        $this->qb = $qb;
213
    }
214
215
    /**
216
     * Csv種別からServiceの初期化を行う.
217
     *
218
     * @param $CsvType|integer
219
     */
220 3
    public function initCsvType($CsvType)
221
    {
222 3
        if ($CsvType instanceof CsvType) {
223
            $this->CsvType = $CsvType;
224
        } else {
225 3
            $this->CsvType = $this->csvTypeRepository->find($CsvType);
226
        }
227
228
        $criteria = [
229 3
            'CsvType' => $CsvType,
230
            'enabled' => true,
231
        ];
232
        $orderBy = [
233 3
            'sort_no' => 'ASC',
234
        ];
235 3
        $this->Csvs = $this->csvRepository->findBy($criteria, $orderBy);
236
    }
237
238
    /**
239
     * @return Csv[]
240
     */
241
    public function getCsvs()
242
    {
243
        return $this->Csvs;
244
    }
245
246
    /**
247
     * ヘッダ行を出力する.
248
     * このメソッドを使う場合は, 事前にinitCsvType($CsvType)で初期化しておく必要がある.
249
     */
250
    public function exportHeader()
251
    {
252
        if (is_null($this->CsvType) || is_null($this->Csvs)) {
253
            throw new \LogicException('init csv type incomplete.');
254
        }
255
256
        $row = [];
257
        foreach ($this->Csvs as $Csv) {
258
            $row[] = $Csv->getDispName();
259
        }
260
261
        $this->fopen();
262
        $this->fputcsv($row);
263
        $this->fclose();
264
    }
265
266
    /**
267
     * クエリビルダにもとづいてデータ行を出力する.
268
     * このメソッドを使う場合は, 事前にsetExportQueryBuilder($qb)で出力対象のクエリビルダをわたしておく必要がある.
269
     *
270
     * @param \Closure $closure
271
     */
272
    public function exportData(\Closure $closure)
273
    {
274
        if (is_null($this->qb) || is_null($this->entityManager)) {
275
            throw new \LogicException('query builder not set.');
276
        }
277
278
        $this->fopen();
279
280
        $query = $this->qb->getQuery();
281
        foreach ($query->getResult() as $iteratableResult) {
282
            $closure($iteratableResult, $this);
283
            $this->entityManager->detach($iteratableResult);
284
            $query->free();
285
            flush();
286
        }
287
288
        $this->fclose();
289
    }
290
291
    /**
292
     * CSV出力項目と比較し, 合致するデータを返す.
293
     *
294
     * @param \Eccube\Entity\Csv $Csv
295
     * @param $entity
296
     *
297
     * @return mixed|null|string|void
298
     */
299
    public function getData(Csv $Csv, $entity)
300
    {
301
        // エンティティ名が一致するかどうかチェック.
302
        $csvEntityName = str_replace('\\\\', '\\', $Csv->getEntityName());
303
        $entityName = ClassUtils::getClass($entity);
304
        if ($csvEntityName !== $entityName) {
305
            return null;
306
        }
307
308
        // カラム名がエンティティに存在するかどうかをチェック.
309
        if (!$entity->offsetExists($Csv->getFieldName())) {
310
            return null;
311
        }
312
313
        // データを取得.
314
        $data = $entity->offsetGet($Csv->getFieldName());
315
316
        // one to one の場合は, dtb_csv.referece_field_nameと比較し, 合致する結果を取得する.
317
        if ($data instanceof \Eccube\Entity\AbstractEntity) {
318
            if (EntityUtil::isNotEmpty($data)) {
319
                return $data->offsetGet($Csv->getReferenceFieldName());
320
            }
321
        } elseif ($data instanceof \Doctrine\Common\Collections\Collection) {
322
            // one to manyの場合は, カンマ区切りに変換する.
323
            $array = [];
324
            foreach ($data as $elem) {
325
                if (EntityUtil::isNotEmpty($elem)) {
326
                    $array[] = $elem->offsetGet($Csv->getReferenceFieldName());
327
                }
328
            }
329
330
            return implode($this->eccubeConfig['eccube_csv_export_multidata_separator'], $array);
331
        } elseif ($data instanceof \DateTime) {
332
            // datetimeの場合は文字列に変換する.
333
            return $data->format($this->eccubeConfig['eccube_csv_export_date_format']);
334
        } else {
335
            // スカラ値の場合はそのまま.
336
            return $data;
337
        }
338
339
        return null;
340
    }
341
342
    /**
343
     * 文字エンコーディングの変換を行うコールバック関数を返す.
344
     *
345
     * @return \Closure
346
     */
347
    public function getConvertEncodhingCallback()
348
    {
349
        $config = $this->eccubeConfig;
350
351
        return function ($value) use ($config) {
352
            return mb_convert_encoding(
353
                (string) $value, $config['eccube_csv_export_encoding'], 'UTF-8'
354
            );
355
        };
356
    }
357
358
    public function fopen()
359
    {
360
        if (is_null($this->fp) || $this->closed) {
361
            $this->fp = fopen('php://output', 'w');
362
        }
363
    }
364
365
    /**
366
     * @param $row
367
     * @param null $callback
368
     */
369
    public function fputcsv($row)
370
    {
371
        if (is_null($this->convertEncodingCallBack)) {
372
            $this->convertEncodingCallBack = $this->getConvertEncodhingCallback();
373
        }
374
375
        fputcsv($this->fp, array_map($this->convertEncodingCallBack, $row), $this->eccubeConfig['eccube_csv_export_separator']);
376
    }
377
378
    public function fclose()
379
    {
380
        if (!$this->closed) {
381
            fclose($this->fp);
382
            $this->closed = true;
383
        }
384
    }
385
386
    /**
387
     * 受注検索用のクエリビルダを返す.
388
     *
389
     * @param Request $request
390
     *
391
     * @return \Doctrine\ORM\QueryBuilder
392
     */
393 View Code Duplication
    public function getOrderQueryBuilder(Request $request)
394
    {
395
        $session = $request->getSession();
396
        $builder = $this->formFactory
397
            ->createBuilder(SearchProductType::class);
398
        $searchForm = $builder->getForm();
399
400
        $viewData = $session->get('eccube.admin.order.search', []);
401
        $searchData = FormUtil::submitAndGetData($searchForm, $viewData);
402
403
        // 受注データのクエリビルダを構築.
404
        $qb = $this->orderRepository
405
            ->getQueryBuilderBySearchDataForAdmin($searchData);
406
407
        return $qb;
408
    }
409
410
    /**
411
     * 会員検索用のクエリビルダを返す.
412
     *
413
     * @param Request $request
414
     *
415
     * @return \Doctrine\ORM\QueryBuilder
416
     */
417 View Code Duplication
    public function getCustomerQueryBuilder(Request $request)
418
    {
419
        $session = $request->getSession();
420
        $builder = $this->formFactory
421
            ->createBuilder(SearchProductType::class);
422
        $searchForm = $builder->getForm();
423
424
        $viewData = $session->get('eccube.admin.customer.search', []);
425
        $searchData = FormUtil::submitAndGetData($searchForm, $viewData);
426
427
        // 会員データのクエリビルダを構築.
428
        $qb = $this->customerRepository
429
            ->getQueryBuilderBySearchData($searchData);
430
431
        return $qb;
432
    }
433
434
    /**
435
     * 商品検索用のクエリビルダを返す.
436
     *
437
     * @param Request $request
438
     *
439
     * @return \Doctrine\ORM\QueryBuilder
440
     */
441 View Code Duplication
    public function getProductQueryBuilder(Request $request)
0 ignored issues
show
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...
442
    {
443
        $session = $request->getSession();
444
        $builder = $this->formFactory
445
            ->createBuilder(SearchProductType::class);
446
        $searchForm = $builder->getForm();
447
448
        $viewData = $session->get('eccube.admin.product.search', []);
449
        $searchData = FormUtil::submitAndGetData($searchForm, $viewData);
450
451
        // 商品データのクエリビルダを構築.
452
        $qb = $this->productRepository
453
            ->getQueryBuilderBySearchDataForAdmin($searchData);
454
455
        return $qb;
456
    }
457
}
458