PluginProbe ʕ •ᴥ•ʔ
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments / 4.6.0
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments v4.6.0
4.6.1 4.6.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 / Concerns / StripsPrivateCatalogFields.php
surecart / app / src / Concerns Last commit date
Arrayable.php 4 years ago HasBlockTheme.php 4 years ago Objectable.php 1 year ago RestrictsAnonymousReads.php 5 days ago SanitizesRestParams.php 2 months ago StripsPrivateCatalogFields.php 5 days ago
StripsPrivateCatalogFields.php
231 lines
1 <?php
2
3 namespace SureCart\Concerns;
4
5 /**
6 * Strips private catalog data from view/embed REST responses in places
7 * the item schema can't reach — expanded sub-objects.
8 */
9 trait StripsPrivateCatalogFields {
10 /**
11 * Strip the given private fields from a catalog response array.
12 *
13 * @param array $data Response data.
14 * @param array $fields Default field keys to strip.
15 * @param string $type Catalog object type the fields belong to.
16 *
17 * @return array
18 */
19 private function stripPrivateFields( $data, $fields, $type ) {
20 /**
21 * Filters the private field keys stripped from view/embed catalog
22 * REST responses.
23 *
24 * WARNING: this is a security control. These endpoints proxy the
25 * private platform API with the store's secret token — removing a
26 * key from this list re-exposes private platform data (stock, skus,
27 * metadata, offer internals, customer PII) to anonymous callers.
28 *
29 * @param array $fields Field keys stripped from the response.
30 * @param string $type Catalog object type (product, variant, price, review, product_collection).
31 * @param array $data The response data being stripped.
32 */
33 $fields = apply_filters( 'surecart/rest/private_catalog_fields', $fields, $type, $data );
34
35 foreach ( (array) $fields as $field ) {
36 unset( $data[ $field ] );
37 }
38
39 return $data;
40 }
41
42 /**
43 * Strip private fields from a product array.
44 *
45 * Covers fields the products schema strips at the top level, so it can
46 * also be applied to products expanded on other resources (e.g. prices).
47 *
48 * @param array|mixed $product Product response data. Non-arrays pass through untouched.
49 *
50 * @return array|mixed
51 */
52 protected function stripPrivateProductFields( $product ) {
53 if ( ! is_array( $product ) ) {
54 return $product;
55 }
56
57 $product = $this->stripPrivateFields(
58 $product,
59 [
60 // private sub-objects — never for anonymous callers.
61 'commission_structure',
62 'downloads',
63 'current_release_download',
64 'files',
65 'shipping_profile',
66 // internals the schema strips on the products endpoint.
67 // metrics stays — the product list renders price ranges from it.
68 'available_stock',
69 'held_stock',
70 'stock',
71 'status',
72 'archived',
73 'archived_at',
74 'discarded_at',
75 'cataloged_at',
76 'sku',
77 'metadata',
78 'dimensions',
79 'weight',
80 'weight_unit',
81 'tax_category',
82 'tax_enabled',
83 'purchase_limit',
84 ],
85 'product'
86 );
87
88 if ( ! empty( $product['variants']['data'] ) && is_array( $product['variants']['data'] ) ) {
89 $product['variants']['data'] = array_map( [ $this, 'stripPrivateVariantFields' ], $product['variants']['data'] );
90 }
91
92 if ( ! empty( $product['prices']['data'] ) && is_array( $product['prices']['data'] ) ) {
93 $product['prices']['data'] = array_map( [ $this, 'stripPrivatePriceFields' ], $product['prices']['data'] );
94 }
95
96 if ( ! empty( $product['reviews']['data'] ) && is_array( $product['reviews']['data'] ) ) {
97 $product['reviews']['data'] = array_map( [ $this, 'stripPrivateReviewFields' ], $product['reviews']['data'] );
98 }
99
100 if ( ! empty( $product['product_collections']['data'] ) && is_array( $product['product_collections']['data'] ) ) {
101 $product['product_collections']['data'] = array_map( [ $this, 'stripPrivateCollectionFields' ], $product['product_collections']['data'] );
102 }
103
104 // accessor-derived copies (Model::toArray appends every get*Attribute) leak the same fields.
105 foreach ( [ 'active_prices', 'active_ad_hoc_prices' ] as $key ) {
106 if ( ! empty( $product[ $key ] ) && is_array( $product[ $key ] ) ) {
107 $product[ $key ] = array_map( [ $this, 'stripPrivatePriceFields' ], $product[ $key ] );
108 }
109 }
110
111 if ( ! empty( $product['in_stock_variants'] ) && is_array( $product['in_stock_variants'] ) ) {
112 $product['in_stock_variants'] = array_map( [ $this, 'stripPrivateVariantFields' ], $product['in_stock_variants'] );
113 }
114
115 if ( ! empty( $product['initial_price'] ) ) {
116 $product['initial_price'] = $this->stripPrivatePriceFields( $product['initial_price'] );
117 }
118
119 foreach ( [ 'initial_variant', 'first_variant_with_stock' ] as $key ) {
120 if ( ! empty( $product[ $key ] ) ) {
121 $product[ $key ] = $this->stripPrivateVariantFields( $product[ $key ] );
122 }
123 }
124
125 return $product;
126 }
127
128 /**
129 * Strip private fields from a variant array.
130 *
131 * @param array|mixed $variant Variant response data. Non-arrays pass through untouched.
132 *
133 * @return array|mixed
134 */
135 protected function stripPrivateVariantFields( $variant ) {
136 if ( ! is_array( $variant ) ) {
137 return $variant;
138 }
139
140 return $this->stripPrivateFields(
141 $variant,
142 [
143 'available_stock',
144 'held_stock',
145 'stock',
146 'sku',
147 'metadata',
148 'dimensions',
149 'weight',
150 'weight_unit',
151 // signed download urls — never for anonymous callers.
152 'downloads',
153 'current_release_download',
154 ],
155 'variant'
156 );
157 }
158
159 /**
160 * Strip private fields from a price array.
161 *
162 * Keeps scratch_amount — the storefront renders it as the compare-at price.
163 *
164 * @param array|mixed $price Price response data. Non-arrays pass through untouched.
165 *
166 * @return array|mixed
167 */
168 protected function stripPrivatePriceFields( $price ) {
169 if ( ! is_array( $price ) ) {
170 return $price;
171 }
172
173 return $this->stripPrivateFields(
174 $price,
175 [
176 'metadata',
177 'archived_at',
178 'discarded_at',
179 ],
180 'price'
181 );
182 }
183
184 /**
185 * Strip customer PII and purchase internals from a review array.
186 *
187 * @param array|mixed $review Review response data. Non-arrays pass through untouched.
188 *
189 * @return array|mixed
190 */
191 protected function stripPrivateReviewFields( $review ) {
192 if ( ! is_array( $review ) ) {
193 return $review;
194 }
195
196 return $this->stripPrivateFields(
197 $review,
198 [
199 'customer',
200 'purchase',
201 ],
202 'review'
203 );
204 }
205
206 /**
207 * Strip private fields from a product collection array.
208 *
209 * Covers the fields the collections schema makes edit-only, so it can
210 * also be applied to collections expanded on products.
211 *
212 * @param array|mixed $collection Product collection response data. Non-arrays pass through untouched.
213 *
214 * @return array|mixed
215 */
216 protected function stripPrivateCollectionFields( $collection ) {
217 if ( ! is_array( $collection ) ) {
218 return $collection;
219 }
220
221 return $this->stripPrivateFields(
222 $collection,
223 [
224 'metadata',
225 'archived_at',
226 ],
227 'product_collection'
228 );
229 }
230 }
231