PluginProbe ʕ •ᴥ•ʔ
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments / 4.7.1
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments v4.7.1
4.7.2 4.7.1 4.7.0 4.6.6 4.6.5 4.6.4 4.6.3 4.6.2 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 / Models / Form.php
surecart / app / src / Models Last commit date
Blocks 1 day ago Concerns 7 months ago Traits 2 months ago Wordpress 1 year ago AbandonedCheckout.php 1 year ago AbandonedCheckoutProtocol.php 3 years ago Account.php 1 year ago AccountPortalSession.php 4 years ago Activation.php 1 year ago Affiliation.php 1 year ago AffiliationProduct.php 1 year ago AffiliationProtocol.php 2 years ago AffiliationRequest.php 1 year ago ApiToken.php 7 months ago AutoFee.php 7 months ago AutoFeeProtocol.php 7 months ago BalanceTransaction.php 1 year ago Batch.php 1 month ago Brand.php 5 months ago BulkAction.php 2 years ago Bump.php 1 year ago BundleItem.php 1 month ago BuyLink.php 2 years ago CancellationAct.php 1 year ago CancellationReason.php 3 years ago Charge.php 11 months ago Checkout.php 1 month ago Click.php 1 year ago Collection.php 4 months ago CommissionStructure.php 2 years ago Component.php 6 months ago Coupon.php 4 months ago Customer.php 2 months ago CustomerLink.php 4 years ago CustomerNotificationProtocol.php 4 years ago CustomerPortalProtocol.php 1 year ago DatabaseModel.php 4 months ago Discount.php 1 year ago DisplayCurrency.php 1 year ago Dispute.php 11 months ago Download.php 4 years ago Event.php 4 years ago Export.php 2 years ago ExternalApiModel.php 4 months ago Fee.php 1 year ago Form.php 1 day ago Fulfillment.php 1 week ago FulfillmentItem.php 1 year ago GalleryItem.php 11 months ago GalleryItemAttachment.php 6 months ago GalleryItemImageAttachment.php 4 months ago GalleryItemMedia.php 1 year ago GalleryItemProductMedia.php 2 months ago GalleryItemVideoAttachment.php 4 months ago Import.php 7 months ago ImportRow.php 3 months ago IncomingWebhook.php 1 year ago Integration.php 2 years ago IntegrationCatalog.php 1 month ago Invoice.php 1 year ago License.php 1 year ago LineItem.php 1 month ago ManualPaymentMethod.php 1 year ago Media.php 2 months ago Model.php 1 month ago ModelInterface.php 4 years ago Order.php 2 months ago OrderProtocol.php 4 years ago ParcelTemplate.php 1 week ago PaymentFailure.php 1 year ago PaymentInstrument.php 3 months ago PaymentIntent.php 1 year ago PaymentMethod.php 1 year ago Payout.php 1 year ago PayoutGroup.php 2 years ago Period.php 1 year ago PlatformFee.php 1 year ago PortalSession.php 4 years ago Price.php 8 months ago Processor.php 1 year ago Product.php 2 weeks ago ProductCollection.php 1 year ago ProductCollectionImport.php 7 months ago ProductGroup.php 1 year ago ProductImport.php 7 months ago ProductMedia.php 6 months ago Promotion.php 1 year ago ProvisionalAccount.php 3 months ago Purchase.php 2 years ago Referral.php 1 year ago ReferralItem.php 2 years ago Refund.php 1 year ago RefundItem.php 1 year ago RegisteredWebhook.php 3 months ago ReturnItem.php 2 years ago ReturnReason.php 2 years ago ReturnRequest.php 1 year ago Review.php 6 months ago ReviewProtocol.php 6 months ago RuleSchema.php 7 months ago ServiceFee.php 1 year ago Shipment.php 1 week ago ShippingChoice.php 1 year ago ShippingMethod.php 3 years ago ShippingProfile.php 3 years ago ShippingProtocol.php 3 years ago ShippingProviderType.php 1 week ago ShippingRate.php 3 years ago ShippingZone.php 3 years ago Statistic.php 4 years ago Subscription.php 2 months ago SubscriptionProtocol.php 4 years ago Swap.php 1 year ago TaxOverride.php 2 years ago TaxProtocol.php 4 years ago TaxRegistration.php 1 year ago TaxZone.php 4 years ago Upload.php 4 years ago Upsell.php 1 year ago UpsellFunnel.php 1 year ago User.php 4 weeks ago Variant.php 1 month ago VariantOption.php 2 years ago VariantOptionValue.php 1 year ago VariantValue.php 2 years ago VerificationCode.php 3 years ago Warehouse.php 1 week ago Webhook.php 1 year ago WebhookRegistration.php 2 years ago
Form.php
266 lines
1 <?php
2
3 namespace SureCart\Models;
4
5 use SureCart\Models\Product;
6
7 /**
8 * Checkout form class
9 */
10 class Form {
11 /**
12 * Holds the form post.
13 *
14 * @var \WP_Post;
15 */
16 protected $post;
17
18 /**
19 * Get the post
20 *
21 * @param [type] $id
22 */
23 final public function __construct( $id = 0 ) {
24 $this->post = get_post( $id );
25 }
26
27 /**
28 * The form's post type
29 *
30 * @return string The post type.
31 */
32 protected function getPostType() {
33 // TODO: get this from registration.
34 return 'sc_form';
35 }
36
37 /**
38 * Get the stored product choices
39 *
40 * @param int|WP_Post $id Post object or id.
41 * @return array
42 */
43 protected function getPriceIds( $id ) {
44 $this->post = get_post( $id );
45 $blocks = parse_blocks( $this->post->post_content );
46 return $this->getNested( $blocks, 'price_id' );
47 }
48
49 /**
50 * Get a form's attribute
51 *
52 * @param string $attribute Attribute name.
53 * @return mixed
54 */
55 public function getAttribute( $attribute ) {
56 $blocks = parse_blocks( $this->post->post_content );
57 $form_block = $blocks[0] ?? false;
58 if ( ! $form_block || 'surecart/form' !== $form_block['blockName'] ) {
59 return '';
60 }
61 return $form_block['attrs'][ $attribute ] ?? null;
62 }
63
64 /**
65 * Get the form's mode
66 *
67 * @param int|WP_Post $id Post object or id.
68 * @return string
69 */
70 protected function getMode( $id ) {
71 $this->post = get_post( $id );
72 if ( empty( $this->post ) ) {
73 return null;
74 }
75 $blocks = parse_blocks( $this->post->post_content );
76 $form_block = $blocks[0] ?? false;
77 if ( ! $form_block || 'surecart/form' !== $form_block['blockName'] ) {
78 return '';
79 }
80 return apply_filters( 'surecart/payments/mode', $form_block['attrs']['mode'] ?? 'live' );
81 }
82
83 /**
84 * Get nested values from an array
85 *
86 * @param array $array Array to search.
87 * @param string $nested_key Nested key to search for.
88 * @return array
89 */
90 protected function getNested( array $array, $nested_key ) {
91 $return = array();
92 array_walk_recursive(
93 $array,
94 function( $a, $key ) use ( &$return, $nested_key ) {
95 if ( $nested_key === $key ) {
96 $return[] = $a;
97 }
98 }
99 );
100 return $return;
101 }
102
103 /**
104 * Get the form's products.
105 *
106 * @param int|WP_Post Block post id.
107 */
108 protected function getProducts( $id ) {
109 $ids = $this->getPriceIds( $id );
110 // no products.
111 if ( empty( $ids ) ) {
112 return [];
113 }
114
115 // get prices with their product
116 $prices = Price::where(
117 [
118 'ids' => $ids,
119 ]
120 )->with( [ 'product' ] )->get();
121
122 $products = [];
123 foreach ( $prices as $price ) {
124 $products[] = $price->product;
125 }
126 return $products;
127 }
128
129 protected function getPosts( $id ) {
130 $blocks = $this->searchBlocks( $id );
131 $shortcodes = $this->searchShortcodes( $id );
132 return array_merge( $blocks, $shortcodes );
133 }
134
135 public function searchBlocks( $id ) {
136 return get_posts(
137 [
138 's' => '<!-- wp:surecart/checkout-form {"id":' . (int) $id,
139 'sentence' => 1,
140 'post_type' => 'any',
141 'per_page' => -1,
142 ]
143 );
144 }
145
146 public function searchShortcodes( $id ) {
147 return get_posts(
148 [
149 's' => '[sc_form id=' . (int) $id,
150 'sentence' => 1,
151 'post_type' => 'any',
152 'per_page' => -1,
153 ]
154 );
155 }
156
157 /**
158 * Get blocks from the posts.
159 *
160 * @param array $posts Array of posts.
161 * @return array Array of blocks.
162 */
163 public function getBlocksFromPosts( $posts ) {
164 $blocks = [];
165 foreach ( $posts as $post ) {
166 $parsed_blocks = parse_blocks( $post->post_content );
167 $blocks = array_merge( $blocks, $this->findCheckoutBlocks( $parsed_blocks, $post ) );
168 }
169 return array_filter( $blocks );
170 }
171
172 /**
173 * Find our checkout block.
174 *
175 * @param array $post_blocks Blocks array.
176 * @param \WP_Post $post_object Post object.
177 * @return array
178 */
179 public function findCheckoutBlocks( $post_blocks, \WP_Post $post_object ) {
180 $blocks = [];
181 foreach ( $post_blocks as $block ) {
182 if ( 'surecart/checkout-form' === $block['blockName'] ) {
183 $block['post'] = $post_object;
184 $blocks[] = $block;
185 } elseif ( ! empty( $block['innerBlocks'] ) ) {
186 $blocks = array_merge( $blocks, $this->findCheckoutBlocks( $block['innerBlocks'], $post_object ) );
187 }
188 }
189
190 return array_filter( $blocks );
191 }
192
193 /**
194 * Whether the current user can create checkout forms.
195 *
196 * @return boolean
197 */
198 protected function canCreate() {
199 $post_type = get_post_type_object( $this->getPostType() );
200 return $post_type && current_user_can( $post_type->cap->create_posts );
201 }
202
203 /**
204 * Duplicate a form as a new draft, including its content and meta.
205 *
206 * @param integer $id Source form post id.
207 *
208 * @return integer|\WP_Error New post id, or error when the source is invalid or the user lacks permission.
209 */
210 protected function duplicate( $id ) {
211 $this->post = get_post( $id );
212 if ( ! $this->post || $this->getPostType() !== $this->post->post_type ) {
213 return new \WP_Error( 'sc_form_not_found', __( 'Checkout form not found.', 'surecart' ), [ 'status' => 404 ] );
214 }
215
216 if ( ! $this->canCreate() || ! current_user_can( 'edit_post', $this->post->ID ) ) {
217 return new \WP_Error( 'sc_form_duplicate_forbidden', __( 'Sorry, you are not allowed to duplicate this checkout form.', 'surecart' ), [ 'status' => 403 ] );
218 }
219
220 // wp_insert_post() expects slashed data; block content holds \uXXXX escapes that would otherwise be stripped.
221 $new_id = wp_insert_post(
222 wp_slash(
223 [
224 'post_type' => $this->getPostType(),
225 'post_status' => 'draft',
226 /* translators: %s: original form title. */
227 'post_title' => sprintf( __( '%s (Copy)', 'surecart' ), $this->post->post_title ),
228 'post_content' => $this->post->post_content,
229 'post_excerpt' => $this->post->post_excerpt,
230 ]
231 ),
232 true
233 );
234
235 if ( is_wp_error( $new_id ) ) {
236 return $new_id;
237 }
238
239 foreach ( get_post_meta( $this->post->ID ) as $key => $values ) {
240 // editor locks are per-post state, not settings.
241 if ( in_array( $key, [ '_edit_lock', '_edit_last' ], true ) ) {
242 continue;
243 }
244 foreach ( $values as $value ) {
245 // keyless get_post_meta() returns raw serialized values; unserialize so add_post_meta() re-serializes
246 // cleanly, and slash because add_post_meta() unslashes string values before saving.
247 add_post_meta( $new_id, $key, wp_slash( maybe_unserialize( $value ) ) );
248 }
249 }
250
251 return $new_id;
252 }
253
254 /**
255 * Static Facade Accessor
256 *
257 * @param string $method Method to call.
258 * @param mixed $params Method params.
259 *
260 * @return mixed
261 */
262 public static function __callStatic( $method, $params ) {
263 return call_user_func_array( [ new static(), $method ], $params );
264 }
265 }
266