Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
56.52% covered (warning)
56.52%
13 / 23
CRAP
57.02% covered (warning)
57.02%
65 / 114
CsvExportService
0.00% covered (danger)
0.00%
0 / 1
56.52% covered (warning)
56.52%
13 / 23
239.66
57.02% covered (warning)
57.02%
65 / 114
 setConfig
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 setCsvRepository
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 setCsvTypeRepository
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 setOrderRepository
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 setCustomerRepository
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 setProductRepository
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 setEntityManager
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getEntityManager
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 setExportQueryBuilder
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 initCsvType
0.00% covered (danger)
0.00%
0 / 1
2.01
85.71% covered (warning)
85.71%
6 / 7
 getCsvs
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 exportHeader
0.00% covered (danger)
0.00%
0 / 1
4.02
88.89% covered (warning)
88.89%
8 / 9
 exportData
0.00% covered (danger)
0.00%
0 / 1
4.01
90.91% covered (success)
90.91%
10 / 11
 getData
0.00% covered (danger)
0.00%
0 / 1
30.63
40.91% covered (danger)
40.91%
9 / 22
 getConvertEncodhingCallback
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 anonymous function
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 fopen
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
3 / 3
 fputcsv
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 fclose
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 getOrderQueryBuilder
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 8
 getCustomerQueryBuilder
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 8
 getProductQueryBuilder
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 8
 findDeserializeObjects
