Completed
Push — master ( 6375fb...517bde )
by Bukashk0zzz
06:43
created

Generator::__construct()   B

Complexity

Conditions 7
Paths 14

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 8.6506
c 0
b 0
f 0
cc 7
nc 14
nop 1
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\Delivery;
17
use Bukashk0zzz\YmlGenerator\Model\Offer\OfferCondition;
18
use Bukashk0zzz\YmlGenerator\Model\Offer\OfferGroupAwareInterface;
19
use Bukashk0zzz\YmlGenerator\Model\Offer\OfferInterface;
20
use Bukashk0zzz\YmlGenerator\Model\Offer\OfferParam;
21
use Bukashk0zzz\YmlGenerator\Model\ShopInfo;
22
23
/**
24
 * Class Generator
25
 */
26
class Generator
27
{
28
    /**
29
     * @var string
30
     */
31
    private $tmpFile;
32
33
    /**
34
     * @var \XMLWriter
35
     */
36
    private $writer;
37
38
    /**
39
     * @var Settings
40
     */
41
    private $settings;
42
43
    /**
44
     * Generator constructor.
45
     *
46
     * @param Settings $settings
47
     */
48
    public function __construct($settings = null)
49
    {
50
        $this->settings = $settings instanceof Settings ? $settings : new Settings();
51
        $this->writer = new \XMLWriter();
52
53
        if ($this->settings->getOutputFile() !== null && $this->settings->getReturnResultYMLString()) {
54
            throw new \LogicException('Only one destination need to be used ReturnResultYMLString or OutputFile');
55
        }
56
57
        if ($this->settings->getReturnResultYMLString()) {
58
            $this->writer->openMemory();
59
        } else {
60
            $this->tmpFile = $this->settings->getOutputFile() !== null ? \tempnam(\sys_get_temp_dir(), 'YMLGenerator') : 'php://output';
61
            $this->writer->openURI($this->tmpFile);
62
        }
63
64
        if ($this->settings->getIndentString()) {
65
            $this->writer->setIndentString($this->settings->getIndentString());
66
            $this->writer->setIndent(true);
67
        }
68
    }
69
70
    /**
71
     * @param ShopInfo $shopInfo
72
     * @param array    $currencies
73
     * @param array    $categories
74
     * @param array    $offers
75
     * @param array    $deliveries
76
     *
77
     * @return bool
78
     */
79
    public function generate(ShopInfo $shopInfo, array $currencies, array $categories, array $offers, array $deliveries = [])
80
    {
81
        try {
82
            $this->addHeader();
83
84
            $this->addShopInfo($shopInfo);
85
            $this->addCurrencies($currencies);
86
            $this->addCategories($categories);
87
88
            if (\count($deliveries) !== 0) {
89
                $this->addDeliveries($deliveries);
90
            }
91
92
            $this->addOffers($offers);
93
            $this->addFooter();
94
95
            if ($this->settings->getReturnResultYMLString()) {
96
                return $this->writer->flush();
97
            }
98
99
            if (null !== $this->settings->getOutputFile()) {
100
                \copy($this->tmpFile, $this->settings->getOutputFile());
101
                @\unlink($this->tmpFile);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
102
            }
103
104
            return true;
105
        } catch (\Exception $exception) {
106
            throw new \RuntimeException(\sprintf('Problem with generating YML file: %s', $exception->getMessage()), 0, $exception);
107
        }
108
    }
109
110
    /**
111
     * Add document header
112
     */
113
    protected function addHeader()
114
    {
115
        $this->writer->startDocument('1.0', $this->settings->getEncoding());
116
        $this->writer->startDTD('yml_catalog', null, 'shops.dtd');
117
        $this->writer->endDTD();
118
        $this->writer->startElement('yml_catalog');
119
        $this->writer->writeAttribute('date', \date('Y-m-d H:i'));
120
        $this->writer->startElement('shop');
121
    }
122
123
    /**
124
     * Add document footer
125
     */
126
    protected function addFooter()
127
    {
128
        $this->writer->fullEndElement();
129
        $this->writer->fullEndElement();
130
        $this->writer->endDocument();
131
    }
132
133
    /**
134
     * Adds shop element data. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#shop)
135
     *
136
     * @param ShopInfo $shopInfo
137
     */
138
    protected function addShopInfo(ShopInfo $shopInfo)
139
    {
140
        foreach ($shopInfo->toArray() as $name => $value) {
141
            if ($value !== null) {
142
                $this->writer->writeElement($name, $value);
143
            }
144
        }
145
    }
146
147
    /**
148
     * @param Currency $currency
149
     */
150
    protected function addCurrency(Currency $currency)
151
    {
152
        $this->writer->startElement('currency');
153
        $this->writer->writeAttribute('id', $currency->getId());
154
        $this->writer->writeAttribute('rate', $currency->getRate());
155
        $this->writer->endElement();
156
    }
157
158
    /**
159
     * @param Category $category
160
     */
161 View Code Duplication
    protected function addCategory(Category $category)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
162
    {
163
        $this->writer->startElement('category');
164
        $this->writer->writeAttribute('id', $category->getId());
165
166
        if ($category->getParentId() !== null) {
167
            $this->writer->writeAttribute('parentId', $category->getParentId());
168
        }
169
170
        $this->writer->text($category->getName());
171
        $this->writer->fullEndElement();
172
    }
173
174
    /**
175
     * @param Delivery $delivery
176
     */
177 View Code Duplication
    protected function addDelivery(Delivery $delivery)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
178
    {
179
        $this->writer->startElement('option');
180
        $this->writer->writeAttribute('cost', $delivery->getCost());
181
        $this->writer->writeAttribute('days', $delivery->getDays());
182
        if ($delivery->getOrderBefore() !== null) {
183
            $this->writer->writeAttribute('order-before', $delivery->getOrderBefore());
184
        }
185
        $this->writer->endElement();
186
    }
187
188
    /**
189
     * @param OfferInterface $offer
190
     */
191
    protected function addOffer(OfferInterface $offer)
192
    {
193
        $this->writer->startElement('offer');
194
        $this->writer->writeAttribute('id', $offer->getId());
195
        $this->writer->writeAttribute('available', $offer->isAvailable() ? 'true' : 'false');
196
197
        if ($offer->getType() !== null) {
198
            $this->writer->writeAttribute('type', $offer->getType());
199
        }
200
201
        if ($offer instanceof OfferGroupAwareInterface && $offer->getGroupId() !== null) {
202
            $this->writer->writeAttribute('group_id', $offer->getGroupId());
203
        }
204
205
        foreach ($offer->toArray() as $name => $value) {
206
            if (\is_array($value)) {
207
                foreach ($value as $itemValue) {
208
                    $this->addOfferElement($name, $itemValue);
209
                }
210
            } else {
211
                $this->addOfferElement($name, $value);
212
            }
213
        }
214
        $this->addOfferParams($offer);
215
        $this->addOfferDeliveryOptions($offer);
216
        $this->addOfferCondition($offer);
217
218
        $this->writer->fullEndElement();
219
    }
220
221
    /**
222
     * Adds <currencies> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#currencies)
223
     *
224
     * @param array $currencies
225
     */
226
    private function addCurrencies(array $currencies)
227
    {
228
        $this->writer->startElement('currencies');
229
230
        /** @var Currency $currency */
231
        foreach ($currencies as $currency) {
232
            if ($currency instanceof Currency) {
233
                $this->addCurrency($currency);
234
            }
235
        }
236
237
        $this->writer->fullEndElement();
238
    }
239
240
    /**
241
     * Adds <categories> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#categories)
242
     *
243
     * @param array $categories
244
     */
245
    private function addCategories(array $categories)
246
    {
247
        $this->writer->startElement('categories');
248
249
        /** @var Category $category */
250
        foreach ($categories as $category) {
251
            if ($category instanceof Category) {
252
                $this->addCategory($category);
253
            }
254
        }
255
256
        $this->writer->fullEndElement();
257
    }
258
259
    /**
260
     * Adds <delivery-option> element. (See https://yandex.ru/support/partnermarket/elements/delivery-options.xml)
261
     *
262
     * @param array $deliveries
263
     */
264
    private function addDeliveries(array $deliveries)
265
    {
266
        $this->writer->startElement('delivery-options');
267
268
        /** @var Delivery $delivery */
269
        foreach ($deliveries as $delivery) {
270
            if ($delivery instanceof Delivery) {
271
                $this->addDelivery($delivery);
272
            }
273
        }
274
275
        $this->writer->fullEndElement();
276
    }
277
278
    /**
279
     * Adds <offers> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#offers)
280
     *
281
     * @param array $offers
282
     */
283
    private function addOffers(array $offers)
284
    {
285
        $this->writer->startElement('offers');
286
287
        /** @var OfferInterface $offer */
288
        foreach ($offers as $offer) {
289
            if ($offer instanceof OfferInterface) {
290
                $this->addOffer($offer);
291
            }
292
        }
293
294
        $this->writer->fullEndElement();
295
    }
296
297
    /**
298
     * @param OfferInterface $offer
299
     */
300
    private function addOfferDeliveryOptions(OfferInterface $offer)
301
    {
302
        $options = $offer->getDeliveryOptions();
303
        if (!empty($options)) {
304
            $this->addDeliveries($options);
305
        }
306
    }
307
308
    /**
309
     * @param OfferInterface $offer
310
     */
311
    private function addOfferParams(OfferInterface $offer)
312
    {
313
        /** @var OfferParam $param */
314
        foreach ($offer->getParams() as $param) {
315
            if ($param instanceof OfferParam) {
316
                $this->writer->startElement('param');
317
318
                $this->writer->writeAttribute('name', $param->getName());
319
                if ($param->getUnit()) {
320
                    $this->writer->writeAttribute('unit', $param->getUnit());
321
                }
322
                $this->writer->text($param->getValue());
323
324
                $this->writer->endElement();
325
            }
326
        }
327
    }
328
329
    /**
330
     * @param OfferInterface $offer
331
     */
332
    private function addOfferCondition(OfferInterface $offer)
333
    {
334
        $params = $offer->getCondition();
335
        if ($params instanceof OfferCondition) {
336
            $this->writer->startElement('condition');
337
            $this->writer->writeAttribute('type', $params->getType());
338
            $this->writer->writeElement('reason', $params->getReasonText());
339
            $this->writer->endElement();
340
        }
341
    }
342
343
    /**
344
     * @param string $name
345
     * @param mixed  $value
346
     *
347
     * @return bool
348
     */
349
    private function addOfferElement($name, $value)
350
    {
351
        if ($value === null) {
352
            return false;
353
        }
354
355
        if ($value instanceof Cdata) {
356
            $this->writer->startElement($name);
357
            $this->writer->writeCdata((string) $value);
358
            $this->writer->endElement();
359
360
            return true;
361
        }
362
363
        if (\is_bool($value)) {
364
            $value = $value ? 'true' : 'false';
365
        }
366
        $this->writer->writeElement($name, $value);
367
368
        return true;
369
    }
370
}
371