FeedRss::setFacebookAds()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 11
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 21
rs 9.9
1
<?php
2
3
namespace CodeBlog\FeedRss;
4
5
use \DOMDocument;
6
use DOMElement;
7
8
/**
9
 * Class CodeBlog FeedRss
10
 *
11
 * @author Whallysson Avelino <https://github.com/whallysson>
12
 * @package CodeBlog\FeedRss
13
 */
14
class FeedRss
15
{
16
    /** @var */
17
    protected $rss;
18
19
    /** @var */
20
    protected $xml;
21
22
    /** @var */
23
    protected $channel;
24
25
    /** @var string */
26
    protected $title;
27
28
    /** @var string */
29
    protected $link;
30
31
    /** @var bool */
32
    protected $googleMerchant = false;
33
34
    /** @var bool */
35
    protected $facebookAds = false;
36
37
    /**
38
     * FeedRss constructor.
39
     * @param bool|null $facebookAds
40
     * @param bool|null $googleMerchant
41
     */
42
    public function __construct(?bool $facebookAds = false, ?bool $googleMerchant = false)
43
    {
44
        $this->xml = new DOMDocument('1.0', 'utf-8');
45
        $this->xml->formatOutput = true;
46
47
        //Rss
48
        $this->rss = $this->xml->createElement('rss');
49
        $this->rss->setAttribute('version', '2.0');
50
        $this->rss->setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1');
51
52
        if ($facebookAds) {
53
            $this->facebookAds = true;
54
        }
55
56
        if ($googleMerchant) {
57
            $this->googleMerchant = true;
58
            $this->rss->setAttribute('xmlns:g', 'http://base.google.com/ns/1.0');
59
        }
60
    }
61
62
    /**
63
     * @param string $title
64
     * @param string $link
65
     * @param string $description
66
     * @param string|null $language
67
     */
68
    public function setChannel(string $title, string $link, string $description, ?string $language = 'pt-BR'): void
69
    {
70
        $this->title = $title;
71
        $this->link = $link;
72
73
        // channel
74
        $this->channel = $this->xml->createElement('channel');
75
76
        $this->channel->appendChild(
77
            $this->xml->createElement('title', $title)
78
        );
79
        $this->channel->appendChild(
80
            $this->xml->createElement('link', $link)
81
        );
82
        $this->channel->appendChild(
83
            $this->xml->createElement('description', $description)
84
        );
85
        $this->channel->appendChild(
86
            $this->xml->createElement('language', $language)
87
        );
88
89
        $this->rss->appendChild($this->channel);
90
    }
91
92
    /**
93
     * @param string $url
94
     * @param string|null $title
95
     * @param string|null $link
96
     */
97
    public function setChannelImage(string $url, ?string $title = null, ?string $link = null): void
98
    {
99
        if (!empty($this->channel)) {
100
            $image = $this->xml->createElement('image');
101
102
            $image->appendChild($this->xml->createElement('title', (!empty($title) ? $title : $this->title)));
103
            $image->appendChild($this->xml->createElement('link', (!empty($link) ? $link : $this->link)));
104
            $image->appendChild($this->xml->createElement('url', $url));
105
106
            $this->channel->appendChild($image);
107
        }
108
    }
109
110
    /**
111
     * @param array $data
112
     */
113
    public function renderRss(array $data): void
114
    {
115
        if (empty($data)) {
116
            return;
117
        }
118
119
        $data = json_decode(json_encode($data));
120
121
        // Items
122
        foreach ($data as $item) {
123
124
            $title = $this->strLimitChars($this->strClean($item->title), 150, '');
125
            $description = $this->strLimitChars($this->strClean($item->description), 5000, '');
126
127
            // item element
128
            $itemElement = $this->xml->createElement("item");
129
130
            // title
131
            $itemElement->appendChild($this->xml->createElement('title', $title));
132
133
            // description Element
134
            $itemDescription = $this->xml->createElement('description');
135
            $itemDescription->appendChild($this->xml->createCDATASection($description));
136
            $itemElement->appendChild($itemDescription);
137
138
            $dtPub = date('D, d M Y H:i:s O', strtotime($item->publication));
139
            $itemElement->appendChild($this->xml->createElement('pubDate', $dtPub));
140
141
            // enclosure
142
            $itemEnclosure = $this->xml->createElement('enclosure');
143
            $itemEnclosure->setAttribute('url', $item->image->url);
144
            $itemEnclosure->setAttribute('type', 'image/*');
145
            $itemEnclosure->setAttribute('length', 0);
146
            $itemElement->appendChild($itemEnclosure);
147
148
            // image
149
            $itemImage = $this->xml->createElement('image');
150
151
            $imageTitle = $this->xml->createElement('title');
152
            $imageTitle->appendChild($this->xml->createCDATASection($item->image->title));
153
154
            $itemImage->appendChild($this->xml->createElement('link', $item->link));
155
            $itemImage->appendChild($this->xml->createElement('url', $item->image->url));
156
            $itemImage->appendChild($imageTitle);
157
158
            $itemElement->appendChild($itemImage);
159
            //image - end
160
161
            // others
162
            $itemElement->appendChild($this->xml->createElement('link', $item->link));
163
            $itemElement->appendChild($this->xml->createElement('guid', $item->link));
164
165
166
            //FB ADS PRODUCTS
167
            if ($this->facebookAds && !empty($item->facebook_ads)) {
168
                $this->setFacebookAds($itemElement, $item->facebook_ads);
169
            }
170
171
            // GOOGLE MERCHANT
172
            if ($this->googleMerchant && !empty($item->google_merchant)) {
173
                $this->setGoogleMerchant($itemElement, $item->google_merchant, $title, $description);
174
            }
175
176
            $this->channel->appendChild($itemElement);
177
        }
178
179
        $this->xml->appendChild($this->rss);
180
181
        header('Content-type: text-xml');
182
        echo $this->xml->saveXML();
183
    }
184
185
    /**
186
     * @param DOMElement $itemElement
187
     * @param object $item
188
     */
189
    private function setFacebookAds(DOMElement $itemElement, object $item): void
190
    {
191
        /*
192
         * https://www.facebook.com/business/help/120325381656392?id=725943027795860
193
         * Items required:
194
         * id, title, description, availability, condition, price, link, image_link, brand
195
         */
196
197
        $required = ['id', 'availability', 'condition', 'price', 'image_link', 'brand'];
198
199
        $itemElement->appendChild($this->xml->createElement('id', $item->id));
200
        $itemElement->appendChild($this->xml->createElement('image_link', $item->image_link));
201
        $itemElement->appendChild($this->xml->createElement('condition', $item->condition)); // new, refurbished, used.
202
        $itemElement->appendChild($this->xml->createElement('price', $item->price));
203
        $itemElement->appendChild($this->xml->createElement('availability',
204
            $item->availability)); // in stock | out of stock
205
        $itemElement->appendChild($this->xml->createElement('brand', htmlspecialchars($item->brand)));
206
207
        foreach ($item as $key => $value) {
208
            if (!in_array($key, $required)) {
209
                $itemElement->appendChild($this->xml->createElement($key, $value));
210
            }
211
        }
212
    }
213
214
    /**
215
     * @param DOMElement $itemElement
216
     * @param object $item
217
     * @param string $title
218
     * @param string $description
219
     */
220
    private function setGoogleMerchant(DOMElement $itemElement, object $item, string $title, string $description): void
221
    {
222
        $required = ['title', 'description'];
223
224
        $itemElement->appendChild($this->xml->createElement('g:title', $title));
225
226
        $gItemDescription = $this->xml->createElement('g:description');
227
        $gItemDescription->appendChild($this->xml->createCDATASection($description));
228
        $itemElement->appendChild($gItemDescription);
229
230
        foreach ($item as $key => $value) {
231
            if (!in_array($key, $required)) {
232
                $itemElement->appendChild($this->xml->createElement("g:{$key}", $value));
233
            }
234
        }
235
    }
236
237
    /**
238
     * @param string $string
239
     * @param int $limit
240
     * @param string $pointer
241
     * @return string
242
     */
243
    private function strLimitChars(string $string, int $limit, string $pointer = "..."): string
244
    {
245
        $string = trim(filter_var($string, FILTER_SANITIZE_SPECIAL_CHARS));
246
        if (mb_strlen($string) <= $limit) {
247
            return $string;
248
        }
249
250
        $chars = mb_substr($string, 0, mb_strrpos(mb_substr($string, 0, $limit), " "));
251
        return "{$chars}{$pointer}";
252
    }
253
254
    /**
255
     * @param string $string
256
     * @return string
257
     */
258
    private function strClean(string $string): string
259
    {
260
        return str_replace('&', 'e', htmlspecialchars($string));
261
    }
262
}