Generator::addFooter()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

102
                /** @scrutinizer ignore-unhandled */ @\unlink($this->tmpFile);

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...
103
            }
104
105
            return true;
106
        } catch (\Exception $exception) {
107
            throw new \RuntimeException(\sprintf('Problem with generating YML file: %s', $exception->getMessage()), 0, $exception);
108
        }
109
    }
110
111
    /**
112
     * Add document header
113
     */
114
    protected function addHeader()
115
    {
116
        $this->writer->startDocument('1.0', $this->settings->getEncoding());
117
        $this->writer->startDTD('yml_catalog', null, 'shops.dtd');
118
        $this->writer->endDTD();
119
        $this->writer->startElement('yml_catalog');
120
        $this->writer->writeAttribute('date', \date(\DATE_RFC3339));
121
        $this->writer->startElement('shop');
122
    }
123
124
    /**
125
     * Add document footer
126
     */
127
    protected function addFooter()
128
    {
129
        $this->writer->fullEndElement();
130
        $this->writer->fullEndElement();
131
        $this->writer->endDocument();
132
    }
133
134
    /**
135
     * Adds shop element data. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#shop)
136
     *
137
     * @param ShopInfo $shopInfo
138
     */
139
    protected function addShopInfo(ShopInfo $shopInfo)
140
    {
141
        foreach ($shopInfo->toArray() as $name => $value) {
142
            if ($value !== null) {
143
                $this->writer->writeElement($name, $value);
144
            }
145
        }
146
    }
147
148
    /**
149
     * @param Currency $currency
150
     */
151
    protected function addCurrency(Currency $currency)
152
    {
153
        $this->writer->startElement('currency');
154
        $this->writer->writeAttribute('id', $currency->getId());
155
        $this->writer->writeAttribute('rate', $currency->getRate());
156
        $this->writer->endElement();
157
    }
158
159
    /**
160
     * @param Category $category
161
     */
162
    protected function addCategory(Category $category)
163
    {
164
        $this->writer->startElement('category');
165
        $this->writer->writeAttribute('id', $category->getId());
166
167
        if ($category->getParentId() !== null) {
0 ignored issues
show
introduced by
The condition $category->getParentId() !== null is always true.
Loading history...
168
            $this->writer->writeAttribute('parentId', $category->getParentId());
169
        }
170
171
        if (!empty($category->getAttributes())) {
172
            foreach ($category->getAttributes() as $attribute) {
173
                $this->writer->writeAttribute($attribute['name'], $attribute['value']);
174
            }
175
        }
176
177
        $this->writer->text($category->getName());
178
        $this->writer->fullEndElement();
179
    }
180
181
    /**
182
     * @param Delivery $delivery
183
     */
184
    protected function addDelivery(Delivery $delivery)
185
    {
186
        $this->writer->startElement('option');
187
        $this->writer->writeAttribute('cost', $delivery->getCost());
188
        $this->writer->writeAttribute('days', $delivery->getDays());
189
        if ($delivery->getOrderBefore() !== null) {
0 ignored issues
show
introduced by
The condition $delivery->getOrderBefore() !== null is always true.
Loading history...
190
            $this->writer->writeAttribute('order-before', $delivery->getOrderBefore());
191
        }
192
        $this->writer->endElement();
193
    }
194
195
    /**
196
     * @param OfferInterface $offer
197
     */
198
    protected function addOffer(OfferInterface $offer)
199
    {
200
        $this->writer->startElement('offer');
201
        $this->writer->writeAttribute('id', $offer->getId());
202
        $this->writer->writeAttribute('available', $offer->isAvailable() ? 'true' : 'false');
203
204
        if ($offer->getType() !== null) {
0 ignored issues
show
introduced by
The condition $offer->getType() !== null is always true.
Loading history...
205
            $this->writer->writeAttribute('type', $offer->getType());
206
        }
207
208
        if ($offer instanceof OfferGroupAwareInterface && $offer->getGroupId() !== null) {
209
            $this->writer->writeAttribute('group_id', $offer->getGroupId());
210
        }
211
212
        foreach ($offer->toArray() as $name => $value) {
213
            if (\is_array($value)) {
214
                foreach ($value as $itemValue) {
215
                    $this->addOfferElement($name, $itemValue);
216
                }
217
            } else {
218
                $this->addOfferElement($name, $value);
219
            }
220
        }
221
        $this->addOfferOutlets($offer);
222
        $this->addOfferParams($offer);
223
        $this->addOfferDeliveryOptions($offer);
224
        $this->addOfferCondition($offer);
225
226
        $this->writer->fullEndElement();
227
    }
228
229
    /**
230
     * Adds <currencies> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#currencies)
231
     *
232
     * @param array $currencies
233
     */
