PluginProbe ʕ •ᴥ•ʔ
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments / 4.5.0
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments v4.5.0
4.5.1 4.5.0 4.4.2 4.4.1 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.3 4.2.2 4.2.1 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 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.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.11.1 1.11.2 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 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 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.9.0 1.9.1 1.9.2 1.9.3 1.9.4 1.9.5 2.0.0 2.0.1 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.10.0 2.10.1 2.11.0 2.11.1 2.11.2 2.11.3 2.11.4 2.12.0 2.13.0 2.14.0 2.14.1 2.15.0 2.15.1 2.16.0 2.16.1 2.16.2 2.16.3 2.17.0 2.17.1 2.17.2 2.18.0 2.19.0 2.19.2 2.19.3 2.19.4 2.2.0 2.2.1 2.20.0 2.20.1 2.20.2 2.20.3 2.20.4 2.20.5 2.20.6 2.21.0 2.22.0 2.22.1 2.23.0 2.24.0 2.25.0 2.25.1 2.25.2 2.26.0 2.27.0 2.27.1 2.28.0 2.29.0 2.29.1 2.29.2 2.29.3 2.29.4 2.3.0 2.3.1 2.30.0 2.31.0 2.31.1 2.31.2 2.31.3 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.40.0 2.40.1 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.9.0 3.0.0 3.0.0-RC1 3.0.0-RC2 3.0.0-beta1 3.0.0-beta2 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.10.0 3.10.1 3.11.0 3.12.0 3.13.0 3.13.1 3.13.2 3.13.3 3.13.4 3.14.0 3.15.0 3.15.1 3.15.2 3.15.3 3.15.4 3.15.5 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.16.6 3.16.7 3.16.8 3.17.0 3.17.1 3.17.2 3.17.3 3.17.4 3.17.5 3.17.6 3.18.0 3.19.0 3.19.1 3.19.2 3.2.0 3.2.1 3.2.2 3.20.0 3.20.1 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 4.0.0 4.0.1 4.0.2 4.0.3 trunk 4.1.0 0.2.19.1 4.1.1 1.0.0 4.2.0 1.0.1 1.0.2
surecart / app / src / Models / Blocks / ProductListBlock.php
surecart / app / src / Models / Blocks Last commit date
AbstractProductListBlock.php 2 months ago ProductListBlock.php 2 months ago ProductPageBlock.php 2 months ago ProductReviewBlock.php 4 months ago ProductReviewListBlock.php 4 months ago RelatedProductsBlock.php 2 months ago
ProductListBlock.php
279 lines
1 <?php
2
3 namespace SureCart\Models\Blocks;
4
5 /**
6 * The product list block.
7 */
8 class ProductListBlock extends AbstractProductListBlock {
9 /**
10 * Get the query context.
11 *
12 * @return array
13 */
14 public function getQueryContext() {
15 return $this->block->context['query'] ?? [];
16 }
17
18 /**
19 * Build the query
20 *
21 * @return $this
22 */
23 public function parse_query() {
24 $query = $this->getQueryContext();
25
26 $offset = absint( $query['offset'] ?? 0 );
27 $per_page = $this->block->parsed_block['attrs']['query']['perPage'] ?? $this->block->parsed_block['attrs']['limit'] ?? $query['perPage'] ?? 15;
28 $order = ! empty( $this->url->getArg( 'order' ) )
29 ? sanitize_text_field( $this->url->getArg( 'order' ) )
30 : ( ! empty( $query['order'] ) ? $query['order'] : 'desc' );
31 $orderby = ! empty( $this->url->getArg( 'orderby' ) )
32 ? sanitize_text_field( $this->url->getArg( 'orderby' ) )
33 : ( ! empty( $query['orderBy'] ) ? $query['orderBy'] : 'date' );
34 $page = $this->url->getCurrentPage();
35
36 // build up the query.
37 $query_vars = array_filter(
38 array(
39 'post_type' => 'sc_product',
40 'post_status' => 'publish',
41 'ignore_sticky_posts' => 1,
42 'posts_per_page' => $per_page,
43 'offset' => ( $per_page * ( $page - 1 ) ) + $offset,
44 'paged' => (int) $this->url->getCurrentPage(),
45 'order' => $order,
46 'orderby' => $orderby,
47 's' => sanitize_text_field( $this->url->getArg( 'search' ) ),
48 )
49 );
50
51 // handle search.
52 if ( ! empty( $query['search'] ) && empty( $query_vars['s'] ) ) {
53 $query_vars['s'] = sanitize_text_field( $query['search'] );
54 }
55
56 // put together price query.
57 if ( 'price' === $this->url->getArg( 'orderby' ) ) {
58 $query_vars['meta_key'] = 'min_price_amount';
59 $query_vars['orderby'] = 'meta_value_num';
60 }
61
62 $tax_query = array(
63 'relation' => 'OR',
64 );
65
66 // handle tax query.
67 if ( ! empty( $query['taxQuery'] ) ) {
68 foreach ( $query['taxQuery'] as $taxonomy => $terms ) {
69 if ( is_taxonomy_viewable( $taxonomy ) && ! empty( $terms ) ) {
70 $tax_query[] = array(
71 'taxonomy' => sanitize_key( $taxonomy ),
72 'terms' => array_filter( array_map( 'absint', $terms ) ),
73 'include_children' => false,
74 );
75 }
76 }
77 }
78
79 // put together price query.
80 if ( 'price' === $orderby ) {
81 $query_vars['meta_key'] = 'min_price_amount';
82 $query_vars['orderby'] = 'meta_value_num';
83 }
84
85 $collection_id = sanitize_text_field( $this->block->context['surecart/product-list/collection_id'] ?? $this->block->parsed_block['attrs']['collection_id'] ?? '' );
86
87 // handle collection id send from "sc_product_collection" shortcode.
88 if ( ! empty( $collection_id ) ) {
89 $collection_ids = array_unique( array_map( 'sanitize_text_field', explode( ',', $collection_id ) ) );
90
91 $legacy_collection_ids = get_terms(
92 array(
93 'taxonomy' => 'sc_collection',
94 'field' => 'term_id',
95 'meta_query' => array(
96 array(
97 'key' => 'sc_id',
98 'value' => $collection_ids,
99 'compare' => 'IN',
100 ),
101 ),
102 )
103 ); // platform collection ids converted to WP taxonomy ids.
104
105 // only get the term_id.
106 $legacy_collection_ids = array_map(
107 function ( $term ) {
108 return $term->term_id;
109 },
110 $legacy_collection_ids
111 );
112
113 $tax_query[] =
114 array(
115 'taxonomy' => 'sc_collection',
116 'field' => 'term_id',
117 'terms' => array_unique( array_map( 'absint', $legacy_collection_ids ?? array() ) ),
118 );
119 } elseif ( is_tax() ) {
120 $term = get_queried_object();
121 $tax_query[] =
122 array(
123 'taxonomy' => 'sc_collection',
124 'field' => 'term_id',
125 'terms' => array_unique( array_map( 'absint', [ (int) $term->term_id ] ) ),
126 );
127 }
128
129 $all_taxonomies = $this->url->getAllTaxonomyArgs();
130
131 // handle taxonomies query.
132 foreach ( $all_taxonomies as $taxonomy => $terms ) {
133 $tax_query[] =
134 array(
135 'taxonomy' => $taxonomy,
136 'field' => 'slug',
137 'terms' => array_unique( array_map( 'strval', $terms ?? array() ) ),
138 'operator' => 'IN',
139 );
140 }
141
142 $query_vars['tax_query'][] = $tax_query;
143
144 // handle featured.
145 if ( 'featured' === ( $this->block->context['surecart/product-list/type'] ?? 'all' ) ) {
146 $query_vars['meta_query'] = [
147 [
148 'key' => 'featured',
149 'value' => '1',
150 'compare' => '=',
151 ],
152 ];
153 }
154
155 if ( 'custom' === ( $this->block->context['surecart/product-list/type'] ?? $this->block->parsed_block['attrs']['type'] ?? 'all' ) ) {
156 $query = $this->getQueryContext();
157 // backward compatibility.
158
159 $ids = ! empty( $query['include'] ) ? $query['include'] : ( ! empty( $this->block->context['surecart/product-list/ids'] ) ? $this->block->context['surecart/product-list/ids'] : ( ! empty( $this->block->parsed_block['attrs']['ids'] ) ? $this->block->parsed_block['attrs']['ids'] : [] ) );
160 $ids = is_array( $ids ) ? $ids : explode( ',', $ids );
161
162 // fallback for older strings - get the ids of legacy products.
163 $legacy_ids = [];
164 $ids_that_are_strings = array_map( 'sanitize_text_field', array_filter( $ids, 'is_string' ) );
165 if ( ! empty( $ids_that_are_strings ) ) {
166 $legacy_ids = get_posts(
167 [
168 'post_type' => 'sc_product',
169 'status' => 'publish',
170 'fields' => 'ids',
171 'posts_per_page' => -1,
172 'meta_query' => [
173 [
174 'key' => 'sc_id',
175 'value' => $ids_that_are_strings,
176 'compare' => 'IN',
177 ],
178 ],
179 ]
180 );
181 }
182
183 // get only ids that are integers.
184 $ids_that_are_integers = array_filter( $ids, 'is_int' );
185
186 // post in.
187 $query_vars['post__in'] = array_merge( $legacy_ids, $ids_that_are_integers );
188
189 // order by posts if there is not an order by.
190 if ( empty( $query_vars['orderby'] ) ) {
191 $query_vars['orderby'] = 'post__in';
192 }
193 }
194
195 return $query_vars;
196 }
197
198 /**
199 * Get the terms.
200 *
201 * @return array
202 */
203 public function getTermOptions( $taxonomy_slug = 'sc_collection' ) {
204 $taxonomy_slug = ! empty( $taxonomy_slug ) ? $taxonomy_slug : 'sc_collection';
205
206 // get non-empty terms.
207 $terms = get_terms(
208 array(
209 'taxonomy' => $taxonomy_slug,
210 'hide_empty' => true,
211 )
212 );
213
214 if ( is_wp_error( $terms ) ) {
215 return false;
216 }
217
218 // we are on a collection page.
219 $current_term = get_queried_object();
220 if ( is_a( $current_term, \WP_Term::class ) ) {
221 return false;
222 }
223
224 $url = \SureCart::block()->urlParams( 'products' );
225
226 $options = array_map(
227 function ( $term ) use ( $url, $taxonomy_slug ) {
228 return [
229 'value' => $term->slug,
230 'label' => $term->name,
231 'href' => $url->hasFilterArg( $taxonomy_slug, $term->slug ) ? $url->removeFilterArg( $taxonomy_slug, $term->slug ) : $url->addFilterArg( $taxonomy_slug, $term->slug ),
232 'checked' => $url->hasFilterArg( $taxonomy_slug, $term->slug ),
233 ];
234 },
235 $terms ?? []
236 );
237
238 // no filter options.
239 if ( empty( $options ) ) {
240 return false;
241 }
242
243 return $options;
244 }
245
246 /**
247 * Offset the found posts.
248 * See: https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination
249 *
250 * @param int $found_posts The found posts.
251 *
252 * @return int The found posts with offset.
253 */
254 public function offsetFoundPosts( $found_posts ) {
255 $query = $this->getQueryContext();
256 $offset = absint( $query['offset'] ?? 0 );
257
258 return $found_posts - $offset;
259 }
260
261 /**
262 * Run the query
263 *
264 * @return $this|\WP_Error
265 */
266 public function query() {
267 $query_vars = $this->parse_query();
268 wp_reset_postdata();
269
270 add_filter( 'found_posts', [ $this, 'offsetFoundPosts' ], 1 );
271 $this->query = new \WP_Query( $query_vars );
272 remove_filter( 'found_posts', [ $this, 'offsetFoundPosts' ], 1 );
273
274 $this->primeAttachmentCaches();
275
276 return $this;
277 }
278 }
279