src/Eccube/Service/CsvExportService.php line 293

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