234
    private function addCurrencies(array $currencies)
235
    {
236
        $this->writer->startElement('currencies');
237
238
        /** @var Currency $currency */
239
        foreach ($currencies as $currency) {
240
            if ($currency instanceof Currency) {
241
                $this->addCurrency($currency);
242
            }
243
        }
244
245
        $this->writer->fullEndElement();
246
    }
247
248
    /**
249
     * Adds <categories> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#categories)
250
     *
251
     * @param array $categories
252
     */
253
    private function addCategories(array $categories)
254
    {
255
        $this->writer->startElement('categories');
256
257
        /** @var Category $category */
258
        foreach ($categories as $category) {
259
            if ($category instanceof Category) {
260
                $this->addCategory($category);
261
            }
262
        }
263
264
        $this->writer->fullEndElement();
265
    }
266
267
    /**
268
     * Adds <delivery-option> element. (See https://yandex.ru/support/partnermarket/elements/delivery-options.xml)
269
     *
270
     * @param array $deliveries
271
     */
272
    private function addDeliveries(array $deliveries)
273
    {
274
        $this->writer->startElement('delivery-options');
275
276
        /** @var Delivery $delivery */
277
        foreach ($deliveries as $delivery) {
278
            if ($delivery instanceof Delivery) {
279
                $this->addDelivery($delivery);
280
            }
281
        }
282
283
        $this->writer->fullEndElement();
284
    }
285
286
    /**
287
     * Adds <offers> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#offers)
288
     *
289
     * @param array $offers
290
     */
291
    private function addOffers(array $offers)
292
    {
293
        $this->writer->startElement('offers');
294
295
        /** @var OfferInterface $offer */
296
        foreach ($offers as $offer) {
297
            if ($offer instanceof OfferInterface) {
298
                $this->addOffer($offer);
299
            }
300
        }
301
302
        $this->writer->fullEndElement();
303
    }
304
305
    /**
306
     * @param OfferInterface $offer
307
     */
308
    private function addOfferDeliveryOptions(OfferInterface $offer)
309
    {
310
        $options = $offer->getDeliveryOptions();
311
        if (!empty($options)) {
312
            $this->addDeliveries($options);
313
        }
314
    }
315
316
    /**
317
     * @param OfferInterface $offer
318
     */
319
    private function addOfferParams(OfferInterface $offer)
320
    {
321
        /** @var OfferParam $param */
322
        foreach ($offer->getParams() as $param) {
323
            if ($param instanceof OfferParam) {
324
                $this->writer->startElement('param');
325
326
                $this->writer->writeAttribute('name', $param->getName());
327
                if ($param->getUnit()) {
328
                    $this->writer->writeAttribute('unit', $param->getUnit());
329
                }
330
                $this->writer->text($param->getValue());
331
332
                $this->writer->endElement();
333
            }
334
        }
335
    }
336
337
    /**
338
     * @param OfferInterface $offer
339
     */
340
    private function addOfferOutlets(OfferInterface $offer)
341
    {
342
        if ($offer->getOutlets() && \count($offer->getOutlets())) {
343
            $this->writer->startElement('outlets');
344
            /** @var OfferOutlet $outlet */
345
            foreach ($offer->getOutlets() as $outlet) {
346
                if ($outlet instanceof OfferOutlet) {
347
                    $this->writer->startElement('outlet');
348
349
                    $this->writer->writeAttribute('id', $outlet->getId());
350
                    $this->writer->writeAttribute('instock', $outlet->getInStock());
351
352
                    $this->writer->endElement();
353
                }
354
            }
355
            $this->writer->fullEndElement();
356
        }
357
    }
358
359
    /**
360
     * @param OfferInterface $offer
361
     */
362
    private function addOfferCondition(OfferInterface $offer)
363
    {
364
        $params = $offer->getCondition();
365
        if ($params instanceof OfferCondition) {
366
            $this->writer->startElement('condition');
367
            $this->writer->writeAttribute('type', $params->getType());
368
            $this->writer->writeElement('reason', $params->getReasonText());
369
            $this->writer->endElement();
370
        }
371
    }
372
373
    /**
374
     * @param string $name
375
     * @param mixed  $value
376
     *
377
     * @return bool
378
     */
379
    private function addOfferElement($name, $value)
380
    {
381
        if ($value === null) {
382
            return false;
383
        }
384
385
        if ($value instanceof Cdata) {
386
            $this->writer->startElement($name);
387
            $this->writer->writeCdata((string) $value);
388
            $this->writer->endElement();
389
390
            return true;
391
        }
392
393
        if (\is_bool($value)) {
394
            $value = $value ? 'true' : 'false';
395
        }
396
        $this->writer->writeElement($name, $value);
397
398
        return true;
399
    }
400
}
401