Completed
Pull Request — master (#6)
by
unknown
33:10 queued 15:36
created

YmlCatalog::writeModel()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 26
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 5.0035

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 26
ccs 18
cts 19
cp 0.9474
rs 8.439
cc 5
eloc 15
nc 16
nop 2
crap 5.0035
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
     * @param BaseFileStream $handle
52
     * @param string $shopClass class name
53
     * @param string $currencyClass class name
54
     * @param string $categoryClass class name
55
     * @param string $localDeliveryCostClass class name
56
     * @param array $offerClasses
57
     * @param null|string $date
58
     */
59 6
    public function __construct(
60
        BaseFileStream $handle,
61
        $shopClass,
62
        $currencyClass,
63
        $categoryClass,
64
        $localDeliveryCostClass,
65
        Array $offerClasses,
66 1
        $date = null
67
    ) {
68 6
        $this->handle = $handle;
69 6
        $this->shopClass = $shopClass;
70 6
        $this->currencyClass = $currencyClass;
71 6
        $this->categoryClass = $categoryClass;
72 6
        $this->localDeliveryCostClass = $localDeliveryCostClass;
73 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...
74 6
        $this->date = $date;
75 4
    }
76
77
    /**
78
     * @throws Exception
79
     */
80 6
    public function generate()
81
    {
82 4
        $date = $this->getDate();
83
84 6
        $this->write(
85 4
            '<?xml version="1.0" encoding="utf-8"?>' . PHP_EOL .
86 4
            '<!DOCTYPE yml_catalog SYSTEM "shops.dtd">' . PHP_EOL .
87 4
            '<yml_catalog date="' . $date . '">' . PHP_EOL
88 2
        );
89
90 4
        $this->writeTag('shop');
91 4
        $this->writeModel(new Shop(), new $this->shopClass());
92 4
        $this->writeTag('currencies');
93 4
        $this->writeEachModel($this->currencyClass);
94 4
        $this->writeTag('/currencies');
95 4
        $this->writeTag('categories');
96 4
        $this->writeEachModel($this->categoryClass);
97 4
        $this->writeTag('/categories');
98 4
        $this->writeModel(new LocalDeliveryCost(), new $this->localDeliveryCostClass());
99 4
        $this->writeTag('offers');
100 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...
101 4
            $this->writeEachModel($offerClass);
102 2
        }
103 4
        $this->writeTag('/offers');
104 4
        $this->writeTag('/shop');
105
106 4
        $this->write('</yml_catalog>');
107 6
    }
108
109
    /**
110
     * @return null|string
111
     */
112 6
    protected function getDate()
113
    {
114 6
        $date = $this->date;
115
116 6
        if ($date === null) {
117 2
            $date = Yii::$app->formatter->asDatetime(new \DateTime(), 'php:Y-m-d H:i');
118 1
        }
119
120 6
        return $date;
121
    }
122
123
    /**
124
     * @param string $string
125
     * @throws \Exception
126
     */
127 4
    protected function write($string)
128
    {
129 4
        $this->handle->write($string);
130 4
    }
131
132
    /**
133
     * @param string $string tag name
134
     */
135 4
    protected function writeTag($string)
136
    {
137 4
        $this->write('<' . $string . '>' . PHP_EOL);
138 4
    }
139
140
    /**
141
     * @param BaseModel $model model
142
     * @param $valuesModel
143
     * @throws Exception
144
     */
145 4
    protected function writeModel(BaseModel $model, $valuesModel)
146
    {
147 4
        $attributes = [];
148 4
        foreach ($model->attributes() as $attribute) {
149 4
            $methodName = 'get' . ucfirst($attribute);
150 4
            $attributeValue = $valuesModel->$methodName();
151
152 4
            $attributes[$attribute] = $attributeValue;
153 2
        }
154
155 4
        $model->load($attributes, '');
156 4
        if (method_exists($valuesModel, 'getParams')) {
157 4
            $model->setParams($valuesModel->getParams());
158 2
        }
159 4
        if (method_exists($valuesModel, 'getPictures')) {
160 4
            $model->setPictures($valuesModel->getPictures());
161 2
        }
162
163 4
        if (!$model->validate()) {
164
            throw new Exception('Model values is invalid ' . serialize($model->getErrors()));
165
        }
166
167 4
        $string = $model->getYml();
168
169 4
        $this->write($string);
170 4
    }
171
172
    /**
173
     * @param string $modelClass class name
174
     */
175 4
    protected function writeEachModel($modelClass)
176
    {
177 4
        $newModel = $this->getNewModel($modelClass);
178
179
        /* @var \yii\db\ActiveQuery $query */
180 4
        $query = $modelClass::findYml();
181
182 4
        foreach ($query->batch(100) as $models) {
183 4
            foreach ($models as $model) {
184 4
                $this->writeModel($newModel, $model);
185 2
            }
186 2
        }
187 4
    }
188
189
    /**
190
     * @param $modelClass
191
     * @return Category|Currency|SimpleOffer
192
     * @throws Exception
193
     */
194 6
    protected function getNewModel($modelClass)
195
    {
196 4
        $obj = new $modelClass();
197
198 4
        if ($obj instanceof CurrencyInterface) {
199 4
            $model = new Currency();
200 2
        } elseif ($obj instanceof CategoryInterface) {
201 4
            $model = new Category();
202 4
        } elseif ($obj instanceof SimpleOfferInterface) {
203 4
            $model = new SimpleOffer();
204 2
        } else {
205
            throw new Exception('Model ' . $modelClass. ' has unknown interface');
206
        }
207
208 4
        return $model;
209
    }
210
}
211