Completed
Push — master ( b73efb...175f05 )
by Bukashk0zzz
03:39
created

Generator::addHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
1
<?php
2
3
/*
4
 * This file is part of the Bukashk0zzzYmlGenerator
5
 *
6
 * (c) Denis Golubovskiy <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Bukashk0zzz\YmlGenerator;
13
14
use Bukashk0zzz\YmlGenerator\Model\Category;
15
use Bukashk0zzz\YmlGenerator\Model\Currency;
16
use Bukashk0zzz\YmlGenerator\Model\Offer\OfferInterface;
17
use Bukashk0zzz\YmlGenerator\Model\Offer\OfferParam;
18
use Bukashk0zzz\YmlGenerator\Model\ShopInfo;
19
20
/**
21
 * Class Generator
22
 *
23
 * @author Denis Golubovskiy <[email protected]>
24
 */
25
class Generator
26
{
27
    /**
28
     * @var string
29
     */
30
    private $tmpFile;
31
32
    /**
33
     * @var \XMLWriter
34
     */
35
    private $writer;
36
37
    /**
38
     * @var Settings
39
     */
40
    private $settings;
41
42
    /**
43
     * Generator constructor.
44
     * @param Settings $settings
45
     */
46
    public function __construct($settings = null)
47
    {
48
        $this->settings = $settings instanceof Settings ? $settings: new Settings();
49
        $this->tmpFile = $this->settings->getOutputFile() !== null ? tempnam(sys_get_temp_dir(), 'YMLGenerator') : 'php://output';
50
51
        $this->writer = new \XMLWriter();
52
        $this->writer->openUri($this->tmpFile);
53
54
        if ($this->settings->getIndentString()) {
55
            $this->writer->setIndentString($this->settings->getIndentString());
56
            $this->writer->setIndent(true);
57
        }
58
    }
59
60
    /**
61
     * @param ShopInfo $shopInfo
62
     * @param array    $currencies
63
     * @param array    $categories
64
     * @param array    $offers
65
     *
66
     * @return bool
67
     *
68
     * @throws \RuntimeException
69
     */
70
    public function generate(ShopInfo $shopInfo, array $currencies, array $categories, array $offers)
71
    {
72
        try {
73
            $this->addHeader();
74
75
            $this->addShopInfo($shopInfo);
76
            $this->addCurrencies($currencies);
77
            $this->addCategories($categories);
78
            $this->addOffers($offers);
79
80
            $this->addFooter();
81
82
            if (null !== $this->settings->getOutputFile()) {
83
                rename($this->tmpFile, $this->settings->getOutputFile());
84
            }
85
86
            return true;
87
        } catch (\Exception $exception) {
88
            throw new \RuntimeException('Problem with generating YML file: '.$exception->getMessage(), 0, $exception);
89
        }
90
    }
91
92
    /**
93
     * Add document header
94
     */
95
    protected function addHeader()
96
    {
97
        $this->writer->startDocument('1.0', $this->settings->getEncoding());
98
        $this->writer->startElement('yml_catalog');
99
        $this->writer->writeAttribute('date', date('Y-m-d H:i'));
100
        $this->writer->startElement('shop');
101
    }
102
103
    /**
104
     * Add document footer
105
     */
106
    protected function addFooter()
107
    {
108
        $this->writer->fullEndElement();
109
        $this->writer->fullEndElement();
110
        $this->writer->endDocument();
111
    }
112
113
    /**
114
     * Adds shop element data. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#shop)
115
     * @param ShopInfo $shopInfo
116
     */
117
    protected function addShopInfo(ShopInfo $shopInfo)
118
    {
119
        foreach ($shopInfo->toArray() as $name => $value) {
120
            if ($value !== null) {
121
                $this->writer->writeElement($name, $value);
122
            }
123
        }
124
    }
125
126
    /**
127
     * @param Currency $currency
128
     */
129
    protected function addCurrency(Currency $currency)
130
    {
131
        $this->writer->startElement('currency');
132
        $this->writer->writeAttribute('id', $currency->getId());
133
        $this->writer->writeAttribute('rate', $currency->getRate());
134
        $this->writer->endElement();
135
    }
136
137
    /**
138
     * @param Category $category
139
     */
140
    protected function addCategory(Category $category)
141
    {
142
        $this->writer->startElement('category');
143
        $this->writer->writeAttribute('id', $category->getId());
144
145
        if ($category->getParentId() !== null) {
146
            $this->writer->writeAttribute('parentId', $category->getParentId());
147
        }
148
149
        $this->writer->text($category->getName());
150
        $this->writer->fullEndElement();
151
    }
152
153
    /**
154
     * @param OfferInterface $offer
155
     */
156
    protected function addOffer(OfferInterface $offer)
157
    {
158
        $this->writer->startElement('offer');
159
        $this->writer->writeAttribute('id', $offer->getId());
160
        $this->writer->writeAttribute('available', $offer->isAvailable() ? 'true' : 'false');
161
162
        if ($offer->getType() !== null) {
163
            $this->writer->writeAttribute('type', $offer->getType());
164
        }
165
166
        foreach ($offer->toArray() as $name => $value) {
167
            $this->addOfferElement($name, $value);
168
        }
169
        $this->addOfferParams($offer);
170
171
        $this->writer->fullEndElement();
172
    }
173
174
    /**
175
     * Adds <currencies> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#currencies)
176
     * @param array $currencies
177
     */
178
    private function addCurrencies(array $currencies)
179
    {
180
        $this->writer->startElement('currencies');
181
182
        /** @var Currency $currency */
183
        foreach ($currencies as $currency) {
184
            if ($currency instanceof Currency) {
185
                $this->addCurrency($currency);
186
            }
187
        }
188
189
        $this->writer->fullEndElement();
190
    }
191
192
    /**
193
     * Adds <categories> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#categories)
194
     * @param array $categories
195
     */
196
    private function addCategories(array $categories)
197
    {
198
        $this->writer->startElement('categories');
199
200
        /** @var Category $category */
201
        foreach ($categories as $category) {
202
            if ($category instanceof Category) {
203
                $this->addCategory($category);
204
            }
205
        }
206
207
        $this->writer->fullEndElement();
208
    }
209
210
    /**
211
     * Adds <offers> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#offers)
212
     * @param array $offers
213
     */
214
    private function addOffers(array $offers)
215
    {
216
        $this->writer->startElement('offers');
217
218
        /** @var OfferInterface $offer */
219
        foreach ($offers as $offer) {
220
            if ($offer instanceof OfferInterface) {
221
                $this->addOffer($offer);
222
            }
223
        }
224
225
        $this->writer->fullEndElement();
226
    }
227
228
    /**
229
     * @param OfferInterface $offer
230
     */
231
    private function addOfferParams(OfferInterface $offer)
232
    {
233
        /** @var OfferParam $param */
234
        foreach ($offer->getParams() as $param) {
235
            if ($param instanceof OfferParam) {
236
                $this->writer->startElement('param');
237
238
                $this->writer->writeAttribute('name', $param->getName());
239
                if ($param->getUnit()) {
240
                    $this->writer->writeAttribute('unit', $param->getUnit());
241
                }
242
                $this->writer->text($param->getValue());
243
244
                $this->writer->endElement();
245
            }
246
        }
247
    }
248
249
    /**
250
     * @param string $name
251
     * @param mixed  $value
252
     * @return bool
253
     */
254
    private function addOfferElement($name, $value)
255
    {
256
        if ($value === null) {
257
            return false;
258
        }
259
260
        if (is_array($value)) {
261
            /** @var string $v */
262
            foreach ((array) $value as $v) {
263
                $this->writer->writeElement($name, $v);
264
            }
265
266
            return true;
267
        }
268
269
        if (is_bool($value)) {
270
            $value = $value ? 'true' : 'false';
271
        }
272
        $this->writer->writeElement($name, $value);
273
274
        return true;
275
    }
276
}
277