Completed
Push — master ( e2a6f1...5a40d9 )
by Andrii
02:40
created

Factory::find()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
nc 3
nop 2
dl 0
loc 9
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * PHP Billing Library
4
 *
5
 * @link      https://github.com/hiqdev/php-billing
6
 * @package   php-billing
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2017-2018, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\php\billing\tools;
12
13
use Money\Money;
14
use Money\Currency;
15
use hiqdev\php\units\Quantity;
16
use Money\Parser\DecimalMoneyParser;
17
use Money\Currencies\ISOCurrencies;
18
19
/**
20
 * Generalized entity factory.
21
 *
22
 * @author Andrii Vasyliev <[email protected]>
23
 */
24
class Factory
25
{
26
    private $entities = [];
27
28
    private $factories = [];
29
30
    protected $moneyParser;
31
32
    public function __construct(array $factories)
33
    {
34
        $this->factories = $factories;
35
        $this->moneyParser = new DecimalMoneyParser(new ISOCurrencies());
36
    }
37
38
    public function getMoney($data)
39
    {
40
        if (is_array($data)) {
41
            $sum = $data['sum'];
42
            $currency = $data['currency'];
43
        } else {
44
            [$sum, $currency] = explode(' ', $data);
45
        }
46
47
        return $this->moneyParser->parse($sum, $currency);
48
    }
49
50
    public function getCurrency($data)
51
    {
52
        return new Currency($data);
53
    }
54
55
    public function getQuantity($data)
56
    {
57
        [$quantity, $unit] = explode(' ', $data);
58
59
        return Quantity::create($unit, $quantity);
60
    }
61
62
    public function getType($data)
63
    {
64
        return $this->get('type', $data);
65
    }
66
67
    public function getTarget($data)
68
    {
69
        return $this->get('target', $data);
70
    }
71
72
    public function getPlan($data)
73
    {
74
        return $this->get('plan', $data);
75
    }
76
77
    public function getCustomer($data)
78
    {
79
        return $this->get('customer', $data);
80
    }
81
82
    public function get(string $entity, $data)
83
    {
84
        if (is_scalar($data)) {
85
            $data = [$this->getEntityKey($entity) => $data];
86
        }
87
        $keys = $this->extractKeys($entity, $data);
88
89
        $res = $this->find($entity, $keys) ?: $this->create($entity, $data);
90
91
        foreach ($keys as $key) {
92
            $this->entities[$entity][$key] = $res;
93
        }
94
95
        return $res;
96
    }
97
98
    public function find(string $entity, array $keys)
99
    {
100
        foreach ($keys as $key) {
101
            if (!empty($this->entities[$entity][$key])) {
102
                return $this->entities[$entity][$key];
103
            }
104
        }
105
106
        return null;
107
    }
108
109
    public function create(string $entity, $data)
110
    {
111
        if (empty($this->factories[$entity])) {
112
            throw new FactoryNotFoundException($entity);
0 ignored issues
show
Bug introduced by
The type hiqdev\php\billing\tools\FactoryNotFoundException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
113
        }
114
115
        $factory = $this->factories[$entity];
116
117
        return $factory->create($this->createDto($entity, $data));
118
    }
119
120
    public function createDto(string $entity, array $data)
121
    {
122
        $class = $this->getDtoClass($entity);
123
        $dto = new $class();
124
125
        foreach ($data as $key => $value) {
126
            $dto->{$key} = $this->prepareValue($entity, $key, $value);
127
        }
128
129
        return $dto;
130
    }
131
132
    public function getDtoClass(string $entity)
133
    {
134
        return $this->getEntityClass($entity) . 'CreationDto';
135
    }
136
137
    public function prepareValue($entity, $key, $value)
138
    {
139
        $method = $this->getPrepareMethod($entity, $key);
140
141
        return $method ? $this->{$method}($value) : $value;
142
    }
143
144
    private function getPrepareMethod(string $entity, string $key)
145
    {
146
        if ($key === 'seller') {
147
            return 'getCustomer';
148
        }
149
        switch ($key) {
150
            case 'seller':
151
                return 'getCustomer';
152
            case 'plan':
153
                return 'getPlan';
154
            case 'type':
155
                return 'getType';
156
            case 'target':
157
                return 'getTarget';
158
            case 'price':
159
                return 'getMoney';
160
            case 'currency':
161
                return 'getCurrency';
162
            case 'prepaid':
163
                return 'getQuantity';
164
        }
165
166
        return null;
167
    }
168
169
    public function getEntityClass(string $entity)
170
    {
171
        $parts = explode('\\', __NAMESPACE__);
172
        array_pop($parts);
173
        $parts[] = $entity;
174
        $parts[] = ucfirst($entity);
175
176
        return implode('\\', $parts);
177
    }
178
179
    public function extractKeys(string $entity, $data)
180
    {
181
        $id = $data['id'] ?? null;
182
        $key = $this->extractKey($entity, $data);
183
184
        return array_filter(['id' => $id, 'key' => $key]);
185
    }
186
187
    public function extractKey(string $entity, $data)
188
    {
189
        $key = $this->getEntityKey($entity);
190
191
        return $data[$key] ?? null;
192
    }
193
194
    public function getEntityKey(string $entity): string
195
    {
196
        switch ($entity) {
197
            case 'customer':
198
                return 'login';
199
            case 'type':
200
                return 'name';
201
            case 'plan':
202
                return 'name';
203
            case 'price':
204
                return 'id';
205
            case 'target':
206
                return 'id';
207
        }
208
209
        throw new UnknownEntityException($entity);
0 ignored issues
show
Bug introduced by
The type hiqdev\php\billing\tools\UnknownEntityException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
210
    }
211
}
212