Completed
Push — master ( abb6bd...6375fb )
by Bukashk0zzz
01:10
created

Generator::addOfferDeliveryOptions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 2
nc 2
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->tmpFile = $this->settings->getOutputFile() !== null ? \tempnam(\sys_get_temp_dir(), 'YMLGenerator') : 'php://output';
52
53
        $this->writer = new \XMLWriter();
54
        $this->writer->openURI($this->tmpFile);
55
56
        if ($this->settings->getIndentString()) {
57
            $this->writer->setIndentString($this->settings->getIndentString());
58
            $this->writer->setIndent(true);
59
        }
60
    }
61
62
    /**
63
     * @param ShopInfo $shopInfo
64
     * @param array    $currencies
65
     * @param array    $categories
66
     * @param array    $offers
67
     * @param array    $deliveries
68
     *
69
     * @return bool
70
     */
71
    public function generate(ShopInfo $shopInfo, array $currencies, array $categories, array $offers, array $deliveries = [])
72
    {
73
        try {
74
            $this->addHeader();
75
76
            $this->addShopInfo($shopInfo);
77
            $this->addCurrencies($currencies);
78
            $this->addCategories($categories);
79
80
            if (\count($deliveries) !== 0) {
81
                $this->addDeliveries($deliveries);
82
            }
83
84
            $this->addOffers($offers);
85
            $this->addFooter();
86
87
            if (null !== $this->settings->getOutputFile()) {
88
                \copy($this->tmpFile, $this->settings->getOutputFile());
89
                @\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...
90
            }
91
92
            return true;
93
        } catch (\Exception $exception) {
94
            throw new \RuntimeException(\sprintf('Problem with generating YML file: %s', $exception->getMessage()), 0, $exception);
95
        }
96
    }
97
98
    /**
99
     * Add document header
100
     */
101
    protected function addHeader()
102
    {
103
        $this->writer->startDocument('1.0', $this->settings->getEncoding());
104
        $this->writer->startDTD('yml_catalog', null, 'shops.dtd');
105
        $this->writer->endDTD();
106
        $this->writer->startElement('yml_catalog');
107
        $this->writer->writeAttribute('date', \date('Y-m-d H:i'));
108
        $this->writer->startElement('shop');
109
    }
110
111
    /**
112
     * Add document footer
113
     */
114
    protected function addFooter()
115
    {
116
        $this->writer->fullEndElement();
117
        $this->writer->fullEndElement();
118
        $this->writer->endDocument();
119
    }
120
121
    /**
122
     * Adds shop element data. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#shop)
123
     *
124
     * @param ShopInfo $shopInfo
125
     */
126
    protected function addShopInfo(ShopInfo $shopInfo)
127
    {
128
        foreach ($shopInfo->toArray() as $name => $value) {
129
            if ($value !== null) {
130
                $this->writer->writeElement($name, $value);
131
            }
132
        }
133
    }
134
135
    /**
136
     * @param Currency $currency
137
     */
138
    protected function addCurrency(Currency $currency)
139
    {
140
        $this->writer->startElement('currency');
141
        $this->writer->writeAttribute('id', $currency->getId());
142
        $this->writer->writeAttribute('rate', $currency->getRate());
143
        $this->writer->endElement();
144
    }
145
146
    /**
147
     * @param Category $category
148
     */
149 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...
150
    {
151
        $this->writer->startElement('category');
152
        $this->writer->writeAttribute('id', $category->getId());
153
154
        if ($category->getParentId() !== null) {
155
            $this->writer->writeAttribute('parentId', $category->getParentId());
156
        }
157
158
        $this->writer->text($category->getName());
159
        $this->writer->fullEndElement();
160
    }
161
162
    /**
163
     * @param Delivery $delivery
164
     */
165 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...
166
    {
167
        $this->writer->startElement('option');
168
        $this->writer->writeAttribute('cost', $delivery->getCost());
169
        $this->writer->writeAttribute('days', $delivery->getDays());
170
        if ($delivery->getOrderBefore() !== null) {
171
            $this->writer->writeAttribute('order-before', $delivery->getOrderBefore());
172
        }
173
        $this->writer->endElement();
174
    }
175
176
    /**
177
     * @param OfferInterface $offer
178
     */
179
    protected function addOffer(OfferInterface $offer)