0.00% covered (danger)
0.00%
0 / 1
20
0.00% covered (danger)
0.00%
0 / 4
<?php
/*
 * This file is part of EC-CUBE
 *
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
 *
 * http://www.lockon.co.jp/
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
namespace Eccube\Service;
use Eccube\Common\Constant;
use Eccube\Util\EntityUtil;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\Common\Collections\ArrayCollection;
class CsvExportService
{
    /**
     * @var
     */
    protected $fp;
    /**
     * @var
     */
    protected $closed = false;
    /**
     * @var \Closure
     */
    protected $convertEncodingCallBack;
    /**
     * @var \Doctrine\ORM\EntityManager
     */
    protected $em;
    /**
     * @var \Doctrine\ORM\QueryBuilder;
     */
    protected $qb;
    /**
     * @var array
     */
    protected $config;
    /**
     * @var \Eccube\Entity\Master\CsvType
     */
    protected $CsvType;
    /**
     * @var \Eccube\Entity\Csv[]
     */
    protected $Csvs;
    /**
     * @var \Eccube\Repository\CsvRepository
     */
    protected $csvRepository;
    /**
     * @var \Eccube\Repository\Master\CsvTypeRepository
     */
    protected $csvTypeRepository;
    /**
     * @var \Eccube\Repository\OrderRepository
     */
    protected $orderRepository;
    /**
     * @var \Eccube\Repository\CustomerRepository
     */
    protected $customerRepository;
    /**
     * @var \Eccube\Repository\ProductRepository
     */
    protected $productRepository;
    /**
     * @param $config
     */
    public function setConfig($config)
    {
        $this->config = $config;
    }
    /**
     * @param \Eccube\Repository\CsvRepository $csvRepository
     */
    public function setCsvRepository(\Eccube\Repository\CsvRepository $csvRepository)
    {
        $this->csvRepository = $csvRepository;
    }
    /**
     * @param \Eccube\Repository\Master\CsvTypeRepository $csvTypeRepository
     */
    public function setCsvTypeRepository(\Eccube\Repository\Master\CsvTypeRepository $csvTypeRepository)
    {
        $this->csvTypeRepository = $csvTypeRepository;
    }
    /**
     * @param \Eccube\Repository\OrderRepository $orderRepository
     */
    public function setOrderRepository(\Eccube\Repository\OrderRepository $orderRepository)
    {
        $this->orderRepository = $orderRepository;
    }
    /**
     * @param \Eccube\Repository\CustomerRepository $customerRepository
     */
    public function setCustomerRepository(\Eccube\Repository\CustomerRepository $customerRepository)
    {
        $this->customerRepository = $customerRepository;
    }
    /**
     * @param \Eccube\Repository\ProductRepository $productRepository
     */
    public function setProductRepository(\Eccube\Repository\ProductRepository $productRepository)
    {
        $this->productRepository = $productRepository;
    }
    /**
     * @param \Doctrine\ORM\EntityManager $em
     */
    public function setEntityManager(\Doctrine\ORM\EntityManager $em)
    {
        $this->em = $em;
    }
    /**
     * @return \Doctrine\ORM\EntityManager
     */
    public function getEntityManager()
    {
        return $this->em;
    }
    /**
     * @param \Doctrine\ORM\QueryBuilder $qb
     */
    public function setExportQueryBuilder(\Doctrine\ORM\QueryBuilder $qb)
    {
        $this->qb = $qb;
    }
    /**
     * Csv種別からServiceの初期化を行う.
     *
     * @param $CsvType|integer
     */
    public function initCsvType($CsvType)
    {
        if ($CsvType instanceof \Eccube\Entity\Master\CsvType) {
            $this->CsvType = $CsvType;
        } else {
            $this->CsvType = $this->csvTypeRepository->find($CsvType);
        }
        $criteria = array(
            'CsvType' => $CsvType,
            'enable_flg' => Constant::ENABLED
        );
        $orderBy = array(
            'rank' => 'ASC'
        );
        $this->Csvs = $this->csvRepository->findBy($criteria, $orderBy);
    }
    /**
     * @return \Eccube\Entity\Csv[]
     */
    public function getCsvs()
    {
        return $this->Csvs;
    }
    /**
     * ヘッダ行を出力する.
     * このメソッドを使う場合は, 事前にinitCsvType($CsvType)で初期化しておく必要がある.
     */
    public function exportHeader()
    {
        if (is_null($this->CsvType) || is_null($this->Csvs)) {
            throw new \LogicException('init csv type incomplete.');
        }
        $row = array();
        foreach ($this->Csvs as $Csv) {
            $row[] = $Csv->getDispName();
        }
        $this->fopen();
        $this->fputcsv($row);
        $this->fclose();
    }
    /**
     * クエリビルダにもとづいてデータ行を出力する.
     * このメソッドを使う場合は, 事前にsetExportQueryBuilder($qb)で出力対象のクエリビルダをわたしておく必要がある.
     *
     * @param \Closure $closure
     */
    public function exportData(\Closure $closure)
    {
        if (is_null($this->qb) || is_null($this->em)) {
            throw new \LogicException('query builder not set.');
        }
        $this->fopen();
        $query = $this->qb->getQuery();
        foreach ($query->getResult() as $iteratableResult) {
            $closure($iteratableResult, $this);
            $this->em->detach($iteratableResult);
            $query->free();
            flush();
        }
        $this->fclose();
    }
    /**
     * CSV出力項目と比較し, 合致するデータを返す.
     *
     * @param \Eccube\Entity\Csv $Csv
     * @param $entity
     * @return mixed|null|string|void
     */
    public function getData(\Eccube\Entity\Csv $Csv, $entity)
    {
        // エンティティ名が一致するかどうかチェック.
        $csvEntityName = str_replace('\\\\', '\\', $Csv->getEntityName());
        $entityName = str_replace('\\\\', '\\', get_class($entity));
        if ($csvEntityName !== $entityName) {
            $entityName = str_replace('DoctrineProxy\\__CG__\\', '', $entityName);
            if ($csvEntityName !== $entityName) {
                return null;
            }
        }
        // カラム名がエンティティに存在するかどうかをチェック.
        if (!$entity->offsetExists($Csv->getFieldName())) {
            return null;
        }
        // データを取得.
        $data = $entity->offsetGet($Csv->getFieldName());
        // one to one の場合は, dtb_csv.referece_field_nameと比較し, 合致する結果を取得する.
        if ($data instanceof \Eccube\Entity\AbstractEntity) {
            if (EntityUtil::isNotEmpty($data)) {
                return $data->offsetGet($Csv->getReferenceFieldName());
            }
        } elseif ($data instanceof \Doctrine\Common\Collections\Collection) {
            // one to manyの場合は, カンマ区切りに変換する.
            $array = array();
            foreach ($data as $elem) {
                if (EntityUtil::isNotEmpty($elem)) {
                    $array[] = $elem->offsetGet($Csv->getReferenceFieldName());
                }
            }
            return implode($this->config['csv_export_multidata_separator'], $array);
        } elseif ($data instanceof \DateTime) {
            // datetimeの場合は文字列に変換する.
            return $data->format($this->config['csv_export_date_format']);
        } else {
            // スカラ値の場合はそのまま.
            return $data;
        }
        return null;
    }
    /**
     * 文字エンコーディングの変換を行うコールバック関数を返す.
     *
     * @return \Closure
     */
    public function getConvertEncodhingCallback()
    {
        $config = $this->config;
        return function ($value) use ($config) {
            return mb_convert_encoding(
                (string) $value, $config['csv_export_encoding'], 'UTF-8'
            );
        };
    }
    /**
     *
     */
    public function fopen()
    {
        if (is_null($this->fp) || $this->closed) {
            $this->fp = fopen('php://output', 'w');
        }
    }
    /**
     * @param $row
     * @param null $callback
     */
    public function fputcsv($row)
    {
        if (is_null($this->convertEncodingCallBack)) {
            $this->convertEncodingCallBack = $this->getConvertEncodhingCallback();
        }
        fputcsv($this->fp, array_map($this->convertEncodingCallBack, $row), $this->config['csv_export_separator']);
    }
    /**
     *
     */
    public function fclose()
    {
        if (!$this->closed) {
            fclose($this->fp);
            $this->closed = true;
        }
    }
    /**
     * 受注検索用のクエリビルダを返す.
     *
     * @param Request $request
     * @return \Doctrine\ORM\QueryBuilder
     */
    public function getOrderQueryBuilder(Request $request)
    {
        $session = $request->getSession();
        if ($session->has('eccube.admin.order.search')) {
            $searchData = $session->get('eccube.admin.order.search');
            $this->findDeserializeObjects($searchData);
        } else {
            $searchData = array();
        }
        // 受注データのクエリビルダを構築.
        $qb = $this->orderRepository
            ->getQueryBuilderBySearchDataForAdmin($searchData);
        return $qb;
    }
    /**
     * 会員検索用のクエリビルダを返す.
     *
     * @param Request $request
     * @return \Doctrine\ORM\QueryBuilder
     */
    public function getCustomerQueryBuilder(Request $request)
    {
        $session = $request->getSession();
        if ($session->has('eccube.admin.customer.search')) {
            $searchData = $session->get('eccube.admin.customer.search');
            $this->findDeserializeObjects($searchData);
        } else {
            $searchData = array();
        }
        // 会員データのクエリビルダを構築.
        $qb = $this->customerRepository
            ->getQueryBuilderBySearchData($searchData);
        return $qb;
    }
    /**
     * 商品検索用のクエリビルダを返す.
     *
     * @param Request $request
     * @return \Doctrine\ORM\QueryBuilder
     */
    public function getProductQueryBuilder(Request $request)
    {
        $session = $request->getSession();
        if ($session->has('eccube.admin.product.search')) {
            $searchData = $session->get('eccube.admin.product.search');
            $this->findDeserializeObjects($searchData);
        } else {
            $searchData = array();
        }
        // 商品データのクエリビルダを構築.
        $qb = $this->productRepository
            ->getQueryBuilderBySearchDataForAdmin($searchData);
        return $qb;
    }
    /**
     * セッションでシリアライズされた Doctrine のオブジェクトを取得し直す.
     *
     * XXX self::setExportQueryBuilder() をコールする前に EntityManager を取得したいので、引数で渡している
     *
     * @param array $searchData セッションから取得した検索条件の配列
     * @param EntityManager $em
     */
    protected function findDeserializeObjects(array &$searchData)
    {
        $em = $this->getEntityManager();
        foreach ($searchData as &$Conditions) {
            if ($Conditions instanceof ArrayCollection) {
                $Conditions = new ArrayCollection(
                    array_map(
                        function ($Entity) use ($em) {
                            return $em->getRepository(get_class($Entity))->find($Entity->getId());
                        }, $Conditions->toArray()
                    )
                );
            } elseif ($Conditions instanceof \Eccube\Entity\AbstractEntity) {
                $Conditions = $em->getRepository(get_class($Conditions))->find($Conditions->getId());
            }
        }
    }
}