Completed
Push — master ( 96c4d7...0211a3 )
by Dmitry
11:07
created

BillImportForm::parse()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 28
rs 8.439
cc 5
eloc 17
nc 9
nop 0
1
<?php
2
3
namespace hipanel\modules\finance\forms;
4
5
use hipanel\modules\client\models\Client;
6
use hipanel\modules\finance\models\Bill;
7
use yii\base\InvalidValueException;
8
use yii\helpers\ArrayHelper;
9
10
class BillImportForm extends \yii\base\Model
11
{
12
    protected $_types;
13
14
    public $data;
15
16
    public function attributes()
17
    {
18
        return ['data'];
19
    }
20
21
    public function rules()
22
    {
23
        return [
24
            ['data', 'safe'],
25
        ];
26
    }
27
28
    public function parse()
29
    {
30
        $bills = [];
31
        $billTemplate = new Bill(['scenario' => Bill::SCENARIO_CREATE]);
32
33
        $lines = explode("\n", $this->data);
34
        foreach ($lines as $line) {
35
            $bills[] = $bill = clone $billTemplate;
36
37
            $chunks = explode(';', $line);
38
            if (count($chunks) !== 6) {
39
                throw new InvalidValueException('Line "' . $line . '" is malformed"');
40
            }
41
42
            list($client, $time, $sum, $currency, $type, $label) = array_map('trim', $chunks);
43
            $bill->setAttributes(compact('client', 'time', 'sum', 'currency', 'type', 'label'));
44
        }
45
46
        $this->resolveClients(ArrayHelper::getColumn($bills, 'client'));
47
48
        foreach ($bills as $bill) {
49
            $bill->time = \Yii::$app->formatter->asDatetime($this->resolveTime($bill->time), 'php:d.m.Y H:i:s');
50
            $bill->type = $this->resolveType($bill->type);
51
            $bill->client_id = $this->convertClientToId($bill->client);
52
        }
53
54
        return empty($bills) ? false : $bills;
55
    }
56
57
    protected function resolveTime($time)
58
    {
59
        $timestamp = strtotime($time);
60
61
        if ($timestamp !== false) {
62
            return $timestamp;
63
        }
64
65
        if ($time === 'this' || $time === 'thisMonth') {
66
            return strtotime('first day of this month midnight');
67
        }
68
69
        if ($time === 'prev' || $time === 'prevMonth') {
70
            return strtotime('first day of last month midnight');
71
        }
72
73
        return time();
74
    }
75
76
    protected function resolveType($type)
77
    {
78
        $types = $this->getTypes();
79
80
        // Type is a normal key
81
        if (isset($types[$type])) {
82
            return $type;
83
        }
84
85
        // Type is a title of type instead of its key
86
        if (in_array($type, $types)) {
87
            return array_search($type, $types);
88
        }
89
90
        // Assuming only second part is passed. Match from the end
91
        $foundKey = null;
92
        foreach ($types as $key => $title) {
93
            list(, $name) = explode(',', $key);
94
            if ($name === $type) {
95
                if ($foundKey !== null) {
96
                    throw new InvalidValueException('Payment type "' . $type . '" is ambiguous');
97
                }
98
99
                $foundKey = $key;
100
            }
101
        }
102
103
        if ($foundKey) {
104
            return $foundKey;
105
        }
106
107
        throw new InvalidValueException('Payment type "' . $type . '" is not recognized');
108
    }
109
110
    protected function convertClientToId($client)
111
    {
112
        if (!isset($this->clientsMap[$client])) {
113
            throw new InvalidValueException('Client "' . $client . '" was not found');
114
        }
115
116
        return $this->clientsMap[$client];
117
    }
118
119
    public function setTypes($types)
120
    {
121
        $result = [];
122
123
        foreach ($types as $category) {
124
            foreach ($category as $key => $title) {
125
                $result[$key] = $title;
126
            }
127
        }
128
129
        $this->_types = $result;
130
    }
131
132
    private $clientsMap = [];
133
134
    private function resolveClients($logins)
135
    {
136
        $clients = Client::find()->where(['login' => $logins])->all();
137
        $this->clientsMap = array_combine(ArrayHelper::getColumn($clients, 'login'),
138
            ArrayHelper::getColumn($clients, 'id'));
139
    }
140
141
    public function getTypes()
142
    {
143
        return $this->_types;
144
    }
145
}
146