Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
53.33% covered (warning)
53.33%
8 / 15
CRAP
62.43% covered (warning)
62.43%
118 / 189
CustomerRepository
0.00% covered (danger)
0.00%
0 / 1
53.33% covered (warning)
53.33%
8 / 15
281.14
62.43% covered (warning)
62.43%
118 / 189
 setApplication
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 newCustomer
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
7 / 7
 loadUserByUsername
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
17 / 17
 refreshUser
0.00% covered (danger)
0.00%
0 / 1
2.15
66.67% covered (warning)
66.67%
2 / 3
 supportsClass
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 getQueryBuilderBySearchData
0.00% covered (danger)
0.00%
0 / 1
515.36
34.41% covered (danger)
34.41%
32 / 93
 getUniqueSecretKey
0.00% covered (danger)
0.00%
0 / 1
2.02
83.33% covered (warning)
83.33%
5 / 6
 getUniqueResetKey
0.00% covered (danger)
0.00%
0 / 1
2.02
83.33% covered (warning)
83.33%
5 / 6
 createSalt
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 encryptPassword
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getNonActiveCustomerBySecretKey
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
8 / 8
 getActiveCustomerByEmail
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
8 / 8
 getActiveCustomerByResetKey
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
8 / 8
 getResetPassword
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 updateBuyData
0.00% covered (danger)
0.00%
0 / 1
6.15
84.00% covered (warning)
84.00%
21 / 25
<?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\Repository;
use Doctrine\ORM\EntityRepository;
use Eccube\Common\Constant;
use Eccube\Entity\Customer;
use Eccube\Entity\Master\CustomerStatus;
use Eccube\Util\Str;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Util\SecureRandom;
/**
 * CustomerRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class CustomerRepository extends EntityRepository implements UserProviderInterface
{
    protected $app;
    public function setApplication($app)
    {
        $this->app = $app;
    }
    public function newCustomer()
    {
        $Customer = new \Eccube\Entity\Customer();
        $Status = $this->getEntityManager()
            ->getRepository('Eccube\Entity\Master\CustomerStatus')
            ->find(1);
        $Customer
            ->setStatus($Status)
            ->setDelFlg(0);
        return $Customer;
    }
    /**
     * Loads the user for the given username.
     *
     * This method must throw UsernameNotFoundException if the user is not
     * found.
     *
     * @param string $username The username
     *
     * @return UserInterface
     *
     * @see UsernameNotFoundException
     *
     * @throws UsernameNotFoundException if the user is not found
     */
    public function loadUserByUsername($username)
    {
        // 本会員ステータスの会員のみ有効.
        $CustomerStatus = $this
            ->getEntityManager()
            ->getRepository('Eccube\Entity\Master\CustomerStatus')
            ->find(CustomerStatus::ACTIVE);
        $query = $this->createQueryBuilder('c')
            ->where('c.email = :email')
            ->andWhere('c.del_flg = :delFlg')
            ->andWhere('c.Status =:CustomerStatus')
            ->setParameters(array(
                'email' => $username,
                'delFlg' => Constant::DISABLED,
                'CustomerStatus' => $CustomerStatus,
            ))
            ->setMaxResults(1)
            ->getQuery();
        $Customer = $query->getOneOrNullResult();
        if (!$Customer) {
            throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
        }
        return $Customer;
    }
    /**
     * Refreshes the user for the account interface.
     *
     * It is up to the implementation to decide if the user data should be
     * totally reloaded (e.g. from the database), or if the UserInterface
     * object can just be merged into some internal array of users / identity
     * map.
     *
     * @param UserInterface $user
     *
     * @return UserInterface
     *
     * @throws UnsupportedUserException if the account is not supported
     */
    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof Customer) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
        }
        return $this->loadUserByUsername($user->getUsername());
    }
    /**
     * Whether this provider supports the given user class.
     *
     * @param string $class
     *
     * @return bool
     */
    public function supportsClass($class)
    {
        return $class === 'Eccube\Entity\Customer';
    }
    public function getQueryBuilderBySearchData($searchData)
    {
        $qb = $this->createQueryBuilder('c')
            ->select('c')
            ->andWhere('c.del_flg = 0');
        if (isset($searchData['multi']) && Str::isNotBlank($searchData['multi'])) {
            //スペース除去
            $clean_key_multi = preg_replace('/\s+|[ ]+/u', '',$searchData['multi']);
            if (preg_match('/^\d+$/', $clean_key_multi)) {
                $qb
                    ->andWhere('c.id = :customer_id')
                    ->setParameter('customer_id', $clean_key_multi);
            } else {
                $qb
                    ->andWhere('CONCAT(c.name01, c.name02) LIKE :name OR CONCAT(c.kana01, c.kana02) LIKE :kana OR c.email LIKE :email')
                    ->setParameter('name', '%' . $clean_key_multi . '%')
                    ->setParameter('kana', '%' . $clean_key_multi . '%')
                    ->setParameter('email', '%' . $clean_key_multi . '%');
            }
        }
        // Pref
        if (!empty($searchData['pref']) && $searchData['pref']) {
            $qb
                ->andWhere('c.Pref = :pref')
                ->setParameter('pref', $searchData['pref']->getId());
        }
        // sex
        if (!empty($searchData['sex']) && count($searchData['sex']) > 0) {
            $sexs = array();
            foreach ($searchData['sex'] as $sex) {
                $sexs[] = $sex->getId();
            }
            $qb
                ->andWhere($qb->expr()->in('c.Sex', ':sexs'))
                ->setParameter('sexs', $sexs);
        }
        if (!empty($searchData['birth_month']) && $searchData['birth_month']) {
            $qb
                ->andWhere('EXTRACT(MONTH FROM c.birth) = :birth_month')
                ->setParameter('birth_month', $searchData['birth_month']);
        }
        // birth
        if (!empty($searchData['birth_start']) && $searchData['birth_start']) {
            $date = $searchData['birth_start']
                ->format('Y-m-d H:i:s');
            $qb
                ->andWhere('c.birth >= :birth_start')
                ->setParameter('birth_start', $date);
        }
        if (!empty($searchData['birth_end']) && $searchData['birth_end']) {
            $date = clone $searchData['birth_end'];
            $date = $date
                ->modify('+1 days')
                ->format('Y-m-d H:i:s');
            $qb
                ->andWhere('c.birth < :birth_end')
                ->setParameter('birth_end', $date);
        }
        // tel
        if (isset($searchData['tel']) && Str::isNotBlank($searchData['tel'])) {
            $qb
                ->andWhere('CONCAT(c.tel01, c.tel02, c.tel03) LIKE :tel')
                ->setParameter('tel', '%' . $searchData['tel'] . '%');
        }
        // buy_total
        if (isset($searchData['buy_total_start']) && Str::isNotBlank($searchData['buy_total_start'])) {
            $qb
                ->andWhere('c.buy_total >= :buy_total_start')
                ->setParameter('buy_total_start', $searchData['buy_total_start']);
        }
        if (isset($searchData['buy_total_end']) && Str::isNotBlank($searchData['buy_total_end'])) {
            $qb
                ->andWhere('c.buy_total <= :buy_total_end')
                ->setParameter('buy_total_end', $searchData['buy_total_end']);
        }
        // buy_times
        if (!empty($searchData['buy_times_start']) && $searchData['buy_times_start']) {
            $qb
                ->andWhere('c.buy_times >= :buy_times_start')
                ->setParameter('buy_times_start', $searchData['buy_times_start']);
        }
        if (!empty($searchData['buy_times_end']) && $searchData['buy_times_end']) {
            $qb
                ->andWhere('c.buy_times <= :buy_times_end')
                ->setParameter('buy_times_end', $searchData['buy_times_end']);
        }
        // create_date
        if (!empty($searchData['create_date_start']) && $searchData['create_date_start']) {
            $date = $searchData['create_date_start']
                ->format('Y-m-d H:i:s');
            $qb
                ->andWhere('c.create_date >= :create_date_start')
                ->setParameter('create_date_start', $date);
        }
        if (!empty($searchData['create_date_end']) && $searchData['create_date_end']) {
            $date = clone $searchData['create_date_end'];
            $date = $date
                ->modify('+1 days')
                ->format('Y-m-d H:i:s');
            $qb
                ->andWhere('c.create_date < :create_date_end')
                ->setParameter('create_date_end', $date);
        }
        // update_date
        if (!empty($searchData['update_date_start']) && $searchData['update_date_start']) {
            $date = $searchData['update_date_start']
                ->format('Y-m-d H:i:s');
            $qb
                ->andWhere('c.update_date >= :update_date_start')
                ->setParameter('update_date_start', $date);
        }
        if (!empty($searchData['update_date_end']) && $searchData['update_date_end']) {
            $date = clone $searchData['update_date_end'];
            $date = $date
                ->modify('+1 days')
                ->format('Y-m-d H:i:s');
            $qb
                ->andWhere('c.update_date < :update_date_end')
                ->setParameter('update_date_end', $date);
        }
        // last_buy
        if (!empty($searchData['last_buy_start']) && $searchData['last_buy_start']) {
            $date = $searchData['last_buy_start']
                ->format('Y-m-d H:i:s');
            $qb
                ->andWhere('c.last_buy_date >= :last_buy_start')
                ->setParameter('last_buy_start', $date);
        }
        if (!empty($searchData['last_buy_end']) && $searchData['last_buy_end']) {
            $date = clone $searchData['last_buy_end'];
            $date = $date
                ->modify('+1 days')
                ->format('Y-m-d H:i:s');
            $qb
                ->andWhere('c.last_buy_date < :last_buy_end')
                ->setParameter('last_buy_end', $date);
        }
        // status
        if (!empty($searchData['customer_status']) && count($searchData['customer_status']) > 0) {
            $qb
                ->andWhere($qb->expr()->in('c.Status', ':statuses'))
                ->setParameter('statuses', $searchData['customer_status']);
        }
        // buy_product_name、buy_product_code
        if (isset($searchData['buy_product_code']) && Str::isNotBlank($searchData['buy_product_code'])) {
            $qb
                ->leftJoin('c.Orders', 'o')
                ->leftJoin('o.OrderDetails', 'od')
                ->andWhere('od.product_name LIKE :buy_product_name OR od.product_code LIKE :buy_product_name')
                ->setParameter('buy_product_name', '%' . $searchData['buy_product_code'] . '%');
        }
        // Order By
        $qb->addOrderBy('c.update_date', 'DESC');
        return $qb;
    }
    /**
     * ユニークなシークレットキーを返す
     * @param $app
     * @return string
     */
    public function getUniqueSecretKey($app)
    {
        $unique = Str::random(32);
        $Customer = $app['eccube.repository.customer']->findBy(array(
            'secret_key' => $unique,
        ));
        if (count($Customer) == 0) {
            return $unique;
        } else {
            return $this->getUniqueSecretKey($app);
        }
    }
    /**
     * ユニークなパスワードリセットキーを返す
     * @param $app
     * @return string
     */
    public function getUniqueResetKey($app)
    {
        $unique = Str::random(32);
        $Customer = $app['eccube.repository.customer']->findBy(array(
                        'reset_key' => $unique,
        ));
        if (count($Customer) == 0) {
            return $unique;
        } else {
            return $this->getUniqueResetKey($app);
        }
    }
    /**
     * saltを生成する
     *
     * @param $byte
     * @return string
     */
    public function createSalt($byte)
    {
        $generator = new SecureRandom();
        return bin2hex($generator->nextBytes($byte));
    }
    /**
     * 入力されたパスワードをSaltと暗号化する
     *
     * @param $app
     * @param  Customer $Customer
     * @return mixed
     */
    public function encryptPassword($app, \Eccube\Entity\Customer $Customer)
    {
        $encoder = $app['security.encoder_factory']->getEncoder($Customer);
        return $encoder->encodePassword($Customer->getPassword(), $Customer->getSalt());
    }
    public function getNonActiveCustomerBySecretKey($secret_key)
    {
        $qb = $this->createQueryBuilder('c')
            ->where('c.del_flg = 0 AND c.secret_key = :secret_key')
            ->leftJoin('c.Status', 's')
            ->andWhere('s.id = :status')
            ->setParameter('secret_key', $secret_key)
            ->setParameter('status', CustomerStatus::NONACTIVE);
        $query = $qb->getQuery();
        return $query->getSingleResult();
    }
    public function getActiveCustomerByEmail($email)
    {
        $query = $this->createQueryBuilder('c')
            ->where('c.email = :email AND c.Status = :status')
            ->setParameter('email', $email)
            ->setParameter('status', CustomerStatus::ACTIVE)
            ->setMaxResults(1)
            ->getQuery();
        $Customer = $query->getOneOrNullResult();
        return $Customer;
    }
    public function getActiveCustomerByResetKey($reset_key)
    {
        $query = $this->createQueryBuilder('c')
            ->where('c.reset_key = :reset_key AND c.Status = :status AND c.reset_expire >= :reset_expire')
            ->setParameter('reset_key', $reset_key)
            ->setParameter('status', CustomerStatus::ACTIVE)
            ->setParameter('reset_expire', new \DateTime())
            ->getQuery();
        $Customer = $query->getSingleResult();
        return $Customer;
    }
    public function getResetPassword()
    {
        return Str::random(8);
    }
    /**
     * 会員の初回購入時間、購入時間、購入回数、購入金額を更新する
     *
     * @param $app
     * @param  Customer $Customer
     * @param  $orderStatusId
     */
    public function updateBuyData($app, Customer $Customer, $orderStatusId)
    {
        // 会員の場合、初回購入時間・購入時間・購入回数・購入金額を更新
        $arr = array($app['config']['order_new'],
                                $app['config']['order_pay_wait'],
                                $app['config']['order_back_order'],
                                $app['config']['order_deliv'],
                                $app['config']['order_pre_end'],
                        );
        $result = $app['eccube.repository.order']->getCustomerCount($Customer, $arr);
        if (!empty($result)) {
            $data = $result[0];
            $now = new \DateTime();
            $firstBuyDate = $Customer->getFirstBuyDate();
            if (empty($firstBuyDate)) {
                $Customer->setFirstBuyDate($now);
            }
            if ($orderStatusId == $app['config']['order_cancel'] ||
                    $orderStatusId == $app['config']['order_pending'] ||
                    $orderStatusId == $app['config']['order_processing']) {
                // キャンセル、決済処理中、購入処理中は購入時間は更新しない
            } else {
                $Customer->setLastBuyDate($now);
            }
            $Customer->setBuyTimes($data['buy_times']);
            $Customer->setBuyTotal($data['buy_total']);
        } else {
            // 受注データが存在しなければ初期化
            $Customer->setFirstBuyDate(null);
            $Customer->setLastBuyDate(null);
            $Customer->setBuyTimes(0);
            $Customer->setBuyTotal(0);
        }
        $app['orm.em']->persist($Customer);
        $app['orm.em']->flush();
    }
}