<?php
declare(strict_types=1);
/**
* CreditCardRepository.php File.
* This file is part of the Payment.net Project.
*
* PHP version 5
*
* @category Application
* @package Bdm\CheckoutBundle\Repository
* @author Pavel Baraulya <pbaraulya@bdmultimedia.fr>
* @link http://www.payment.net/
*
* FEATURES :
* ==========
*
* TODO-LIST :
* ===========
*
* HISTORY :
* =========
* 20150710 - Pavel Baraulya
* 20150916 - Alexandr Bakurin - add iterateCardsExpiringBeforePayment() method
* 20151009 - Helen Tochko - update Token
*/
namespace Bdm\CheckoutBundle\Repository;
use Bdm\CheckoutBundle\Entity\CreditCard;
use Bdm\CheckoutBundle\Entity\Subscription;
use Bdm\CheckoutBundle\Entity\SubscriptionPlan;
use Bdm\CheckoutBundle\Entity\Token;
use Bdm\CheckoutBundle\Exception\CreditCardException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query;
use Doctrine\Persistence\ObjectRepository;
use Symfony\Component\Config\Definition\Exception\Exception;
/**
* Class CreditCardRepository
*/
class CreditCardRepository
{
protected ObjectRepository $oRepository;
/**
* Constructor
*
* @param EntityManager $oEm entity manager
* @param TokenRepository $oTokenRepository token repository
*/
public function __construct(protected EntityManager $oEm, protected TokenRepository $oTokenRepository)
{
$this->oRepository = $oEm->getRepository(CreditCard::class);
}
/**
* Find by token
*
* @param string $sToken token
* @param bool $bCheckToken check token
*
* @return CreditCard
* @throws InvalidTokenException
*/
public function findOneByToken($sToken, $bCheckToken = true)
{
if ((bool) $bCheckToken) {
$oToken = $this->oTokenRepository->findValidToken($sToken);
} else {
$oToken = $this->oTokenRepository->findByHash($sToken);
}
$oEntity = $this->oRepository->find($oToken->getEntityId());
if ($oEntity instanceof CreditCard) {
return $oEntity;
}
throw new InvalidTokenException();
}
/**
* Save credit card
*
* @param CreditCard $oCreditCard credit card
*
* @return CreditCard
* @throws Exception
*/
public function save(CreditCard $oCreditCard)
{
$this->oEm->persist($oCreditCard);
$this->oEm->flush();
return $oCreditCard;
}
/**
* Add new credit card
*
* @deprecated: use self::save(CreditCard $oCreditCard) instead of this method
*
* @param CreditCard $oCreditCard credit card
*
* @return CreditCard
* @throws Exception
*/
public function add(CreditCard $oCreditCard)
{
return $this->save($oCreditCard);
}
/**
* Update token
*
* @param CreditCard $oCreditCard credit card
*
* @return CreditCard
*/
public function updateToken(CreditCard $oCreditCard)
{
if ($oCreditCard->getToken()) {
$oCreditCard->getToken()->setUsed();
}
$oToken = new Token();
$oToken->setEntity($oCreditCard);
$oCreditCard->setToken($oToken);
$this->oTokenRepository->add($oToken);
return $oCreditCard;
}
/**
* Find which is gonna be expired before next payment
*
* @return \Generator<CreditCard>
*/
public function iterateCardsExpiringBeforePayment()
{
$oIterator = $this->oRepository->createQueryBuilder('cc')
->innerJoin(Subscription::class, 's', 'WITH', 's.oPaymentMethod = cc.iId')
->innerJoin(SubscriptionPlan::class, 'sp', 'WITH', 'sp.iId = s.oSubscriptionPlan')
->where('cc.bActive = :isCcActive')
->andWhere('s.bActive = :isSubActive')
->andWhere('s.sState = :subState')
->andWhere('s.oUpcomingPaymentDate > cc.oExpDate')
->andWhere('s.oUpcomingPaymentDate < :beforeDate')
->andWhere('sp.bRecurring = :isRecurring')
->andWhere('sp.bActive = :isSpActive')
->andWhere('sp.sState = :spStatus')
->setParameter('isCcActive', true)
->setParameter('beforeDate', (new \DateTime())->add(new \DateInterval('P1M')))
->setParameter('isSubActive', true)
->setParameter('isSpActive', true)
->setParameter('subState', Subscription::STATE_ACTIVE)
->setParameter('spStatus', SubscriptionPlan::STATUS_ACTIVE)
->setParameter('isRecurring', true)
->groupBy('cc.iId')
->getQuery()
->iterate();
foreach ($oIterator as $oRow) {
$oCard = $oRow[0];
if ($oCard->getUpcomingPayment()->getState() === Subscription::STATE_ACTIVE) {
yield $oCard;
}
}
}
}