Completed
Pull Request — master (#8)
by
unknown
03:17
created

YmlCatalog::getNewModel()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4.0119

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 16
ccs 10
cts 11
cp 0.9091
rs 9.2
cc 4
eloc 11
nc 4
nop 1
crap 4.0119
1
<?php
2
namespace pastuhov\ymlcatalog;
3
4
use pastuhov\ymlcatalog\models\BaseModel;
5
use pastuhov\ymlcatalog\models\Category;
6
use pastuhov\ymlcatalog\models\Currency;
7
use pastuhov\ymlcatalog\models\LocalDeliveryCost;
8
use pastuhov\ymlcatalog\models\Shop;
9
use pastuhov\ymlcatalog\models\SimpleOffer;
10
use Yii;
11
use pastuhov\FileStream\BaseFileStream;
12
use yii\base\Exception;
13
14
/**
15
 * Yml генератор каталога.
16
 *
17
 * @package pastuhov\ymlcatalog
18
 */
19
class YmlCatalog
20
{
21
    /**
22
     * @var BaseFileStream
23
     */
24
    protected $handle;
25
    /**
26
     * @var string
27
     */
28
    protected $shopClass;
29
    /**
30
     * @var string
31
     */
32
    protected $currencyClass;
33
    /**
34
     * @var string
35
     */
36
    protected $categoryClass;
37
    /**
38
     * @var string
39
     */
40
    protected $localDeliveryCostClass;
41
    /**
42
     * @var string
43
     */
44
    protected $offerClass;
45
    /**
46
     * @var null|string
47
     */
48
    protected $date;
49
50
    /**
51
     * @var null|callable
52
     */
53
    protected $onValidationError;
54
55
    /**
56
     * @param BaseFileStream $handle
57
     * @param string $shopClass class name
58
     * @param string $currencyClass class name
59
     * @param string $categoryClass class name
60
     * @param string $localDeliveryCostClass class name
61
     * @param array $offerClasses
62
     * @param null|string $date
63
     * @param null|callable $onValidationError
64
     */
65 6
    public function __construct(
66
        BaseFileStream $handle,
67
        $shopClass,
68
        $currencyClass,
69
        $categoryClass,
70
        $localDeliveryCostClass,
71
        Array $offerClasses,
72
        $date = null,
73
        $onValidationError = null
74 2
    ) {
75 6
        $this->handle = $handle;
76 6
        $this->shopClass = $shopClass;
77 6
        $this->currencyClass = $currencyClass;
78 6
        $this->categoryClass = $categoryClass;
79 6
        $this->localDeliveryCostClass = $localDeliveryCostClass;
80 6
        $this->offerClasses = $offerClasses;
0 ignored issues
show
Bug introduced by
The property offerClasses does not seem to exist. Did you mean offerClass?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
81 6
        $this->date = $date;
82 6
        $this->onValidationError = $onValidationError;
83 6
    }
84
85
    /**
86
     * @throws Exception
87
     */
88 6
    public function generate()
89
    {
90 6
        $date = $this->getDate();
91
92 6
        $this->write(
93 6
            '<?xml version="1.0" encoding="utf-8"?>' . PHP_EOL .
94 6
            '<!DOCTYPE yml_catalog SYSTEM "shops.dtd">' . PHP_EOL .
95 6
            '<yml_catalog date="' . $date . '">' . PHP_EOL
96 4
        );
97
98 6
        $this->writeTag('shop');
99 6
        $this->writeModel(new Shop(), new $this->shopClass());
100 6
        $this->writeTag('currencies');
101 6
        $this->writeEachModel($this->currencyClass);
102 6
        $this->writeTag('/currencies');
103 6
        $this->writeTag('categories');
104 6
        $this->writeEachModel($this->categoryClass);
105 6
        $this->writeTag('/categories');
106 6
        $this->writeModel(new LocalDeliveryCost(), new $this->localDeliveryCostClass());
107 6
        $this->writeTag('offers');
108 6
        foreach ($this->offerClasses as $offerClass) {
0 ignored issues
show
Bug introduced by
The property offerClasses does not seem to exist. Did you mean offerClass?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
109 6
            $this->writeEachModel($offerClass);
110 4
        }
111 6
        $this->writeTag('/offers');
112 6
        $this->writeTag('/shop');
113
114 6
        $this->write('</yml_catalog>');
115 6
    }
116
117
    /**
118
     * @return null|string
119
     */
120 6
    protected function getDate()
121
    {
122 6
        $date = $this->date;
123
124 6
        if ($date === null) {
125 3
            $date = Yii::$app->formatter->asDatetime(new \DateTime(), 'php:Y-m-d H:i');
126 2
        }
127
128 6
        return $date;
129
    }
130
131
    /**
132
     * @param string $string
133
     * @throws \Exception
134
     */
135 6
    protected function write($string)
136
    {
137 6
        $this->handle->write($string);
138 6
    }
139
140
    /**
141
     * @param string $string tag name
142
     */
143 6
    protected function writeTag($string)
144 4
    {
145 6
        $this->write('<' . $string . '>' . PHP_EOL);
146 6
    }
147
148
    /**
149
     * @param BaseModel $model model
150
     * @param $valuesModel
151
     * @throws Exception
152
     */
153 6
    protected function writeModel(BaseModel $model, $valuesModel)
154
    {
155 6
        $attributes = [];
156 6
        foreach ($model->attributes() as $attribute) {
157 6
            $methodName = 'get' . ucfirst($attribute);
158 6
            $attributeValue = $valuesModel->$methodName();
159
160 6
            $attributes[$attribute] = $attributeValue;
161 4
        }
162
163 6
        $model->load($attributes, '');
164 6
        if (method_exists($valuesModel, 'getParams')) {
165 6
            $model->setParams($valuesModel->getParams());
166 4
        }
167 6
        if (method_exists($valuesModel, 'getPictures')) {
168 6
            $model->setPictures($valuesModel->getPictures());
169 4
        }
170
171 6
        if (!$model->validate()) {
172 6
            if (is_callable($onValidationError = $this->onValidationError)) {
173 6
                $onValidationError($model);
174 4
            } else {
175
                throw new Exception('Model values is invalid ' . serialize($model->getErrors()));
176
            }
177 4
        }
178
179 6
        $string = $model->getYml();
180
181 6
        $this->write($string);
182 6
    }
183
184
    /**
185
     * @param string $modelClass class name
186
     */
187 6
    protected function writeEachModel($modelClass)
188
    {
189 6
        $newModel = $this->getNewModel($modelClass);
190
191
        /* @var \yii\db\ActiveQuery $query */
192 6
        $query = $modelClass::findYml();
193
194 6
        foreach ($query->batch(100) as $models) {
195 6
            foreach ($models as $model) {
196 6
                $this->writeModel($newModel, $model);
197 4
            }
198 4
        }
199 6
    }
200
201
    /**
202
     * @param $modelClass
203
     * @return Category|Currency|SimpleOffer
204
     * @throws Exception
205
     */
206 6
    protected function getNewModel($modelClass)
207
    {
208 6
        $obj = new $modelClass();
209
210 6
        if ($obj instanceof CurrencyInterface) {
211 6
            $model = new Currency();
212 4
        } elseif ($obj instanceof CategoryInterface) {
213 6
            $model = new Category();
214 4
        } elseif ($obj instanceof SimpleOfferInterface) {
215 6
            $model = new SimpleOffer();
216 4
        } else {
217
            throw new Exception('Model ' . $modelClass. ' has unknown interface');
218
        }
219
220 6
        return $model;
221
    }
222
}
223