PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.3.0
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.3.0
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 / flow / classes / class-cartflows-flow-post-type.php

class-cartflows-flow-post-type.php in CartFlows – Funnel Builder & Checkout Plugin for WooCommerce 3.3.0, at modules/flow/classes/class-cartflows-flow-post-type.php

380 lines 10.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Flow post type
4 *
5 * @package CartFlows
6 */
7
8 // Exit if accessed directly.
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12 /**
13 * Initialization
14 *
15 * @since 1.0.0
16 */
17 class Cartflows_Flow_Post_Type {
18
19
20 /**
21 * Member Variable
22 *
23 * @var instance
24 */
25 private static $instance;
26
27 /**
28 * Initiator
29 */
30 public static function get_instance() {
31 if ( ! isset( self::$instance ) ) {
32 self::$instance = new self();
33 }
34 return self::$instance;
35 }
36
37 /**
38 * Constructor
39 */
40 public function __construct() {
41
42 add_action( 'init', array( $this, 'flow_post_type' ) );
43
44 add_action( 'do_meta_boxes', array( $this, 'wcf_change_metabox_position' ) );
45
46 add_filter( 'post_updated_messages', array( $this, 'custom_post_type_post_update_messages' ) );
47
48 add_filter( 'display_post_states', array( $this, 'add_cartflows_post_state' ), 15, 1 );
49
50 add_filter( 'hidden_meta_boxes', array( $this, 'display_flow_slug_meta_box' ), 10, 2 );
51
52 /* View Post URL */
53 add_filter( 'post_row_actions', array( $this, 'post_row_actions' ), 10, 2 );
54 add_filter( 'preview_post_link', array( $this, 'preview_post_link' ), 10, 2 );
55 add_action( 'template_redirect', array( $this, 'redirect_to_step' ), 10 );
56 }
57
58 /**
59 * Add CartFlows post status.
60 *
61 * @param array $post_states post data.
62 * @return array
63 */
64 public function add_cartflows_post_state( $post_states ) {
65
66 global $post;
67
68 if ( isset( $post->post_type ) && CARTFLOWS_STEP_POST_TYPE === $post->post_type ) {
69
70 $flow_id = get_post_meta( $post->ID, 'wcf-flow-id', true );
71 $flow_title = get_the_title( $flow_id );
72
73 $post_states['cartflows_step'] = '( ' . __( 'Flow: ', 'cartflows' ) . $flow_id . ' | ' . __( 'Name: ', 'cartflows' ) . $flow_title . ')';
74
75 }
76
77 return $post_states;
78 }
79
80 /**
81 * Display slugdiv.
82 *
83 * @param array $hidden metaboxes.
84 * @param obj $screen screen.
85 * @return array
86 */
87 public function display_flow_slug_meta_box( $hidden, $screen ) {
88 $post_type = $screen->id;
89 if ( ! empty( $post_type ) && CARTFLOWS_FLOW_POST_TYPE === $post_type ) {
90 $pos = array_search( 'slugdiv', $hidden, true );
91
92 // array_search() returns false when slugdiv is not hidden, and unset( $hidden[ false ] )
93 // resolves to index 0 — which would un-hide an unrelated metabox.
94 if ( false !== $pos ) {
95 unset( $hidden[ $pos ] );
96 $hidden = array_values( $hidden );
97 }
98 }
99
100 return $hidden;
101 }
102
103 /**
104 * Create custom post type
105 */
106 public function flow_post_type() {
107
108 $labels = array(
109 'name' => esc_html_x( 'Flows', 'flow general name', 'cartflows' ),
110 'singular_name' => esc_html_x( 'Flow', 'flow singular name', 'cartflows' ),
111 'search_items' => esc_html__( 'Search Flows', 'cartflows' ),
112 'all_items' => esc_html__( 'All Flows', 'cartflows' ),
113 'edit_item' => esc_html__( 'Edit Flow', 'cartflows' ),
114 'view_item' => esc_html__( 'View Flow', 'cartflows' ),
115 'add_new' => esc_html__( 'Add New', 'cartflows' ),
116 'update_item' => esc_html__( 'Update Flow', 'cartflows' ),
117 'add_new_item' => esc_html__( 'Add New', 'cartflows' ),
118 'new_item_name' => esc_html__( 'New Flow Name', 'cartflows' ),
119 );
120
121 $args = array(
122 'labels' => $labels,
123 'show_in_menu' => false,
124 'public' => false, // it's not public, not own permalink.
125 'publicly_queryable' => false, // Prevent unauthenticated flow enumeration.
126 'show_ui' => true,
127 'query_var' => true,
128 'can_export' => true,
129 'show_in_admin_bar' => false,
130 'exclude_from_search' => true,
131 'has_archive' => false, // it shouldn't have archive page.
132 'rewrite' => false, // it shouldn't have rewrite rules.
133 'supports' => array( 'title', 'thumbnail', 'slug' ),
134 'capability_type' => 'post',
135 );
136
137 if ( ! _is_cartflows_pro() ) {
138
139 $flow_posts = get_posts(
140 array(
141 'posts_per_page' => 4,
142 'post_type' => CARTFLOWS_FLOW_POST_TYPE,
143 'post_status' => array( 'publish', 'pending', 'draft', 'future', 'private' ),
144 )
145 );
146
147 if ( is_array( $flow_posts ) ) {
148
149 $flow_count = count( $flow_posts );
150
151 if ( $flow_count > 3 || 3 === $flow_count ) {
152
153 $args['capabilities'] = array(
154 'create_posts' => 'do_not_allow',
155 );
156 $args['map_meta_cap'] = true;
157
158 // Add new notice button.
159 add_action( 'admin_print_footer_scripts', array( $this, 'add_new_notice_button' ) );
160
161 // Add the notice popup HTML to admin footer.
162 add_action( 'admin_footer', array( $this, 'upgrade_to_pro_notice_popup' ) );
163 }
164 }
165 }
166
167 register_post_type( CARTFLOWS_FLOW_POST_TYPE, $args );
168 }
169
170 /**
171 * Show custom add new button.
172 */
173 public function add_new_notice_button() {
174
175 $screen = get_current_screen();
176
177 if ( is_object( $screen ) && CARTFLOWS_FLOW_POST_TYPE === $screen->post_type && 'edit-cartflows_flow' === $screen->id ) {
178 ?>
179 <script>
180 jQuery('.wrap h1.wp-heading-inline').after('<a type="button" class="wcf-custom-add-new-button button">Add New</a>');
181 </script>
182 <?php
183 }
184 }
185
186 /**
187 * Upgrade to pro notice popup.
188 *
189 * @since 1.3.4
190 *
191 * @return void
192 */
193 public function upgrade_to_pro_notice_popup() {
194
195 ?>
196 <div id="cartflows-upgrade-notice-overlay" style="display:none;"></div>
197 <div id="cartflows-upgrade-notice-popup" style="display:none;">
198 <div class="inner">
199 <div class="heading">
200 <span><?php esc_html_e( 'Upgrade to CartFlows Pro', 'cartflows' ); ?></span>
201 <span class="cartflows-close-popup-button tb-close-icon"></span>
202 </div>
203 <div class="contents">
204 <div class="wcf-notice">
205 <p>Upgrade to CartFlows Pro for adding more flows and other features. <a href ="<?php echo esc_url( \Cartflows_Helper::get_upgrade_to_pro_link( '', 'https://cartflows.com/' ) ); ?>" target="_blank"> Click here</a> to upgrade.</p>
206 </div>
207 </div>
208 </div>
209 </div>
210 <?php
211 }
212
213 /**
214 * Change metabox position.
215 */
216 public function wcf_change_metabox_position() {
217
218 remove_meta_box( 'slugdiv', CARTFLOWS_FLOW_POST_TYPE, 'normal' );
219 add_meta_box( 'slugdiv', __( 'Slug', 'cartflows' ), 'post_slug_meta_box', CARTFLOWS_FLOW_POST_TYPE, 'side', 'high' );
220 }
221
222 /**
223 * Add post raw actions
224 *
225 * @param array $actions actions.
226 * @param array $post post data.
227 * @return array
228 */
229 public function post_row_actions( $actions, $post ) {
230
231 $first_step = $this->get_first_step_url( $post );
232
233 if ( $first_step && isset( $actions['view'] ) ) {
234
235 $actions['view'] = '<a href="' . $first_step . '">' . __( 'View', 'cartflows' ) . '</a>';
236 }
237
238 return $actions;
239 }
240
241 /**
242 * Returns previous post link
243 *
244 * @param string $prev_link previous link.
245 * @param array $post post data.
246 * @return string
247 */
248 public function preview_post_link( $prev_link, $post ) {
249
250 if ( $this->is_flow_post_type( $post ) ) {
251
252 $first_step = $this->get_first_step_url( $post );
253
254 if ( $first_step ) {
255
256 return $first_step;
257 }
258
259 return '';
260 }
261
262 return $prev_link;
263 }
264
265 /**
266 * Check if post type is flow
267 *
268 * @param array $post post data.
269 * @return bool
270 */
271 public function is_flow_post_type( $post ) {
272
273 if ( isset( $post ) && CARTFLOWS_FLOW_POST_TYPE === $post->post_type ) {
274
275 return true;
276 }
277
278 return false;
279 }
280
281 /**
282 * Redirect to first step
283 *
284 * @return void
285 */
286 public function redirect_to_step() {
287
288 global $post;
289
290 $flow = $post;
291
292 // The flow post type is not publicly queryable, so WP drops the query var — resolve the legacy funnel URL by slug.
293 if ( ! $this->is_flow_post_type( $flow ) && ! empty( $_GET[ CARTFLOWS_FLOW_POST_TYPE ] ) && is_string( $_GET[ CARTFLOWS_FLOW_POST_TYPE ] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
294 $slug = sanitize_title( wp_unslash( $_GET[ CARTFLOWS_FLOW_POST_TYPE ] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
295 $flow_obj = ! empty( $slug ) ? get_page_by_path( $slug, OBJECT, CARTFLOWS_FLOW_POST_TYPE ) : null;
296
297 if ( $flow_obj instanceof WP_Post && 'publish' === $flow_obj->post_status ) {
298 $flow = $flow_obj;
299 }
300 }
301
302 $first_step = $this->get_first_step_url( $flow );
303
304 if ( $first_step ) {
305
306 wp_safe_redirect( $first_step );
307 exit;
308 }
309 }
310
311 /**
312 * Return first step URL
313 *
314 * @param array $post post data.
315 * @return bool
316 */
317 public function get_first_step_url( $post ) {
318
319 if ( $this->is_flow_post_type( $post ) ) {
320
321 $flow_id = $post->ID;
322 $title = $post->post_title;
323 $steps = get_post_meta( $flow_id, 'wcf-steps', true );
324
325 if ( is_array( $steps ) && ! empty( $steps ) && isset( $steps[0]['id'] ) ) {
326
327 return get_permalink( $steps[0]['id'] );
328 }
329 }
330
331 return false;
332 }
333
334 /**
335 * Add Update messages for any custom post type
336 *
337 * @param array $messages Array of default messages.
338 */
339 public function custom_post_type_post_update_messages( $messages ) {
340
341 $custom_post_type = get_post_type( get_the_ID() );
342
343 if ( CARTFLOWS_FLOW_POST_TYPE == $custom_post_type ) {
344
345 $obj = get_post_type_object( $custom_post_type );
346 $singular_name = $obj->labels->singular_name;
347 $messages[ $custom_post_type ] = array(
348 0 => '', // Unused. Messages start at index 1.
349 /* translators: %s: singular custom post type name */
350 1 => sprintf( __( '%s updated.', 'cartflows' ), $singular_name ),
351 /* translators: %s: singular custom post type name */
352 2 => sprintf( __( 'Custom %s updated.', 'cartflows' ), $singular_name ),
353 /* translators: %s: singular custom post type name */
354 3 => sprintf( __( 'Custom %s deleted.', 'cartflows' ), $singular_name ),
355 /* translators: %s: singular custom post type name */
356 4 => sprintf( __( '%s updated.', 'cartflows' ), $singular_name ),
357 /* translators: %1$s: singular custom post type name ,%2$s: date and time of the revision */
358 5 => isset( $_GET['revision'] ) ? sprintf( __( '%1$s restored to revision from %2$s', 'cartflows' ), $singular_name, wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, //phpcs:ignore WordPress.Security.NonceVerification.Recommended
359 /* translators: %s: singular custom post type name */
360 6 => sprintf( __( '%s published.', 'cartflows' ), $singular_name ),
361 /* translators: %s: singular custom post type name */
362 7 => sprintf( __( '%s saved.', 'cartflows' ), $singular_name ),
363 /* translators: %s: singular custom post type name */
364 8 => sprintf( __( '%s submitted.', 'cartflows' ), $singular_name ),
365 /* translators: %s: singular custom post type name */
366 9 => sprintf( __( '%s scheduled for.', 'cartflows' ), $singular_name ),
367 /* translators: %s: singular custom post type name */
368 10 => sprintf( __( '%s draft updated.', 'cartflows' ), $singular_name ),
369 );
370 }
371
372 return $messages;
373 }
374 }
375
376 /**
377 * Kicking this off by calling 'get_instance()' method
378 */
379 Cartflows_Flow_Post_Type::get_instance();
380