Failed Conditions
Push — master ( 61df42...3ac846 )
by Adrien
07:43
created

AccountRepository::getOrCreate()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 4.002

Importance

Changes 0
Metric Value
cc 4
eloc 19
nc 4
nop 1
dl 0
loc 31
ccs 19
cts 20
cp 0.95
crap 4.002
rs 9.6333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Repository;
6
7
use Application\DBAL\Types\AccountTypeType;
8
use Application\Model\Account;
9
use Application\Model\User;
10
11
class AccountRepository extends AbstractRepository implements LimitedAccessSubQueryInterface
12
{
13
    private const PARENT_ACCOUNT_ID_FOR_USER = 10011;
14
15
    /**
16
     * Returns pure SQL to get ID of all objects that are accessible to given user.
17
     *
18
     * @param null|User $user
19
     *
20
     * @return string
21
     */
22 12
    public function getAccessibleSubQuery(?User $user): string
23
    {
24 12
        if (!$user) {
25 2
            return '-1';
26
        }
27
28 10
        if (in_array($user->getRole(), [User::ROLE_RESPONSIBLE, User::ROLE_ADMINISTRATOR], true)) {
29 2
            return $this->getAllIdsQuery();
30
        }
31
32 8
        return $this->getAllIdsForOwnerQuery($user);
33
    }
34
35
    /**
36
     * Unsecured way to get a account from its ID.
37
     *
38
     * This should only be used in tests or controlled environment.
39
     *
40
     * @param int $id
41
     *
42
     * @return null|Account
43
     */
44 3
    private function getOneById(int $id): ?Account
45
    {
46 3
        $this->getAclFilter()->setEnabled(false);
47 3
        $account = $this->findOneById($id);
48 3
        $this->getAclFilter()->setEnabled(true);
49
50 3
        return $account;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $account could return the type Application\Model\AbstractModel which includes types incompatible with the type-hinted return Application\Model\Account|null. Consider adding an additional type-check to rule them out.
Loading history...
51
    }
52
53
    /**
54
     * This will return, and potentially create, an account for the given user
55
     *
56
     * @param User $user
57
     *
58
     * @return Account
59
     */
60 8
    public function getOrCreate(User $user): Account
61
    {
62
        // If an account already exists, because getOrCreate was called once before without flushing in between,
63
        // then can return immediately
64 8
        if ($user->getAccount()) {
65 6
            return $user->getAccount();
66
        }
67
68 4
        $this->getAclFilter()->setEnabled(false);
69 4
        $account = $this->findOneByOwner($user);
0 ignored issues
show
Bug introduced by
The method findOneByOwner() does not exist on Application\Repository\AccountRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

69
        /** @scrutinizer ignore-call */ 
70
        $account = $this->findOneByOwner($user);
Loading history...
70 4
        $this->getAclFilter()->setEnabled(true);
71
72 4
        if (!$account) {
73 3
            $account = new Account();
74 3
            $this->getEntityManager()->persist($account);
75 3
            $account->setOwner($user);
76 3
            $account->setType(AccountTypeType::LIABILITY);
77 3
            $account->setName($user->getName());
78
79 3
            $maxCode = $this->getEntityManager()->getConnection()->fetchColumn('SELECT MAX(code) FROM account WHERE parent_id = ' . self::PARENT_ACCOUNT_ID_FOR_USER);
80 3
            $newCode = ++$maxCode;
81 3
            $account->setCode((string) $newCode);
82
83 3
            $parent = $this->getOneById(self::PARENT_ACCOUNT_ID_FOR_USER);
84 3
            if (!$parent) {
85
                throw new \Exception('Cannot find parent account for creation of user account');
86
            }
87 3
            $account->setParent($parent);
88
        }
89
90 4
        return $account;
91
    }
92
93
    /**
94
     * Sum balance by account type
95
     *
96
     * @API\Input(type="AccountType")
97
     *
98
     * @param string $accountType
99
     *
100
     * @return string
101
     */
102 1
    public function totalBalanceByType(string $accountType): string
103
    {
104 1
        $qb = $this->getEntityManager()->getConnection()->createQueryBuilder()
105 1
            ->select('SUM(balance)')
106 1
            ->from($this->getClassMetadata()->getTableName())
107 1
            ->where('type = :type');
108
109 1
        $qb->setParameter('type', $accountType);
110
111 1
        $result = $qb->execute();
112
113 1
        return (string) $result->fetchColumn();
114
    }
115
}
116