Completed
Push — master ( 9b1caf...f1fc38 )
by Bukashk0zzz
01:20
created

Generator::addOfferCondition()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
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->addOfferCondition($offer);
204
205
        $this->writer->fullEndElement();
206
    }
207
208
    /**
209
     * Adds <currencies> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#currencies)
210
     *
211
     * @param array $currencies
212
     */
213
    private function addCurrencies(array $currencies)
214
    {
215
        $this->writer->startElement('currencies');
216
217
        /** @var Currency $currency */
218
        foreach ($currencies as $currency) {
219
            if ($currency instanceof Currency) {
220
                $this->addCurrency($currency);
221
            }
222
        }
223
224
        $this->writer->fullEndElement();
225
    }
226
227
    /**
228
     * Adds <categories> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#categories)
229
     *
230
     * @param array $categories
231
     */
232
    private function addCategories(array $categories)
233
    {
234
        $this->writer->startElement('categories');
235
236
        /** @var Category $category */
237
        foreach ($categories as $category) {
238
            if ($category instanceof Category) {
239
                $this->addCategory($category);
240
            }
241
        }
242
243
        $this->writer->fullEndElement();
244
    }
245
246
    /**
247
     * Adds <delivery-option> element. (See https://yandex.ru/support/partnermarket/elements/delivery-options.xml)
248
     *
249
     * @param array $deliveries
250
     */
251
    private function addDeliveries(array $deliveries)
252
    {
253
        $this->writer->startElement('delivery-options');
254
255
        /** @var Delivery $delivery */
256
        foreach ($deliveries as $delivery) {
257
            if ($delivery instanceof Delivery) {
258
                $this->addDelivery($delivery);
259
            }
260
        }
261
262
        $this->writer->fullEndElement();
263
    }
264
265
    /**
266
     * Adds <offers> element. (See https://yandex.ru/support/webmaster/goods-prices/technical-requirements.xml#offers)
267
     *
268
     * @param array $offers
269
     */
270
    private function addOffers(array $offers)
271
    {
272
        $this->writer->startElement('offers');
273
274
        /** @var OfferInterface $offer */
275
        foreach ($offers as $offer) {
276
            if ($offer instanceof OfferInterface) {
277
                $this->addOffer($offer);
278
            }
279
        }
280
281
        $this->writer->fullEndElement();
282
    }
283
284
    /**
285
     * @param OfferInterface $offer
286
     */
287
    private function addOfferParams(OfferInterface $offer)
288
    {
289
        /** @var OfferParam $param */
290
        foreach ($offer->getParams() as $param) {
291
            if ($param instanceof OfferParam) {
292
                $this->writer->startElement('param');
293
294
                $this->writer->writeAttribute('name', $param->getName());
295
                if ($param->getUnit()) {
296
                    $this->writer->writeAttribute('unit', $param->getUnit());
297
                }
298
                $this->writer->text($param->getValue());
299
300
                $this->writer->endElement();
301
            }
302
        }
303
    }
304
305
    /**
306
     * @param OfferInterface $offer
307
     */
308
    private function addOfferCondition(OfferInterface $offer)
309
    {
310
        $params = $offer->getCondition();
311
        if ($params instanceof OfferCondition) {
312
            $this->writer->startElement('condition');
313
            $this->writer->writeAttribute('type', $params->getType());
314
            $this->writer->writeElement('reason', $params->getReasonText());
315
            $this->writer->endElement();
316
        }
317
    }
318
319
    /**
320
     * @param string $name
321
     * @param mixed  $value
322
     *
323
     * @return bool
324
     */
325
    private function addOfferElement($name, $value)
326
    {
327
        if ($value === null) {
328
            return false;
329
        }
330
331
        if ($value instanceof Cdata) {
332
            $this->writer->startElement($name);
333
            $this->writer->writeCdata((string) $value);
334
            $this->writer->endElement();
335
336
            return true;
337
        }
338
339
        if (\is_bool($value)) {
340
            $value = $value ? 'true' : 'false';
341
        }
342
        $this->writer->writeElement($name, $value);
343
344
        return true;
345
    }
346
}
347