PluginProbe
HurryTimer – An Scarcity and Urgency Countdown Timer for WordPress & WooCommerce / 2.6.2
HurryTimer – An Scarcity and Urgency Countdown Timer for WordPress & WooCommerce v2.6.2
2.15.0 trunk 1.0.0 1.0.1 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1.2 2.1.3 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 All 62 releases
← All changes | includes/Frontend.php +142 -125 trunk2.6.2 View file →
@@ -10,9 +10,10 @@
10 10 *
11 11 * @package Hurrytimer
12 12 * @subpackage Hurrytimer/public
13 13 */
14 -class Frontend {
14 +class Frontend
15 +{
15 16 /**
16 17 * The ID of this plugin.
17 18 *
18 19 * @since 1.0.0
@@ -38,64 +39,71 @@
38 39 *
39 40 * @since 1.0.0
40 41 *
41 42 */
42 - public function __construct($plugin_name, $version) {
43 + public function __construct( $plugin_name, $version )
44 + {
43 45 $this->plugin_name = $plugin_name;
44 46 $this->version = $version;
45 47 }
46 48
47 - function init() {
49 + function init()
50 + {
48 51
49 52 // Enqueue CSS and JS.
50 - add_action('wp_enqueue_scripts', [$this, 'enqueue_styles']);
51 - add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']);
53 + add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_styles' ] );
54 + add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
52 55
53 56 // Display campaign in sticky bar.
54 - add_action('wp_footer', [$this, 'render_sticky_bar']);
55 - add_action('wp_footer', [$this, 'run_in_background']);
57 + add_action( 'wp_footer', [ $this, 'render_sticky_bar' ] );
58 + add_action( 'wp_footer', [ $this, 'run_in_background' ] );
56 59
57 60 // Display campaign on product page.
58 - add_action('wp', [$this, 'render_on_product_page']);
61 + add_action( 'wp', [ $this, 'render_on_product_page' ] );
59 62
63 + // Change stock status for recurring/onetime campaign via Ajax.
64 + add_action( 'wp_ajax_change_stock_status', [ $this, 'ajax_change_stock_status' ] );
65 + add_action( 'wp_ajax_nopriv_change_stock_status', [ $this, 'ajax_change_stock_status' ] );
66 +
60 67 // Log evergreen campaign start time for each visitor.
61 - add_action('wp_ajax_hurryt/update_timestamp', [$this, 'ajax_save_evergreen_start_time']);
62 - add_action('wp_ajax_nopriv_hurryt/update_timestamp', [$this, 'ajax_save_evergreen_start_time']);
68 + add_action( 'wp_ajax_hurryt/update_timestamp', [ $this, 'ajax_save_evergreen_start_time' ] );
69 + add_action( 'wp_ajax_nopriv_hurryt/update_timestamp', [ $this, 'ajax_save_evergreen_start_time' ] );
63 70
64 71 // Return next recurrence.
65 - add_action('wp_ajax_next_recurrence', [$this, 'ajax_next_recurrence']);
66 - add_action('wp_ajax_nopriv_next_recurrence', [$this, 'ajax_next_recurrence']);
72 + add_action( 'wp_ajax_next_recurrence', [ $this, 'ajax_next_recurrence' ] );
73 + add_action( 'wp_ajax_nopriv_next_recurrence', [ $this, 'ajax_next_recurrence' ] );
67 74
68 75 // Check before rendering campaign.
69 - add_action('hurryt_pre_render', [$this, 'pre_render_shortcode']);
76 + add_action( 'hurryt_pre_render', [ $this, 'pre_render_shortcode' ] );
70 77
71 78 // Check actions for expired recurring and onetime campaigns
72 79 // This only concerns shortcodes inserted in post editor.
73 80 // Fallback to shortcode callback
74 - add_action('wp', [$this, 'check_post_shortcode']);
81 + add_action( 'wp', [ $this, 'check_post_shortcode' ] );
82 +
75 83 }
76 84
77 - function run_in_background() {
85 + function run_in_background()
86 + {
78 87
79 88 // At this time, all campagins with the "Expire coupon" action
80 89 // should run in background.
81 - $campaigns = get_posts([
90 + $campaigns = get_posts( [
82 91 'post_type' => HURRYT_POST_TYPE,
83 92 'numberposts' => -1,
84 93 'post_status' => 'publish',
85 - ]);
94 + ] );
86 95
87 - foreach ($campaigns as $campaign) {
88 - $campaign = new Campaign($campaign->ID);
96 + foreach ( $campaigns as $campaign ) {
97 + $campaign = new Campaign( $campaign->ID );
89 98
90 99 $campaign->loadSettings();
91 - $action_expire_coupon = $campaign->get_action(C::ACTION_EXPIRE_COUPON);
92 - // $action_hide_atc_button = $campaign->get_action(C::ACTION_HIDE_ADD_TO_CART_BUTTON);
100 + $action = $campaign->get_action( C::ACTION_EXPIRE_COUPON );
93 101
94 - $run_in_background = !empty($action_expire_coupon);
95 - if ($run_in_background) {
96 - echo do_shortcode('[hurrytimer id=' . $campaign->get_id() . ' run_in_background=true]');
102 + if ( !empty( $action ) ) {
103 + echo do_shortcode( '[hurrytimer id=' . $campaign->get_id() . ' run_in_background=true]' );
97 104 }
105 +
98 106 }
99 107 }
100 108
101 109 /**
@@ -100,17 +108,17 @@
100 108
101 109 /**
102 110 * Check if there is shortcode in the current post.
103 111 */
104 - function check_post_shortcode() {
112 + function check_post_shortcode()
113 + {
105 114 global $post;
106 - if (
107 - is_singular() && is_a($post, 'WP_Post')
108 - && has_shortcode($post->post_content, 'hurrytimer') && !(defined('DOING_AJAX') && DOING_AJAX)
115 + if ( is_singular() && is_a( $post, 'WP_Post' )
116 + && has_shortcode( $post->post_content, 'hurrytimer' ) && !( defined( 'DOING_AJAX' ) && DOING_AJAX )
109 117 ) {
110 - $campaigns_ids = hurryt_parse_campaigns($post->post_content);
111 - foreach ($campaigns_ids as $id) {
112 - do_action('hurryt_pre_render', hurryt_get_campaign($id));
118 + $campaigns_ids = hurryt_parse_campaigns( $post->post_content );
119 + foreach ( $campaigns_ids as $id ) {
120 + do_action( 'hurryt_pre_render', hurryt_get_campaign( $id ) );
113 121 }
114 122 }
115 123 }
116 124
@@ -116,31 +124,31 @@
116 124
117 125 /**
118 126 * @param $campaign Campaign
119 127 */
120 - function pre_render_shortcode($campaign) {
121 - if ($campaign->is_running() && $campaign->is_expired()) {
122 - (new ActionManager($campaign))->run();
128 + function pre_render_shortcode( $campaign )
129 + {
130 + if ( $campaign->is_running() && $campaign->is_expired() ) {
131 + ( new ActionManager( $campaign ) )->run();
123 132 }
124 133 }
125 134
126 135
127 - public function ajax_next_recurrence() {
128 - check_ajax_referer('hurryt', 'nonce');
129 - $campaign_id = absint($_GET['id']);
130 - if (
131 - !get_post($campaign_id)
132 - || get_post_type($campaign_id) !== HURRYT_POST_TYPE
136 + public function ajax_next_recurrence()
137 + {
138 + check_ajax_referer( 'hurryt', 'nonce' );
139 + $campaign_id = absint( $_GET[ 'id' ] );
140 + if ( !get_post( $campaign_id )
141 + || get_post_type( $campaign_id ) !== HURRYT_POST_TYPE
133 142 ) {
134 - die(-1);
143 + die( -1 );
135 144 }
136 145
137 - $campaign = new Campaign($campaign_id);
146 + $campaign = new Campaign( $campaign_id );
138 147 $endDate = $campaign->getRecurrenceEndDate();
139 -
140 - wp_send_json_success([
148 + wp_send_json_success( [
141 149 'endTimestamp' => $endDate ? $endDate->getBrowserTimestamp() : null,
142 - ]);
150 + ] );
143 151 }
144 152
145 153 /**
146 154 * Uses ajax to save start time for the given visitor.
@@ -145,60 +153,64 @@
145 153 /**
146 154 * Uses ajax to save start time for the given visitor.
147 155 * This used to bypass cookie cache.
148 156 */
149 - public function ajax_save_evergreen_start_time() {
150 - check_ajax_referer('hurryt', 'nonce');
151 - if (!isset($_POST['timestamp']) || !isset($_POST['cid'])) {
157 + public function ajax_save_evergreen_start_time()
158 + {
159 + check_ajax_referer( 'hurryt', 'nonce' );
160 + if ( !isset( $_POST[ 'timestamp' ] ) || !isset( $_POST[ 'cid' ] ) ) {
152 161 wp_die();
153 162 }
154 163
155 - $cid = intval($_POST['cid']);
156 - $timestamp = filter_input(INPUT_POST, 'timestamp', FILTER_VALIDATE_INT);
157 -
158 - if (!$cid || $timestamp === false || $timestamp === null) {
159 - wp_die();
160 - }
161 -
162 - // Verify the campaign exists and is of the correct type.
163 - if (!get_post($cid) || get_post_type($cid) !== HURRYT_POST_TYPE) {
164 - wp_die();
165 - }
166 -
167 - $evergreen_campaign = new EvergreenCampaign($cid);
168 - $evergreen_campaign->setEndDate($timestamp);
169 - wp_die('Success!');
164 + $evergreen_campaign = new EvergreenCampaign( intval( $_POST[ 'cid' ] ) );
165 + $evergreen_campaign->setEndDate( filter_input( INPUT_POST, 'timestamp' ) );
166 + wp_die( 'Success!' );
170 167 }
171 168
172 - public function render_sticky_bar() {
173 - $args = [
169 + public function render_sticky_bar()
170 + {
171 + $campaigns = get_posts( [
174 172 'post_type' => HURRYT_POST_TYPE,
175 173 'numberposts' => -1,
176 174 'post_status' => 'publish',
177 175 'meta_key' => 'enable_sticky',
178 176 'meta_value' => C::YES,
179 - ];
177 + 'suppress_filters' => false,
178 + ] );
179 + foreach ( $campaigns as $post ) {
180 + echo do_shortcode( sprintf( '[hurrytimer id="%d" sticky="true" ]', $post->ID ) );
181 + }
180 182
181 - if(defined( 'ICL_SITEPRESS_VERSION' )){
182 - $args['suppress_filters'] = false;
183 - }
184 -
185 - $campaigns = get_posts($args);
183 + }
186 184
187 - foreach ($campaigns as $post) {
188 - echo do_shortcode(sprintf('[hurrytimer id="%d" sticky="true" ]', $post->ID));
185 + /**
186 + * Apply change stock status
187 + */
188 + public function ajax_change_stock_status()
189 + {
190 + check_ajax_referer( 'hurryt', 'nonce' );
191 + if ( !isset( $_POST[ 'campaign_id' ], $_POST[ 'status' ] ) ) {
192 + die( -1 );
189 193 }
194 + $id = intval( $_POST[ 'campaign_id' ] );
195 + $status = sanitize_key( $_POST[ 'status' ] );
196 + $wc_campaign = new WCCampaign();
197 + $campaign = new Campaign( $id );
198 + $wc_campaign->change_stock_status( $campaign, $status );
199 + die();
190 200 }
191 201
192 202 /**
193 203 * Maybe display campaign on current product page.
194 204 */
195 - public function render_on_product_page() {
205 + public function render_on_product_page()
206 + {
196 207 global $post;
197 - if (hurryt_is_woocommerce_activated() && is_product()) {
208 + if ( hurryt_is_woocommerce_activated() && is_product() ) {
198 209 $wc_campaign = new WCCampaign();
199 - $wc_campaign->run($post->ID);
210 + $wc_campaign->run( $post->ID );
200 211 }
212 +
201 213 }
202 214
203 215 /**
204 216 * Register the stylesheets for the public-facing side of the site.
@@ -204,75 +216,54 @@
204 216 * Register the stylesheets for the public-facing side of the site.
205 217 *
206 218 * @since 1.0.0
207 219 */
208 - public function enqueue_styles() {
209 - wp_enqueue_style( 'hurrytimer', CSS_Builder::get_instance()->get_css_url());
220 + public function enqueue_styles()
221 + {
222 + // Using hashed filename for cache busting.
223 + wp_enqueue_style( $this->plugin_name, CSS_Builder::get_instance()->get_build_url() );
210 224 }
211 225
212 - function get_custom_css(){
213 - $custom_css = get_option('hurrytimer_custom_css');
214 - if($custom_css){
215 - return $custom_css;
216 - }
217 - ob_start();
218 - // TODO: Minify CSS
219 - include __DIR__ . '/includes/css_template.php';
220 - $custom_css = ob_get_clean();
221 - update_option('hurrytimer_custom_css', $custom_css);
222 - return $custom_css;
223 - }
224 -
225 226 /**
226 227 * Register the JavaScript for the public-facing side of the site.
227 228 *
228 229 * @since 1.0.0
229 230 */
230 - public function enqueue_scripts() {
231 + public function enqueue_scripts()
232 + {
231 233
232 - wp_enqueue_script('jquery');
234 + wp_enqueue_script( 'jquery' );
233 235
234 - $deps = ['jquery', 'hurryt-countdown'];
235 -
236 - // Use woocommerce js cookie if already enqueued.
237 - // TODO: remove this dep in the future
238 - // if(! wp_script_is('js-cookie') ){
239 - wp_enqueue_script(
240 - 'hurryt-cookie',
241 - HURRYT_URL . 'assets/js/cookie.min.js',
242 - [],
243 - '3.14.1',
244 - true
245 - );
246 - $deps[] = 'hurryt-cookie';
247 - // }
248 -
249 236 wp_enqueue_script(
237 + 'hurryt-cookie',
238 + HURRYT_URL . 'assets/js/cookie.min.js',
239 + [],
240 + '3.14.1',
241 + true
242 + );
243 + wp_enqueue_script(
250 244 'hurryt-countdown',
251 245 HURRYT_URL . 'assets/js/jquery.countdown.min.js',
252 - ['jquery'],
246 + [ 'jquery' ],
253 247 '2.2.0',
254 248 true
255 249 );
256 -
257 250 wp_enqueue_script(
258 251 $this->plugin_name,
259 252 HURRYT_URL . 'assets/js/hurrytimer.js',
260 - $deps,
261 - defined('WP_DEBUG') && WP_DEBUG ? time() : $this->version,
253 + [ 'jquery', 'hurryt-countdown', 'hurryt-cookie' ],
254 + defined( 'WP_DEBUG' ) && WP_DEBUG ? time() : $this->version,
262 255 true
263 256 );
264 257
265 258
266 - $disable_actions = hurryt_is_admin_area() && hurryt_settings()['disable_actions'];
267 - $disable_actions = filter_var(
268 - apply_filters('hurryt_disable_actions', $disable_actions),
269 - FILTER_VALIDATE_BOOLEAN
270 - );
259 + $disable_actions = hurryt_is_admin_area() && hurryt_settings()[ 'disable_actions' ];
260 + $disable_actions = filter_var( apply_filters( 'hurryt_disable_actions', $disable_actions ),
261 + FILTER_VALIDATE_BOOLEAN );
271 262
272 - wp_localize_script($this->plugin_name, 'hurrytimer_ajax_object', [
273 - 'ajax_url' => admin_url('admin-ajax.php'),
274 - 'ajax_nonce' => wp_create_nonce('hurryt'),
263 + wp_localize_script( $this->plugin_name, 'hurrytimer_ajax_object', [
264 + 'ajax_url' => admin_url( 'admin-ajax.php' ),
265 + 'ajax_nonce' => wp_create_nonce( 'hurryt' ),
275 266 'disable_actions' => $disable_actions,
276 267 'methods' => [
277 268 'COOKIE' => C::DETECTION_METHOD_COOKIE,
278 269 'IP' => C::DETECTION_METHOD_IP,
@@ -292,12 +283,38 @@
292 283 'immediately' => C::RESTART_IMMEDIATELY,
293 284 'afterReload' => C::RESTART_AFTER_RELOAD,
294 285 'after_duration' => C::RESTART_AFTER_DURATION,
295 286 ],
296 - 'COOKIEPATH' => defined('COOKIEPATH') ? COOKIEPATH : '',
297 - 'COOKIE_DOMAIN' => defined('COOKIE_DOMAIN') ? COOKIE_DOMAIN : '',
298 - 'redirect_no_back' => apply_filters('hurryt_redirect_no_back', true),
299 - 'expire_coupon_message' => __( 'Coupon "%s" has expired.', 'woocommerce' ),
300 - ]);
287 + 'COOKIEPATH' => defined( 'COOKIEPATH' ) ? COOKIEPATH : '',
288 + 'COOKIE_DOMAIN' => defined( 'COOKIE_DOMAIN' ) ? COOKIE_DOMAIN : '',
289 + 'redirect_no_back' => apply_filters( 'hurryt_redirect_no_back', true ),
290 + 'expire_coupon_message' => $this->get_coupon_expired_message(),
291 + ] );
292 + }
293 +
294 +
295 + /**
296 + * Get WooCommerce coupon expired message.
297 + *
298 + *
299 + * TODO: move to /integration/woocommerce
300 + *
301 + * @return string
302 + * @since 2.3
303 + */
304 + function get_coupon_expired_message()
305 + {
306 +
307 + if ( !hurryt_is_woocommerce_activated() ) {
308 + return '';
309 + }
310 +
311 + try {
312 + return ( new \WC_Coupon() )->get_coupon_error( \WC_Coupon::E_WC_COUPON_EXPIRED );
313 +
314 + } catch ( \Exception $e ) {
315 + return '';
316 + }
317 +
301 318 }
302 319
303 320 }