Completed
Push — master ( 77b1bb...7f3712 )
by Dmitry
04:57
created

AbstractTariffForm::calculator()   A

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
c 0
b 0
f 0
dl 0
loc 10
ccs 0
cts 8
cp 0
rs 9.4285
cc 2
eloc 5
nc 2
nop 0
crap 6
1
<?php
2
3
namespace hipanel\modules\finance\forms;
4
5
use hipanel\modules\finance\logic\TariffCalculator;
6
use hipanel\modules\finance\models\Tariff;
7
use Yii;
8
use yii\base\InvalidConfigException;
9
use yii\helpers\ArrayHelper;
10
11
abstract class AbstractTariffForm extends \yii\base\Model
12
{
13
    /**
14
     * @var int Tariff ID
15
     */
16
    public $id;
17
18
    /**
19
     * @var string Tariff name
20
     */
21
    public $name;
22
23
    /**
24
     * @var int Parent tariff ID
25
     */
26
    public $parent_id;
27
28
    /**
29
     * @var Tariff[] array of available base tariffs
30
     */
31
    public $baseTariffs;
32
33
    /**
34
     * @var Tariff the selected base tariff
35
     */
36
    public $baseTariff;
37
38
    /**
39
     * @var Tariff
40
     */
41
    protected $tariff;
42
43
    /**
44
     * @var \hipanel\modules\finance\models\Resource[]
45
     */
46
    protected $_resources;
47
48
    /**
49
     * @inheritdoc
50
     */
51
    public function init()
52
    {
53
        if (!isset($this->baseTariffs)) {
54
            throw new InvalidConfigException('Property "baseTariffs" must be filled');
55
        }
56
57
        $this->initTariff();
58
    }
59
60
    /**
61
     * Initializes tariff
62
     * @void
63
     */
64
    protected function initTariff()
65
    {
66
        $this->selectBaseTariff();
67
        $this->ensureTariff();
68
        $this->ensureScenario();
69
    }
70
71
    /**
72
     * Ensures that [[tariff]] is set.
73
     * Otherwise calls [[setDefaultTariff()]]
74
     * @return bool
75
     */
76
    protected function ensureTariff()
77
    {
78
        if ($this->getTariff() instanceof Tariff) {
79
            return true;
80
        }
81
82
        return $this->setDefaultTariff();
83
    }
84
85
    protected function ensureScenario()
86
    {
87
        foreach ($this->tariff->resources as $resource) {
88
            $resource->scenario = $this->scenario;
89
        }
90
    }
91
92
    /**
93
     * Sets default tariff
94
     *
95
     * @return bool
96
     */
97
    protected function setDefaultTariff()
98
    {
99
        $this->setTariff($this->baseTariff);
100
101
        // Default tariff's id and name are useless on create
102
        $this->id = null;
103
        $this->name = null;
104
105
        return true;
106
    }
107
108
    /** @inheritdoc */
109
    public function rules()
110
    {
111
        return [
112
            [['name'], 'required', 'on' => ['create', 'update']],
113
            [['parent_id', 'id'], 'integer', 'on' => ['create', 'update']],
114
            [['parent_id'], 'required', 'on' => ['create']],
115
            [['id'], 'required', 'on' => ['update']],
116
        ];
117
    }
118
119
    /** @inheritdoc */
120
    public function fields()
121
    {
122
        return ArrayHelper::merge(array_combine($this->attributes(), $this->attributes()), [
123
            'resources' => '_resources'
124
        ]);
125
    }
126
127
    /** @inheritdoc */
128
    public function attributes()
129
    {
130
        return [
131
            'id',
132
            'parent_id',
133
            'name',
134
        ];
135
    }
136
137
    /**
138
     * @return \hipanel\modules\finance\models\Resource[]
139
     */
140
    public function getResources()
141
    {
142
        return $this->_resources;
143
    }
144
145
    /**
146
     * @param \hipanel\modules\finance\models\Resource[] $resources
147
     * @throws InvalidConfigException when not implemented
148
     */
149
    public function setResources($resources)
150
    {
151
        throw new InvalidConfigException('Method "setResources" must be implemented');
152
    }
153
154
    /**
155
     * @return array
156
     */
157
    public function getResourceTypes()
158
    {
159
        return reset($this->baseTariff->resources)->getTypes();
160
    }
161
162
    /**
163
     * @return array
164
     */
165
    public function attributeLabels()
166
    {
167
        return [
168
            'parent_id' => Yii::t('hipanel/finance/tariff', 'Parent tariff'),
169
            'name' => Yii::t('hipanel/finance/tariff', 'Name'),
170
            'label' => Yii::t('hipanel/finance/tariff', 'Label'),
171
            'note' => Yii::t('hipanel', 'Note'),
172
        ];
173
    }
174
175
    /**
176
     * @param array $data to be loaded
177
     * @param null $formName
178
     * @return bool
179
     * @throws InvalidConfigException when not implemented
180
     */
181
    public function load($data, $formName = null)
182
    {
183
        throw new InvalidConfigException("Method load must be implemented");
184
    }
185
186
    /**
187
     * Selects one of [[baseTariffs]] and puts it to [[baseTariff]]
188
     *
189
     * @return bool
190
     */
191
    public function selectBaseTariff()
192
    {
193
        if (!isset($this->parent_id)) {
194
            if (isset($this->tariff)) {
195
                $this->parent_id = $this->tariff->parent_id;
0 ignored issues
show
Documentation introduced by
The property parent_id does not exist on object<hipanel\modules\finance\models\Tariff>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
196
            } else {
197
                $this->parent_id = ArrayHelper::getValue(reset($this->baseTariffs), 'id');
0 ignored issues
show
Security Bug introduced by
It seems like reset($this->baseTariffs) targeting reset() can also be of type false; however, yii\helpers\BaseArrayHelper::getValue() does only seem to accept array|object, did you maybe forget to handle an error condition?
Loading history...
198
            }
199
        }
200
201
        $filtered = array_filter($this->baseTariffs, function ($model) {
202
            return $model->id == $this->parent_id;
203
        });
204
205
        if (count($filtered) !== 1) {
206
            Yii::error('Found ' . count($filtered) . ' base tariffs. Must be exactly one');
207
            return false;
208
        }
209
210
        $this->baseTariff = reset($filtered);
211
        $this->parent_id = $this->baseTariff->id;
212
213
        return true;
214
    }
215
216
    /**
217
     * Builds key-value array of [[baseTariffs]]
218
     *  - key: tariff id
219
     *  - value: tariff name
220
     *
221
     * @return array
222
     */
223
    public function getBaseTariffsList()
224
    {
225
        return array_combine(
226
            ArrayHelper::getColumn($this->baseTariffs, 'id'),
227
            ArrayHelper::getColumn($this->baseTariffs, 'name')
228
        );
229
    }
230
231
    public function insert($runValidation = true)
0 ignored issues
show
Unused Code introduced by
The parameter $runValidation is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
232
    {
233
        throw new InvalidConfigException("Method insert must be implemented");
234
    }
235
236
    public function update($runValidation = true)
0 ignored issues
show
Unused Code introduced by
The parameter $runValidation is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
237
    {
238
        throw new InvalidConfigException("Method update must be implemented");
239
    }
240
241
    /**
242
     * @return Tariff
243
     */
244
    public function getTariff()
245
    {
246
        return $this->tariff;
247
    }
248
249
    /**
250
     * Sets [[tariff]]
251
     *
252
     * @param Tariff $tariff
253
     * @return bool
254
     */
255
    public function setTariff($tariff)
256
    {
257
        if ($tariff === null) {
258
            return false;
259
        }
260
261
        $this->tariff = $tariff;
262
263
        $this->id = $tariff->id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<hipanel\modules\finance\models\Tariff>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
264
        $this->name = $tariff->name;
0 ignored issues
show
Documentation introduced by
The property name does not exist on object<hipanel\modules\finance\models\Tariff>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
265
266
        return true;
267
    }
268
269
    public function getPrimaryKey()
270
    {
271
        return ['id'];
272
    }
273
274
    /**
275
     * @var TariffCalculator
276
     */
277
    protected $_calculator;
278
279
    /**
280
     * Creates [[TariffCalculator]] object for the [[tariff]]
281
     *
282
     * @return TariffCalculator
283
     */
284
    protected function calculator()
285
    {
286
        if (isset($this->_calculator)) {
287
            return $this->_calculator;
288
        }
289
290
        $this->_calculator = new TariffCalculator($this->tariff);
291
292
        return $this->_calculator;
293
    }
294
295
    /**
296
     * @return \hipanel\modules\finance\models\Value
297
     */
298
    public function calculation()
299
    {
300
        return $this->calculator()->getCalculation($this->tariff->id)->forCurrency($this->tariff->currency);
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<hipanel\modules\finance\models\Tariff>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property currency does not exist on object<hipanel\modules\finance\models\Tariff>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
301
    }
302
303
    /**
304
     * @var TariffCalculator
305
     */
306
    protected $_baseCalculator;
307
308
    /**
309
     * Creates [[TariffCalculator]] object for the [[baseTariff]]
310
     *
311
     * @return TariffCalculator
312
     */
313
    protected function baseCalculator()
314
    {
315
        if (isset($this->_baseCalculator)) {
316
            return $this->_baseCalculator;
317
        }
318
319
        $this->_baseCalculator = new TariffCalculator($this->baseTariff);
320
321
        return $this->_baseCalculator;
322
    }
323
324
    /**
325
     * @return \hipanel\modules\finance\models\Value
326
     */
327
    public function baseCalculation()
328
    {
329
        return $this->baseCalculator()->getCalculation($this->baseTariff->id)->forCurrency($this->baseTariff->currency);
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<hipanel\modules\finance\models\Tariff>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property currency does not exist on object<hipanel\modules\finance\models\Tariff>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
330
    }
331
}
332