Last active
June 20, 2019 11:40
-
-
Save faizanakram99/adf21153247ab23ea959f2d14304199b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Qbil\TradeBundle\Domain; | |
use Doctrine\ORM\EntityManagerInterface; | |
use Qbil\TradeBundle\Entity\Contract; | |
use Qbil\TradeBundle\Entity\Contractline; | |
use Qbil\TradeBundle\Entity\Eenheid; | |
use Qbil\TradeBundle\Entity\Log; | |
use Symfony\Component\Security\Core\User\UserInterface; | |
class ContractVolumeChanged implements VolumeChangedInterface | |
{ | |
/** | |
* @var EntityManagerInterface | |
*/ | |
private $entityManager; | |
public function __construct(EntityManagerInterface $entityManager) | |
{ | |
$this->entityManager = $entityManager; | |
} | |
public function getVolumeChanged(UserInterface $user, \DateTimeInterface $date): array | |
{ | |
$rawContractHistory = $this | |
->entityManager | |
->getRepository(Log::class) | |
->getLogs($user, $date->format('Y-m-d'), 'contract'); | |
$totalQuantityGroupedByUnit = []; | |
$existingContracts = []; | |
/** @var Log $log */ | |
foreach ($rawContractHistory as $log) { | |
$contract = $log->getContent(); | |
if (!$contract['id'] || !$this->entityManager->find(Contract::class, $contract['id'])) { | |
continue; | |
} | |
if (Contract::STATUS_CONTRACT !== $contract['status']) { | |
continue; | |
} | |
if (in_array($contract['id'], $existingContracts)) { | |
continue; | |
} | |
$existingContracts[] = $contract['id']; | |
foreach ($contract['lines'] as $contractLine) { | |
if (!$contractLine['id'] || !$this->entityManager->find(Contractline::class, $contractLine['id'])) { | |
continue; | |
} | |
if (!isset($totalQuantityGroupedByUnit[$contractLine['unit']])) { | |
$totalQuantityGroupedByUnit[$contractLine['unit']] = 0; | |
} | |
$totalQuantityGroupedByUnit[$contractLine['unit']] += $contractLine['quantity']; | |
} | |
} | |
$totalQuantityGroupedByMeasurement = []; | |
foreach ($totalQuantityGroupedByUnit as $unit => $quantity) { | |
$unitEntity = $this->entityManager->find(Eenheid::class, $unit); | |
$totalQuantityGroupedByMeasurement[$unitEntity->getMeasurement()] = $quantity * $unitEntity->getSIfactor(); | |
} | |
return $totalQuantityGroupedByMeasurement; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Qbil\CommonBundle\Security; | |
use Doctrine\ORM\EntityManagerInterface; | |
use Qbil\TradeBundle\Domain\VolumeChangedInterface; | |
use Qbil\TradeBundle\Entity\Contract; | |
use Qbil\TradeBundle\Entity\Eenheid; | |
use Qbil\TradeBundle\Entity\Permission; | |
use Qbil\TradeBundle\Entity\Useraccount; | |
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; | |
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; | |
use Symfony\Component\Security\Core\Authorization\Voter\Voter; | |
class TradingVolumeLimitationVoter extends Voter | |
{ | |
const CHECK = 'check'; | |
/** | |
* @var AccessDecisionManagerInterface | |
*/ | |
private $decisionManager; | |
/** | |
* @var EntityManagerInterface | |
*/ | |
private $entityManager; | |
/** | |
* @var VolumeChangedInterface | |
*/ | |
private $volumeChanged; | |
public function __construct( | |
AccessDecisionManagerInterface $decisionManager, | |
VolumeChangedInterface $volumeChanged, | |
EntityManagerInterface $entityManager | |
) { | |
$this->decisionManager = $decisionManager; | |
$this->volumeChanged = $volumeChanged; | |
$this->entityManager = $entityManager; | |
} | |
/** | |
* Determines if the attribute and subject are supported by this voter. | |
* | |
* @param string $attribute An attribute | |
* @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type | |
* | |
* @return bool True if the attribute and subject are supported, false otherwise | |
*/ | |
protected function supports($attribute, $subject) | |
{ | |
if (!$subject instanceof Contract) { | |
return false; | |
} | |
if (self::CHECK !== $attribute) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Perform a single access check operation on a given attribute, subject and token. | |
* It is safe to assume that $attribute and $subject already passed the "supports()" method check. | |
* | |
* @param string $attribute | |
* @param Contract $subject | |
* @param TokenInterface $token | |
* | |
* @return bool | |
* | |
* @throws \Exception | |
*/ | |
protected function voteOnAttribute($attribute, $subject, TokenInterface $token) | |
{ | |
$user = $token->getUser(); | |
if (!$user instanceof Useraccount) { | |
return false; | |
} | |
if ($this->decisionManager->decide($token, ['ROLE_SUPER_ADMIN'])) { | |
return true; | |
} | |
$unsavedContractLineQuantitiesGroupedByMeasurement = []; | |
foreach ($subject->getContractlines() as $contractLine) { | |
if (!isset($unsavedContractLineQuantitiesGroupedByMeasurement[$contractLine->getUnit()->getMeasurement()])) { | |
$unsavedContractLineQuantitiesGroupedByMeasurement[$contractLine->getUnit()->getMeasurement()] = 0; | |
} | |
if ($contractLine->getId()) { | |
$unsavedContractLineQuantitiesGroupedByMeasurement[$contractLine->getUnit()->getMeasurement()] += ( | |
array_key_exists('hoeveelheid', $contractLineChangeSet = $this->entityManager->getUnitOfWork()->getEntityChangeSet($contractLine)) | |
? $contractLineChangeSet['hoeveelheid'][1] - $contractLineChangeSet['hoeveelheid'][0] | |
: 0 | |
); | |
} else { | |
$unsavedContractLineQuantitiesGroupedByMeasurement[$contractLine->getUnit()->getMeasurement()] += $contractLine->getQuantityInSiUnit(); | |
} | |
} | |
$totalQuantityGroupedByMeasurement = $this->volumeChanged->getVolumeChanged($user, new \DateTimeImmutable()); | |
foreach ($this->entityManager->getRepository(Eenheid::class)->groupUnitsByMeasurement() as $measurement => $unit) { | |
$previouslyTradedVolume = isset($totalQuantityGroupedByMeasurement[$measurement]) ? abs($totalQuantityGroupedByMeasurement[$measurement]) : 0; | |
$volume = $previouslyTradedVolume + ($unsavedContractLineQuantitiesGroupedByMeasurement[$measurement] ?? 0); | |
if (!$user->getPermissionHandler()->hasPermissionWithVolumeOver(Permission::MUTATION_DAILY_CONTRACT_VOLUME_LIMIT, $measurement, $volume)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Qbil\TradeBundle\Domain; | |
use Symfony\Component\Security\Core\User\UserInterface; | |
interface VolumeChangedInterface | |
{ | |
public function getVolumeChanged(UserInterface $user, \DateTimeInterface $date): array; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment