PluginProbe
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More / 1.9.1
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More v1.9.1
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 / classes / attribute.php

attribute.php in StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More 1.9.1, at includes/classes/attribute.php

309 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace StoreEngine\Classes;
4
5 use StoreEngine\Classes\Exceptions\StoreEngineException;
6 use StoreEngine\Database;
7 use StoreEngine\Utils\Formatting;
8 use StoreEngine\Utils\Helper;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit;
12 }
13
14 class Attribute {
15
16 protected int $id;
17 protected string $table;
18
19 protected array $data = [
20 'attribute_name' => '',
21 'attribute_label' => '',
22 'attribute_type' => 'select',
23 'attribute_orderby' => '',
24 'attribute_public' => 0,
25 ];
26 protected array $new_data = [];
27
28 public const CACHE_KEY = 'storeengine_attribute_';
29 public const CACHE_GROUP = 'storeengine_attributes';
30
31 public function __construct( int $id = 0 ) {
32 global $wpdb;
33 $this->id = $id;
34 $this->table = $wpdb->prefix . Helper::DB_PREFIX . 'attribute_taxonomies';
35 }
36
37 public function get() {
38 global $wpdb;
39
40 $has_cache = wp_cache_get( self::CACHE_KEY . $this->get_id(), self::CACHE_GROUP );
41 if ( $has_cache ) {
42 return $this->set_data( $has_cache );
43 }
44
45 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.DirectDatabaseQuery.DirectQuery
46 $result = $wpdb->get_row( $wpdb->prepare(
47 "SELECT * FROM $this->table WHERE attribute_id = %d", $this->get_id()
48 ) );
49 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.DirectDatabaseQuery.DirectQuery
50
51 if ( ! $result ) {
52 return false;
53 }
54 wp_cache_set( self::CACHE_KEY . $this->get_id(), $result, self::CACHE_GROUP );
55
56 return $this->set_data( $result );
57 }
58
59 public function set_data( $data ): Attribute {
60 $this->id = $data->attribute_id;
61 $this->data['attribute_name'] = $data->attribute_name;
62 $this->data['attribute_label'] = $data->attribute_label;
63 $this->data['attribute_type'] = $data->attribute_type;
64 $this->data['attribute_orderby'] = $data->attribute_orderby;
65 $this->data['attribute_public'] = $data->attribute_public;
66
67 return $this;
68 }
69
70 public function save() {
71 global $wpdb;
72 $data = array_merge( $this->data, $this->new_data );
73 $formatter = [ '%s', '%s', '%s', '%s', '%d' ];
74
75 $taxonomy = Database::register_attribute_taxonomy( $this->get_name(), $this->get_label(), $this->is_public() );
76
77 // Early bail if taxonomy can't be registered.
78 if ( is_wp_error( $taxonomy ) ) {
79 throw StoreEngineException::from_wp_error( $taxonomy ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
80 }
81
82 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
83 if ( 0 === $this->get_id() ) {
84 $wpdb->insert( $this->table, $data, $formatter );
85 $this->id = $wpdb->insert_id;
86 } else {
87 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
88 $wpdb->update( $this->table, $data, [ 'attribute_id' => $this->get_id() ], $formatter, [ '%d' ] );
89 wp_cache_delete( self::CACHE_KEY . $this->id, self::CACHE_GROUP );
90 }
91 // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery
92 wp_cache_flush_group( self::CACHE_GROUP );
93 wp_cache_flush_group( AbstractProduct::CACHE_GROUP );
94 wp_cache_flush_group( $taxonomy->name . '_relationships' );
95 wp_cache_set_terms_last_changed();
96 }
97
98 public function delete(): bool {
99 if ( 0 === $this->get_id() ) {
100 return false;
101 }
102
103 $taxonomy = $this->get_taxonomy_name();
104 $terms = $this->get_terms();
105 $deleted_terms = [];
106 foreach ( $terms as $term ) {
107 $result = wp_delete_term( $term->term_id, $taxonomy );
108 if ( ! is_wp_error( $result ) ) {
109 $deleted_terms[] = $term->term_id;
110 }
111 }
112
113 global $wpdb;
114 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
115 if ( ! empty( $deleted_terms ) ) {
116 $deleted_terms_placeholders = implode( ',', array_fill( 0, count( $deleted_terms ), '%d' ) );
117 $variation_ids = $wpdb->get_results(
118 $wpdb->prepare(
119 "SELECT variation_id FROM {$wpdb->prefix}storeengine_variation_term_relations WHERE term_id in ($deleted_terms_placeholders)",
120 ...$deleted_terms
121 )
122 );
123
124 $this->delete_variation( array_map( fn( $v ) => $v->variation_id, $variation_ids ) );
125
126 $wpdb->query(
127 $wpdb->prepare(
128 "DELETE FROM {$wpdb->prefix}storeengine_variation_term_relations WHERE term_id in ($deleted_terms_placeholders)",
129 ...$deleted_terms,
130 )
131 );
132 }
133
134
135 $res = $wpdb->delete( $this->table, [ 'attribute_id' => $this->id ], [ '%d' ] );
136 // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
137
138 if ( ! $res ) {
139 return false;
140 }
141
142 wp_cache_delete( self::CACHE_KEY . $this->id, self::CACHE_GROUP );
143 wp_cache_flush_group( self::CACHE_GROUP );
144 wp_cache_flush_group( AbstractProduct::CACHE_GROUP );
145
146 return true;
147 }
148
149 public function get_id(): int {
150 return $this->id;
151 }
152
153 public function get_name() {
154 return $this->get_prop( 'attribute_name' );
155 }
156
157 public function get_taxonomy_name(): string {
158 return Helper::get_attribute_taxonomy_name( $this->get_name() );
159 }
160
161 public function get_label() {
162 return $this->get_prop( 'attribute_label' );
163 }
164
165 public function get_type() {
166 return $this->get_prop( 'attribute_type' );
167 }
168
169 public function get_orderby() {
170 return $this->get_prop( 'attribute_orderby' );
171 }
172
173 public function get_terms( $args = [] ) {
174 $args = wp_parse_args( $args, [
175 'taxonomy' => $this->get_taxonomy_name(),
176 'hide_empty' => false,
177 'orderby' => $this->get_orderby(),
178 ] );
179 $terms = get_terms( $args );
180
181 return is_wp_error( $terms ) ? [] : $terms;
182 }
183
184 public function get_count() {
185 return wp_count_terms( $this->get_taxonomy_name() );
186 }
187
188 public function add_term( string $name, array $args = [] ) {
189 $args = wp_parse_args( $args, [
190 'slug' => '',
191 'description' => '',
192 'parent' => 0,
193 ] );
194
195 return wp_insert_term( $name, $this->get_taxonomy_name(), $args );
196 }
197
198 public function update_term( int $term_id, string $name, array $args = [] ) {
199 $args = wp_parse_args( $args, [
200 'slug' => '',
201 'description' => '',
202 'parent' => 0,
203 ] );
204
205 return wp_update_term(
206 $term_id,
207 $this->get_taxonomy_name(),
208 [
209 'name' => $name,
210 'slug' => $args['slug'],
211 'description' => $args['description'],
212 'parent' => $args['parent'],
213 ]
214 );
215 }
216
217 public function delete_term( int $term_id ) {
218 global $wpdb;
219
220 $result = wp_delete_term( $term_id, $this->get_taxonomy_name() );
221
222 if ( is_wp_error( $result ) ) {
223 return $result;
224 }
225
226 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
227 $variation_ids = $wpdb->get_results(
228 $wpdb->prepare(
229 "SELECT variation_id FROM {$wpdb->prefix}storeengine_variation_term_relations WHERE term_id = %d",
230 $term_id
231 )
232 );
233
234 $wpdb->query(
235 $wpdb->prepare(
236 "DELETE FROM {$wpdb->prefix}storeengine_variation_term_relations WHERE term_id = %d",
237 $term_id
238 )
239 );
240 // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
241
242 $this->delete_variation( array_map( fn( $v ) => $v->variation_id, $variation_ids ) );
243
244 return true;
245 }
246
247 public function is_public(): bool {
248 return Formatting::string_to_bool( $this->get_prop( 'attribute_public', false ) );
249 }
250
251 public function set_name( string $value ) {
252 $this->new_data['attribute_name'] = $value;
253 }
254
255 public function set_label( string $value ) {
256 $this->new_data['attribute_label'] = $value;
257 }
258
259 public function set_type( string $value ) {
260 $this->new_data['attribute_type'] = $value;
261 }
262
263 public function set_orderby( string $value ) {
264 $this->new_data['attribute_orderby'] = $value;
265 }
266
267 public function set_public( bool $value ) {
268 $this->new_data['attribute_public'] = $value;
269 }
270
271 protected function get_prop( string $name, $default = '' ) {
272 if ( array_key_exists( $name, $this->new_data ) ) {
273 return $this->new_data[ $name ];
274 }
275
276 return $this->data[ $name ] ?? $default;
277 }
278
279 /**
280 * @param array $variation_ids
281 *
282 * @return void
283 */
284 private function delete_variation( array $variation_ids ): void {
285 global $wpdb;
286
287 if ( empty( $variation_ids ) ) {
288 return;
289 }
290
291 $variation_ids_placeholders = implode( ',', array_fill( 0, count( $variation_ids ), '%d' ) );
292
293 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- Query prepared.
294 $wpdb->query(
295 $wpdb->prepare(
296 "DELETE FROM {$wpdb->prefix}storeengine_product_variations WHERE id in ($variation_ids_placeholders)",
297 ...$variation_ids,
298 )
299 );
300 $wpdb->query(
301 $wpdb->prepare(
302 "DELETE FROM {$wpdb->prefix}storeengine_product_variation_meta WHERE variation_id in ($variation_ids_placeholders)",
303 ...$variation_ids,
304 )
305 );
306 // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- Query prepared.
307 }
308 }
309