PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.1.1
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.1.1
3.3.0 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 trunk 1.0.4 1.1.0 1.1.0.1 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 All 162 releases
cartflows / modules / bricks / class-cartflows-bricks-dynamic-data.php

class-cartflows-bricks-dynamic-data.php in CartFlows – Funnel Builder & Checkout Plugin for WooCommerce 3.1.1, at modules/bricks/class-cartflows-bricks-dynamic-data.php

254 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cartflows Bricks Dynamic Data.
4 *
5 * @package Cartflows
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly.
10 }
11
12 /**
13 * This class handles bricks dynamic data functionality.
14 */
15 class Cartflows_Bricks_Dynamic_Data {
16 /**
17 * Member Variable
18 *
19 * @var object instance
20 */
21 private static $instance;
22
23 /**
24 * Initiator
25 *
26 * @return object instance
27 */
28 public static function get_instance() {
29 if ( ! isset( self::$instance ) ) {
30 self::$instance = new self();
31 }
32 return self::$instance;
33 }
34
35 /**
36 * Setup actions and filters.
37 *
38 * @since 1.6.13
39 */
40 private function __construct() {
41 add_filter( 'bricks/dynamic_tags_list', array( $this, 'dynamic_tags' ), 10 );
42 add_filter( 'bricks/dynamic_data/render_tag', array( $this, 'get_the_tag_value' ), 10, 3 );
43 add_filter( 'bricks/frontend/render_data', array( $this, 'render' ), 10, 3 );
44 add_filter( 'bricks/dynamic_data/render_content', array( $this, 'render' ), 10, 3 );
45 }
46
47 /**
48 * Register Tags.
49 *
50 * @param array $tags Existing tags.
51 *
52 * @return array
53 */
54 public function dynamic_tags( $tags = array() ) {
55 $cartflows_tags = apply_filters(
56 'cartflows_bricks_dynamic_tags_list',
57 array(
58 array(
59 'slug' => 'wcf_next_step',
60 'name' => '{wcf_next_step}',
61 'label' => esc_html__( 'Next Step', 'cartflows' ),
62 'group' => esc_html__( 'CartFlows', 'cartflows' ),
63 ),
64 )
65 );
66 return array_merge( $tags, $cartflows_tags );
67 }
68
69 /**
70 * Parse tag
71 *
72 * @param string $name Tag name.
73 * @param object $post Post object.
74 * @return string
75 */
76 public function parse_tag( $name, $post ) {
77 switch ( $name ) {
78 case 'wcf_next_step':
79 return '?class=wcf-next-step';
80 }
81 $name = apply_filters( 'cartflows_bricks_dynamic_data_render_tag', $name, $post );
82 return $name;
83 }
84
85 /**
86 * Dynamic tag exists in $content: Replaces dynamic tag with requested data.
87 *
88 * @param string $content Content.
89 * @param WP_Post $post Post object.
90 * @param string $context Context.
91 *
92 * @return string
93 */
94 public function render( $content, $post, $context = 'text' ) {
95
96 if ( ! wcf()->utils->is_step_post_type() ) {
97 return $content;
98 }
99
100 /**
101 * \w: Matches any word character (alphanumeric & underscore).
102 * Equivalent to [A-Za-z0-9_]
103 * "À-ÖØ-öø-ÿ" Add the accented characters
104 * "-" Needed because some post types handles are like "my-post-type"
105 * ":" Needed for extra arguments to dynamic data tags (e.g. post_excerpt:20 or wp_user_meta:my_meta_key)
106 * "|" and "," needed for the post terms like {post_terms_post_tag:sep} where sep could be a pipe or comma
107 * "(", ")" and "'" for the function arguments of the dynamic tag {echo}
108 * "@" to support email addresses as arguments of the dynamic tag {echo} #3kazphp
109 *
110 * @since 1.9.4: "u" modifier: Pattern strings are treated as UTF-8 to support Cyrillic, Arabic, etc.
111 * @since 1.10: "$", "+", "%", "#", "!", "=", "<", ">", "&", "~", "[", "]", ";" as arguments of the dynamic tag {echo}
112 *
113 * @see https://regexr.com/
114 */
115 $pattern = '/{([\wÀ-ÖØ-öø-ÿ\-\s\.\/:\(\)\'@|,$%#!+=<>&~\[\];]+)}/u';
116
117 /**
118 * Matches the echo tag pattern (#86bwebj6m)
119 *
120 * @since 1.9.8
121 */
122 $echo_pattern = '/echo:([a-zA-Z0-9_]+)/';
123
124 // Get a list of tags to exclude from the Dynamic Data logic.
125 $exclude_tags = apply_filters( 'bricks/dynamic_data/exclude_tags', array() ); // phpcs:ignore
126
127 /**
128 * STEP: Determine how many times we need to run the DD parser
129 *
130 * Previously we ran the parser by counting the number of open curly braces in the content. (@since 1.8)
131 * But this is not reliable because the content could contain curly braces in the code elements or any shortcodes.
132 * Causing the website to load extremely slow.
133 *
134 * @since 1.8.2 (#862jyyryg)
135 */
136 // Get all registered tags except the excluded ones.
137 // Example: [0 => "post_title", 1 => "woo_product_price", 2 => "echo"].
138 $registered_tags = array_filter(
139 array_column( $this->dynamic_tags(), 'slug' ),
140 function ( $tag ) use ( $exclude_tags ) {
141 return ! in_array( $tag, $exclude_tags, true );
142 }
143 );
144
145 $dd_tags_in_content = array();
146 $dd_tags_found = array();
147 $echo_tags_found = array();
148
149 // Find all dynamic data tags in the content.
150 preg_match_all( $pattern, $content, $dd_tags_in_content );
151
152 $dd_tags_in_content = ! empty( $dd_tags_in_content[1] ) ? $dd_tags_in_content[1] : array();
153
154 // Find all echo tags in the content.
155 preg_match_all( $echo_pattern, $content, $echo_tags_found );
156
157 // Combine the dynamic data tags from the content and the echo tags.
158 if ( ! empty( $echo_tags_found[0] ) ) {
159 $dd_tags_in_content = array_merge( $dd_tags_in_content, $echo_tags_found[0] );
160 }
161
162 if ( ! empty( $dd_tags_in_content ) ) {
163 /**
164 * $dd_tags_in_content only matches the pattern, but some codes from Code element could match the pattern too.
165 * Example: function test() { return 'Hello World'; } will match the pattern, but it's not a dynamic data tag.
166 *
167 * Find all dynamic data tags in the content which starts with dynamic data tag from $registered_tags
168 * Cannot use array_in or array_intersect because $registered_tags only contains the tag name, somemore tags could have filters like {echo:my_function( 'Hello World' )
169 *
170 * Example: $registered_tags = [0 => "post_title", 1 => "woo_product_price", 2 => "echo"]
171 * Example: $dd_tags_in_content = [0 => "post_title", 1 => "woo_product_price:value", 2 => "echo:my_function('Hello World')"]
172 */
173 $dd_tags_found = array_filter(
174 $dd_tags_in_content,
175 function ( $tag ) use ( $registered_tags ) {
176 foreach ( $registered_tags as $all_tag ) {
177 /**
178 * Skip not our tags.
179 */
180 if ( strpos( $tag, 'wcf_' ) === 0 ) {
181 return true;
182 }
183
184 if ( strpos( $tag, $all_tag ) === 0 ) {
185 return true;
186 }
187 }
188 return false;
189 }
190 );
191 }
192
193 // Get the count of found dynamic data tags.
194 $dd_tag_count = count( $dd_tags_found );
195
196 // STEP: Run the parser based on the count of found dynamic data tags.
197 for ( $i = 0; $i < $dd_tag_count; $i++ ) {
198 preg_match_all( $pattern, $content, $matches );
199
200 if ( empty( $matches[0] ) ) {
201 return $content;
202 }
203
204 foreach ( $matches[1] as $key => $match ) {
205 $tag = $matches[0][ $key ];
206
207 if ( in_array( $match, $exclude_tags, true ) ) {
208 continue;
209 }
210
211 $value = $this->get_the_tag_value( $match, $post, $content );
212 $content = str_replace( $tag, $value, $content );
213 }
214 ++$dd_tag_count;
215 }
216
217 return $content;
218 }
219
220 /**
221 * Main function to render the tag value for WooCommerce provider
222 *
223 * @param string $tag Tag name.
224 * @param object $post Post object.
225 * @param string $context The Tag context.
226 *
227 * @return string
228 */
229 public function get_the_tag_value( $tag, $post, $context ) {
230
231 if ( ! wcf()->utils->is_step_post_type() ) {
232 return $tag;
233 }
234
235 // Get all the registered tags and check if the tag exists.
236 $registered_tags = $this->dynamic_tags();
237
238 $tag_slug = strtok( $tag, ':' );
239
240 if ( ! in_array( $tag_slug, array_column( $registered_tags, 'slug' ), true ) ) {
241 return $tag;
242 }
243
244 // Return the parsed tag value.
245 return $this->parse_tag( $tag, $post );
246 }
247
248 }
249
250 /**
251 * Initiate the class.
252 */
253 Cartflows_Bricks_Dynamic_Data::get_instance();
254