PluginProbe
Pixelavo – Server Side Tracking & Pixel + AI Ads Tools / 1.2.2
Pixelavo – Server Side Tracking & Pixel + AI Ads Tools v1.2.2
1.5.5 1.5.4 trunk 1.0.0 1.0.1 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 All 47 releases
pixelavo / includes / pixel-feed.php

pixel-feed.php in Pixelavo – Server Side Tracking & Pixel + AI Ads Tools 1.2.2, at includes/pixel-feed.php

292 lines 10.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Pixelavo;
4
5 /* Exit if accessed directly */
6 if (!defined('ABSPATH')) {
7 exit;
8 }
9
10 class PixelFeed{
11
12 private static $_instance = null;
13
14 /**
15 * Instance.
16 * Initializes a singleton instance.
17 * @return self class
18 */
19 static function instance() {
20 if ( is_null( self::$_instance ) ) {
21 self::$_instance = new self();
22 }
23 return self::$_instance;
24 }
25
26 function __construct() {
27 add_action('init', [$this, 'init_feed']);
28 add_filter('feed_content_type', [$this, 'feed_content_type'], 10, 2);
29 }
30
31 function feed_content_type($content_type, $type) {
32 if ('pixelavo' === $type) {
33 return feed_content_type( 'rss-http' );
34 }
35 return $content_type;
36 }
37
38 /**
39 * Feed.
40 * Run when user search for any product and go to `search` page.
41 * @return void
42 */
43 function init_feed() {
44 add_feed( 'pixelavo', [$this, 'pixel_feed'] );
45 }
46
47 function pixel_feed() {
48
49 /**
50 * Settings
51 */
52 $settings = get_option('pixelavo_settings');
53 $exclude_categories = array_key_exists('exclude_categories', $settings) ? $settings['exclude_categories'] : [];
54 $exclude_tags = array_key_exists('exclude_tags', $settings) ? $settings['exclude_tags'] : [];
55
56 /**
57 * Products
58 */
59 $args = [
60 'status' => 'publish',
61 'limit' => -1,
62 'orderby' => 'ID',
63 'order' => 'ASC',
64 'tax_query' => [
65 'relation' => 'AND',
66 [
67 'taxonomy' => 'product_cat',
68 'field' => 'term_id',
69 'terms' => $exclude_categories,
70 'operator' => 'NOT IN',
71 ],
72 [
73 'taxonomy' => 'product_tag',
74 'field' => 'term_id',
75 'terms' => $exclude_tags,
76 'operator' => 'NOT IN',
77 ]
78 ],
79 ];
80 $products = wc_get_products($args);
81
82 /**
83 * Feed Namespace
84 */
85 $namespace = 'http://base.google.com/ns/1.0';
86
87 /**
88 * Feed RSS
89 */
90 $rss = new \SimpleXMLElement("<?xml version='1.0' encoding='UTF-8'?><rss xmlns:g='{$namespace}'></rss>");
91 $rss->addAttribute('version', '2.0');
92
93 /**
94 * Feed Channel
95 */
96 $channel = $rss->addChild('channel');
97 $channel->addChild('title', get_bloginfo('name'));
98 if(!empty(get_bloginfo('description'))) {
99 $channel->addChild('description', get_bloginfo('description'));
100 }
101 $channel->addChild('link', get_bloginfo('url'));
102
103 /**
104 * Feed Item
105 */
106 foreach ($products as $product) {
107 $pro['id'] = $settings['product_identifier'] == 'post_id' ? $product->get_id() : $product->get_sku();
108 $pro['group_id'] = $pro['id'];
109 $pro['title'] = $product->get_title();
110 $pro['desc'] = $settings['description_field'] == 'description' ? $product->get_description() : $product->get_short_description();
111 $pro['link'] = $product->get_permalink();
112 $pro['image_link'] = $this->get_image_link($product->get_id());
113 $pro['brand'] = $this->get_brand($product->get_id());
114 $pro['condition'] = $this->get_condition($product->get_id());
115 $pro['availability'] = $product->is_in_stock() ? 'in stock' : 'out of stock';
116 $pro['price'] = $this->get_price($product);
117 $pro['extra_fields'] = $this->get_extra_fields($product);
118 $pro['additional_images'] = $this->get_additional_images($product);
119 $pro['google_product_category'] = empty( $settings['product_feed_gpc'] ) ? $product->get_attribute( 'google_product_category' ) : $settings['product_feed_gpc'];
120
121 if($product->is_type('variable') && pixelavo_get_option('include_variations', 'pixelavo_settings') == 'on') {
122 foreach ($product->get_available_variations() as $variation) {
123 $pro['additional_images'] = $this->get_additional_images($product, $variation);
124 $this->feed_item($channel, $pro, $namespace, $variation);
125 }
126 } else {
127 $this->feed_item($channel, $pro, $namespace);
128 }
129 }
130
131 echo $rss->asXML(); // phpcs:ignore
132 }
133
134 /**
135 * Feed item function
136 */
137 function feed_item($channel, $product, $namespace, $variation = false) {
138
139 if($variation) {
140 $product['id'] = $product['id'] . '-' . $variation['variation_id'];
141 $product['title'] = $product['title'] . ' - ' . $this->get_variation_title($variation['attributes']);
142 $product['extra_fields'] = array_merge($product['extra_fields'], $this->get_extra_fields(null,$variation['attributes']));
143 }
144
145 $item = $channel->addChild('item');
146 $item->addChild("g:id", $product['id'], $namespace);
147 $item->addChild("g:item_group_id", $product['group_id'], $namespace);
148 $item->addChild("g:title", $product['title'], $namespace);
149 $item->addChild("g:description", $product['desc'], $namespace);
150 $item->addChild("g:availability", $product['availability'], $namespace);
151 $item->addChild("g:condition", $product['condition'], $namespace);
152 if($product['price']) {
153 $item->addChild("g:price", $product['price'], $namespace);
154 }
155 $item->addChild("g:link", $product['link'], $namespace);
156 if($product['image_link']) {
157 $item->addChild("g:image_link", $product['image_link'], $namespace);
158 }
159 if(isset($product['google_product_category']) && !empty($product['google_product_category'])) {
160 $item->addChild("g:google_product_category", $product['google_product_category'], $namespace);
161 }
162 if(!empty($product['brand'])) {
163 $item->addChild("g:brand", $product['brand'], $namespace);
164 }
165 foreach ($product['extra_fields'] as $key => $value) {
166 $item->addChild("g:{$key}", $value, $namespace);
167 }
168 foreach ($product['additional_images'] as $image) {
169 $item->addChild("g:additional_image_link", $image, $namespace);
170 }
171 }
172
173 /**
174 * Get variation product title
175 */
176 function get_variation_title($variations) {
177 if (is_array($variations)) {
178 $variation_values = [];
179 foreach ($variations as $variation) {
180 if(!empty($variation)) {
181 $variation_values[] = $variation;
182 }
183 }
184 return '(' . implode( '-', $variation_values ) . ')';
185 }
186 return '';
187 }
188
189 /**
190 * Get product thumbnail image link
191 */
192 function get_image_link($product_id, $variation = null) {
193 $image_id = is_array( $variation ) ? $variation[ 'image_id' ] : get_post_thumbnail_id( $product_id );
194 $image = wp_get_attachment_image_src( $image_id, 'single-post-thumbnail' );
195 if($image) {
196 return $image[0];
197 }
198 return $image;
199 }
200
201 /**
202 * Get brand name
203 */
204 function get_brand($product_id) {
205 $brand_terms = wp_get_post_terms( $product_id, 'product_brand' );
206 if (!empty($brand_terms) && !is_wp_error($brand_terms)) {
207 return $brand_terms[0]->name;
208 }
209 $settings = get_option('pixelavo_settings');
210 return isset($settings['product_feed_brand']) ? $settings['product_feed_brand'] : '';
211 }
212
213 /**
214 * Get product condition
215 */
216 function get_condition($product_id) {
217 $condition = get_post_meta($product_id, '_product_condition', true);
218 if (empty($condition)) {
219 return 'new';
220 }
221 return $condition;
222 }
223
224 /**
225 * Get product price
226 */
227 function get_price($product, $variation = null) {
228 $the_price = is_array($variation) ? $variation['display_price'] : wc_get_price_to_display( $product );
229 if ($the_price) {
230 return $the_price . ' ' . get_woocommerce_currency();
231 }
232 return false;
233 }
234
235 /**
236 * Get product extra fields
237 */
238 function get_extra_fields($product, $variation = null) {
239 $fields = ['color', 'gender', 'pattern', 'material', 'size'];
240 $extra_fields = [];
241 forEach ( $fields as $field ) {
242 if ( isSet($variation[ 'attribute_pa_' . $field ]) && !empty($variation[ 'attribute_pa_' . $field ])) {
243 $extra_fields[$field] = $variation[ 'attribute_pa_' . $field ];
244 } else if (isSet($product) && $product->get_attribute($field) && !empty($product->get_attribute($field))) {
245 $extra_fields[$field] = $product->get_attribute($field);
246 }
247 }
248 return $extra_fields;
249 }
250
251 /**
252 * Get product categories
253 */
254 function get_categories($product) {
255 $categories = get_the_terms($product->get_id(), 'product_cat');
256 $category_string = '';
257 if (!empty($categories)) {
258 $categories = wp_list_sort($categories, ['parent' => 'ASC', 'name' => 'ASC'], 'ASC');
259 foreach ($categories as $category) {
260 $category_string = empty($category_string) ? $category_string . $category->name : $category_string .' > '. $category->name;
261 }
262 }
263 return $category_string;
264 }
265
266 /**
267 * Get product additional images
268 */
269 function get_additional_images( $product, $variation = null ) {
270 $images = [];
271 /* Variation Image */
272 $variation_image = is_array($variation) ? wp_get_attachment_image_src($variation['image_id'], 'single-post-thumbnail') : false;
273 if ($variation_image) {
274 $images[] = $variation_image[0];
275 }
276 /* Gallery Images */
277 $gallery_ids = $product->get_gallery_image_ids();
278 if (!empty($gallery_ids)) {
279 foreach($gallery_ids as $gallery_id) {
280 $images[] = wp_get_attachment_url($gallery_id);
281 }
282 }
283 return array_unique($images);
284 }
285
286 }
287
288 /**
289 * Initialize PixelFeed Class
290 */
291 PixelFeed::instance();
292