Completed
Pull Request — master (#8)
by
unknown
02:35
created

YmlCatalog::writeModel()   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6.2163

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 28
ccs 18
cts 22
cp 0.8182
rs 8.439
cc 6
eloc 16
nc 24
nop 2
crap 6.2163
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
            if (is_callable($onValidationError = $this->onValidationError)) {
173
                $onValidationError($model);
174
            }
175
        }
176
177 6
        $string = $model->getYml();
178
179 6
        $this->write($string);
180 6
    }
181
182
    /**
183
     * @param string $modelClass class name
184
     */
185 6
    protected function writeEachModel($modelClass)
186
    {
187 6
        $newModel = $this->getNewModel($modelClass);
188
189
        /* @var \yii\db\ActiveQuery $query */
190 6
        $query = $modelClass::findYml();
191
192 6
        foreach ($query->batch(100) as $models) {
193 6
            foreach ($models as $model) {
194 6
                $this->writeModel($newModel, $model);
195 4
            }
196 4
        }
197 6
    }
198
199
    /**
200
     * @param $modelClass
201
     * @return Category|Currency|SimpleOffer
202
     * @throws Exception
203
     */
204 6
    protected function getNewModel($modelClass)
205
    {
206 6
        $obj = new $modelClass();
207
208 6
        if ($obj instanceof CurrencyInterface) {
209 6
            $model = new Currency();
210 4
        } elseif ($obj instanceof CategoryInterface) {
211 6
            $model = new Category();
212 4
        } elseif ($obj instanceof SimpleOfferInterface) {
213 6
            $model = new SimpleOffer();
214 4
        } else {
215
            throw new Exception('Model ' . $modelClass. ' has unknown interface');
216
        }
217
218 6
        return $model;
219
    }
220
}
221