BillRepository::findId()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 10
rs 10
c 0
b 0
f 0
ccs 0
cts 6
cp 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
/**
3
 * API for Billing
4
 *
5
 * @link      https://github.com/hiqdev/billing-hiapi
6
 * @package   billing-hiapi
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2017-2018, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\billing\hiapi\bill;
12
13
use hiqdev\php\billing\bill\BillInterface;
14
use hiqdev\php\billing\bill\BillRepositoryInterface;
15
use hiqdev\php\billing\charge\ChargeInterface;
16
use hiqdev\yii\DataMapper\expressions\CallExpression;
17
use hiqdev\yii\DataMapper\expressions\HstoreExpression;
18
use hiqdev\yii\DataMapper\models\relations\Bucket;
19
use yii\db\ArrayExpression;
20
use yii\db\Query;
21
use yii\helpers\ArrayHelper;
22
23
class BillRepository extends \hiqdev\yii\DataMapper\repositories\BaseRepository implements BillRepositoryInterface
24
{
25
    /** {@inheritdoc} */
26
    public $queryClass = BillQuery::class;
27
28
    /**
29
     * @param BillInterface $bill
30
     */
31
    public function save(BillInterface $bill)
32
    {
33
        $hstore = $this->prepareHstore($bill);
34
        $this->db->transaction(function() use ($bill, $hstore) {
35
            $chargeIds = [];
36
            $call = new CallExpression('set_bill', [$hstore]);
37
            $command = (new Query())->select($call);
38
            $bill->setId($command->scalar($this->db));
39
            foreach ($bill->getCharges() as $charge) {
40
                $charge->setBill($bill);
41
                $this->em->save($charge);
42
                $chargeIds[] = $charge->getId();
43
            }
44
            if ($chargeIds) {
45
                $call = new CallExpression('set_bill_charges', [$bill->getId(), new ArrayExpression($chargeIds, 'integer')]);
46
                (new Query())->select($call)->scalar($this->db);
47
            }
48
        });
49
    }
50
51
    public function findId(BillInterface $bill)
52
    {
53
        if ($bill->getId()) {
54
            return $bill->getId();
55
        }
56
57
        $hstore = $this->prepareHstore($bill);
58
        $call = new CallExpression('bill_id', [$hstore]);
59
60
        return (new Query())->select($call)->scalar($this->db);
61
    }
62
63
    /**
64
     * undocumented function
65
     *
66
     * @return HstoreExpression
67
     */
68
    protected function prepareHstore(BillInterface $bill): HstoreExpression
69
    {
70
        return new HstoreExpression([
71
            'id'            => $bill->getId(),
72
            'object_id'     => $bill->getTarget()->getId(),
73
            'tariff_id'     => $bill->getPlan() ? $bill->getPlan()->getId() : null,
74
            'type_id'       => $bill->getType()->getId(),
75
            'type'          => $bill->getType()->getName(),
76
            'buyer_id'      => $bill->getCustomer()->getId(),
77
            'buyer'         => $bill->getCustomer()->getLogin(),
78
            'currency'      => $bill->getSum()->getCurrency()->getCode(),
79
            'sum'           => $bill->getSum()->getAmount(),
80
            'quantity'      => $bill->getQuantity()->getQuantity(),
81
            'unit'          => $bill->getQuantity()->getUnit()->getName(),
82
            'time'          => $bill->getTime()->format('c'),
83
            'label'         => $bill->getComment() ?: null,
84
            'is_finished'   => $bill->isFinished(),
85
        ]);
86
    }
87
88
    public function findByIds(array $ids): array
89
    {
90
        $spec = $this->createSpecification()
91
            ->with('charges')
92
            ->where(['id' => $ids]);
93
94
        return $this->findAll($spec);
95
    }
96
97
    protected function joinCharges(&$rows)
98
    {
99
        $bucket = Bucket::fromRows($rows, 'id');
100
        $spec = $this->createSpecification()->with('parent')->where(['bill-id' => $bucket->getKeys()]);
101
        $charges = $this->getRepository(ChargeInterface::class)->queryAll($spec);
102
        $bucket->fill($charges, 'bill.id', 'id');
103
        $bucket->pour($rows, 'charges');
104
105
        $indexedCharges = ArrayHelper::index($charges, 'id');
106
        foreach ($rows as &$bill) {
107
            foreach ($bill['charges'] as &$charge) {
108
                $charge = $this->enrichChargeWithParents($indexedCharges, $charge);
109
            }
110
        }
111
    }
112
113
    private function enrichChargeWithParents(array $charges, ?array $charge = null): array
114
    {
115
        if (isset($charge['parent-id'], $charges[$charge['parent-id']])) {
116
            $charge['parent'] = $this->enrichChargeWithParents($charges, $charges[$charge['parent-id']]);
117
        }
118
119
        return $charge;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $charge could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
120
    }
121
}
122