PluginProbe
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More / 2.2.0
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More v2.2.0
2.3.0 2.2.0 2.1.1 2.1.0 2.0.0 1.10.0 1.9.1 1.9.0 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 All 59 releases
storeengine / includes / utils / traits / product.php

product.php in StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More 2.2.0, at includes/utils/traits/product.php

245 lines 8.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace StoreEngine\Utils\traits;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 use StoreEngine\Classes\AbstractProduct;
10 use StoreEngine\Classes\Data\AttributeData;
11 use StoreEngine\Classes\Exceptions\StoreEngineException;
12 use StoreEngine\Classes\Price;
13 use StoreEngine\Classes\ProductFactory;
14 use StoreEngine\Classes\Variation;
15 use StoreEngine\Utils\Helper;
16
17 trait Product {
18
19 public static function get_product( int $product_id ) {
20 $product = ( new ProductFactory() )->get_product( $product_id );
21
22 return $product instanceof AbstractProduct && $product->get_id() ? $product : false;
23 }
24
25 public static function get_product_by_price_id( int $price_id ) {
26 $product = ( new ProductFactory() )->get_product_by_price_id( $price_id );
27
28 return $product instanceof AbstractProduct && $product->get_id() ? $product : false;
29 }
30
31 /**
32 * @param array $args Arguments for get_posts().
33 *
34 * @return AbstractProduct[]
35 */
36 public static function get_products( array $args = array() ): array {
37 $args['post_type'] = Helper::DB_PREFIX . 'product';
38 $args = wp_parse_args( $args, [
39 's' => '',
40 'posts_per_page' => 10,
41 'paged' => 1,
42 'orderby' => 'date',
43 'order' => 'DESC',
44 'post_status' => 'publish',
45 ] );
46
47 $cache_key = 'storeengine_products_' . md5( wp_json_encode( $args ) );
48 $has_cache = wp_cache_get( $cache_key, AbstractProduct::CACHE_GROUP );
49 if ( $has_cache ) {
50 return $has_cache;
51 }
52
53 $posts = get_posts( $args );
54 if ( empty( $posts ) ) {
55 return [];
56 }
57 $posts = array_map( fn( $post ) => (array) $post, $posts );
58
59 $post_ids = array_map( fn( $post ) => $post['ID'], $posts );
60 $placeholders = array_fill( 0, count( $posts ), '%d' );
61 $placeholders = implode( ',', $placeholders );
62
63 global $wpdb;
64 //phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- we're preparing dynamic placeholder above.
65 $meta_data = $wpdb->get_results( $wpdb->prepare( "
66 SELECT post_id, meta_key, meta_value
67 FROM $wpdb->postmeta
68 WHERE post_id IN ($placeholders)", ...$post_ids
69 ) );
70 //phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
71
72 $meta_data_by_posts = [];
73 foreach ( $meta_data as $meta ) {
74 //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
75 $meta_data_by_posts[ $meta->post_id ][ $meta->meta_key ] = $meta->meta_value;
76 }
77
78 $products = [];
79 foreach ( $posts as $post ) {
80 $product_type = get_post_meta( $post['ID'], '_storeengine_product_type', true );
81 $classname = ProductFactory::get_product_classname( $post['ID'], $product_type );
82 $instance = new $classname();
83
84 $instance->set_data( $post );
85 $instance->set_metadata( is_array( $meta_data_by_posts[ $post['ID'] ] ) ? $meta_data_by_posts[ $post['ID'] ] : [] );
86 $products[] = $instance;
87 }
88 wp_cache_set( $cache_key, $products, AbstractProduct::CACHE_GROUP );
89
90 return $products;
91 }
92
93 /**
94 * @throws StoreEngineException
95 */
96 public static function get_price( int $price_id ) {
97 return ( new Price( $price_id ) );
98 }
99
100 public static function get_prices_array_by_product_id( int $product_id, $context = 'view', bool $force_show_hidden = false ): array {
101 $product = self::get_product( $product_id );
102 if ( ! $product ) {
103 return [];
104 }
105
106 return self::get_prices_array_from_product( $product, $context, $force_show_hidden );
107 }
108
109 /**
110 * @param AbstractProduct $product
111 *
112 * @return array
113 */
114 public static function get_prices_array_from_product( AbstractProduct $product, $context = 'view', bool $force_show_hidden = false ): array {
115 $prices = [];
116 foreach ( $product->get_prices( $force_show_hidden ) as $price ) {
117 $prices[] = [
118 'id' => $price->get_id(),
119 'price_name' => $price->get_name(),
120 'price_type' => $price->get_type(),
121 'price' => $price->get_price($context),
122 'compare_price' => $price->get_compare_price($context),
123 'product_id' => $price->get_product_id(),
124 'settings' => $price->get_settings(),
125 'order' => $price->get_menu_order(),
126 'checkout_link' => add_query_arg( [
127 'product_id' => $price->get_product_id(),
128 'price_id' => $price->get_id(),
129 ], Helper::get_checkout_url() ),
130 ];
131 }
132
133 return $prices;
134 }
135
136 public static function get_product_variation( int $id ) {
137 return ( new Variation( $id ) )->get();
138 }
139
140 public static function get_product_list( int $integration_id, string $provider, string $search = '' ): array {
141 $products = get_posts( [
142 'post_type' => 'storeengine_product',
143 'posts_per_page' => 10,
144 'post_status' => 'publish',
145 's' => $search,
146 ] );
147
148 if ( empty( $products ) ) {
149 return [];
150 }
151
152 $product_ids = array_map( fn( $product ) => $product->ID, $products );
153 $product_ids_formatter = implode( ',', array_fill( 0, count( $product_ids ), '%d' ) );
154
155 global $wpdb;
156 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
157 $prices = $wpdb->get_results(
158 $wpdb->prepare(
159 "
160 SELECT
161 p.id,
162 p.product_id,
163 price_name,
164 price_type,
165 price,
166 compare_price,
167 `order`
168 FROM
169 {$wpdb->prefix}storeengine_product_price p
170 WHERE
171 NOT EXISTS ( SELECT 1 FROM {$wpdb->prefix}storeengine_integrations i
172 WHERE i.price_id = p.id AND i.integration_id = %d AND i.provider = %s)
173 AND p.product_id IN ($product_ids_formatter);
174 ",
175 $integration_id,
176 $provider,
177 ...$product_ids
178 )
179 );
180 // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
181
182 $product_prices = [];
183 foreach ( $prices as $price ) {
184 $product_prices[ (int) $price->product_id ][] = $price;
185 }
186
187 return array_map( function ( $product ) use ( $product_prices ) {
188 return [
189 'label' => $product->post_title,
190 'value' => $product->ID,
191 'prices' => $product_prices[ $product->ID ] ?? [],
192 ];
193 }, $products );
194 }
195
196 public static function get_variation_attributes( int $product_id, int $price_id = 0 ): array {
197 $product = self::get_product( $product_id );
198 if ( ! $product || 'variable' !== $product->get_type() ) {
199 return [];
200 }
201 $variation_attributes = [];
202
203 $variant_with_attributes = [];
204 foreach ( $product->get_available_variants() as $variant ) {
205 if ( 0 < $price_id && (int) $variant->get_pricing_id() !== $price_id ) {
206 continue;
207 }
208 $variant_with_attributes[] = $variant->get_attributes();
209 }
210 /** @var AttributeData[] $variant_with_attributes */
211 $variant_with_attributes = array_merge( ...$variant_with_attributes );
212
213 foreach ( $variant_with_attributes as $variant_with_attribute ) {
214 $attribute_taxonomy = get_taxonomy( $variant_with_attribute->taxonomy );
215 if ( ! $attribute_taxonomy ) {
216 continue;
217 }
218 if ( ! isset( $variation_attributes[ $variant_with_attribute->taxonomy ] ) ) {
219 $variation_attributes[ $variant_with_attribute->taxonomy ] = [
220 'name' => $attribute_taxonomy->label,
221 'taxonomy' => $variant_with_attribute->taxonomy,
222 'options' => [
223 [
224 'id' => $variant_with_attribute->term_id,
225 'name' => $variant_with_attribute->name,
226 'slug' => $variant_with_attribute->slug,
227 'description' => $variant_with_attribute->description,
228 ],
229 ],
230 ];
231 } else {
232 $variation_attributes[ $variant_with_attribute->taxonomy ]['options'][] = [
233 'id' => $variant_with_attribute->term_id,
234 'name' => $variant_with_attribute->name,
235 'slug' => $variant_with_attribute->slug,
236 'description' => $variant_with_attribute->description,
237 ];
238 $variation_attributes[ $variant_with_attribute->taxonomy ]['options'] = array_values( array_unique( $variation_attributes[ $variant_with_attribute->taxonomy ]['options'], SORT_REGULAR ) );
239 }
240 }
241
242 return array_values( $variation_attributes );
243 }
244 }
245