180
    {
181
        $this->writer->startElement('offer');
182
        $this->writer->writeAttribute('id', $offer->getId());
183
        $this->writer->writeAttribute('available', $offer->isAvailable() ? 'true' : 'false');
184
185
        if ($offer->getType() !== null) {
186
            $this->writer->writeAttribute('type', $offer->getType());
187
        }
188
189
        if ($offer instanceof OfferGroupAwareInterface && $offer->getGroupId() !== null) {
190
            $this->writer->writeAttribute('group_id', $offer->getGroupId());
191
        }
192
193
        foreach ($offer->toArray() as $name => $value) {
194
            if (\is_array($value)) {
195
                foreach ($value as $itemValue) {
196
                    $this->addOfferElement($name, $itemValue);
197
                }
198
            } else {
199
                $this->addOfferElement($name, $value);
200
            }
201
        }
202
        $this->addOfferParams($offer);
203
        $this->addOfferDeliveryOptions($offer);
204
        $this->addOfferCondition($offer);
205
206
        $this->writer->fullEndElement();
207
    }
208
209
    /**
210
     * Adds <currencies> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#currencies)
211
     *
212
     * @param array $currencies
213
     */
214
    private function addCurrencies(array $currencies)
215
    {
216
        $this->writer->startElement('currencies');
217
218
        /** @var Currency $currency */
219
        foreach ($currencies as $currency) {
220
            if ($currency instanceof Currency) {
221
                $this->addCurrency($currency);
222
            }
223
        }
224
225
        $this->writer->fullEndElement();
226
    }
227
228
    /**
229
     * Adds <categories> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#categories)
230
     *
231
     * @param array $categories
232
     */
233
    private function addCategories(array $categories)
234
    {
235
        $this->writer->startElement('categories');
236
237
        /** @var Category $category */
238
        foreach ($categories as $category) {
239
            if ($category instanceof Category) {
240
                $this->addCategory($category);
241
            }
242
        }
243
244
        $this->writer->fullEndElement();
245
    }
246
247
    /**
248
     * Adds <delivery-option> element. (See https://yandex.ru/support/partnermarket/elements/delivery-options.xml)
249
     *
250
     * @param array $deliveries
251
     */
252
    private function addDeliveries(array $deliveries)
253
    {
254
        $this->writer->startElement('delivery-options');
255
256
        /** @var Delivery $delivery */
257
        foreach ($deliveries as $delivery) {
258
            if ($delivery instanceof Delivery) {
259
                $this->addDelivery($delivery);
260
            }
261
        }
262
263
        $this->writer->fullEndElement();
264
    }
265
266
    /**
267
     * Adds <offers> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#offers)
268
     *
269
     * @param array $offers
270
     */
271
    private function addOffers(array $offers)
272
    {
273
        $this->writer->startElement('offers');
274
275
        /** @var OfferInterface $offer */
276
        foreach ($offers as $offer) {
277
            if ($offer instanceof OfferInterface) {
278
                $this->addOffer($offer);
279
            }
280
        }
281
282
        $this->writer->fullEndElement();
283
    }
284
285
    /**
286
     * @param OfferInterface $offer
287
     */
288
    private function addOfferDeliveryOptions(OfferInterface $offer)
289
    {
290
        $options = $offer->getDeliveryOptions();
291
        if (!empty($options)) {
292
            $this->addDeliveries($options);
293
        }
294
    }
295
296
    /**
297
     * @param OfferInterface $offer
298
     */
299
    private function addOfferParams(OfferInterface $offer)
300
    {
301
        /** @var OfferParam $param */
302
        foreach ($offer->getParams() as $param) {
303
            if ($param instanceof OfferParam) {
304
                $this->writer->startElement('param');
305
306
                $this->writer->writeAttribute('name', $param->getName());
307
                if ($param->getUnit()) {
308
                    $this->writer->writeAttribute('unit', $param->getUnit());
309
                }
310
                $this->writer->text($param->getValue());
311
312
                $this->writer->endElement();
313
            }
314
        }
315
    }
316
317
    /**
318
     * @param OfferInterface $offer
319
     */
320
    private function addOfferCondition(OfferInterface $offer)
321
    {
322
        $params = $offer->getCondition();
323
        if ($params instanceof OfferCondition) {
324
            $this->writer->startElement('condition');
325
            $this->writer->writeAttribute('type', $params->getType());
326
            $this->writer->writeElement('reason', $params->getReasonText());
327
            $this->writer->endElement();
328
        }
329
    }
330
331
    /**
332
     * @param string $name
333
     * @param mixed  $value
334
     *
335
     * @return bool
336
     */
337
    private function addOfferElement($name, $value)
338
    {
339
        if ($value === null) {
340
            return false;
341
        }
342
343
        if ($value instanceof Cdata) {
344
            $this->writer->startElement($name);
345
            $this->writer->writeCdata((string) $value);
346
            $this->writer->endElement();
347
348
            return true;
349
        }
350
351
        if (\is_bool($value)) {
352
            $value = $value ? 'true' : 'false';
353
        }
354
        $this->writer->writeElement($name, $value);
355
356
        return true;
357
    }
358
}
359