PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.14
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.14
1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 1.3.51 1.3.50 1.3.49 1.3.48 1.3.47 1.3.46 1.3.45 All 177 releases
disco / libs / WebAppick / AppServices / Promotions.php

Promotions.php in Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO 1.4.14, at libs/WebAppick/AppServices/Promotions.php

388 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Webappick Promotion handler
4 * @version 1.0.0
5 * @package Disco
6 * @subpackage AppServices
7 */
8
9 namespace Disco\Libs\WebAppick\AppServices;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 die();
13 }
14
15 /**
16 * Class Promotions
17 * Source Format
18 *
19 $promos = [
20 (object) [
21 // required; offer start
22 'start' => '2019-11-20 00:00:01',
23 // required; offer end
24 'end' => '2019-12-04 23:59:00',
25 // required; some unique hash for offer, use for hiding the offer when user click to close.
26 'hash' => '9df37798-bd35-421b-b6f2-fbc095686efc',
27 // Optional; Allow closing default is 0, set to 1 to allow user hide it
28 'dismissible' => 1, // 0
29 // required; main content required, will be filtered with wp_kses_post()
30 'content' => '<p>Biggest Sale of the year on this</p><h3>Black Friday & Cyber Monday</h3><p>Claim your discount on till 4th December</p>',
31 // optional; wrapper padding
32 wrapperPadding => ''
33 // optional; image source url or data url
34 'backgroundImage' => '',
35 // optional;
36 'backgroundRepeat' => '',
37 // optional;
38 'backgroundSize' => '',
39 // optional; background color to apply with the background image
40 'backgroundColor' => '#000',
41 // optional; text color will be inherited by the content
42 'color' => '#fff',
43 // optional; can be empty
44 'logo' => [
45 // required; image source url or data url
46 'src' => '',
47 // required;
48 'alt' => 'Woo Feed Pro',
49 ],
50 // optional; can be empty
51 'button' => [
52 // required
53 'label' => 'Save 30%',
54 // required
55 'url' => '#?utm_campaign=black_friday_&_cyber_monday&utm_medium=banner&utm_source=wp_dashboard',
56 // optional;
57 'backgroundColor' => '#F71560',
58 // optional;
59 'color' => '#FFF',
60 // optional;
61 'after' => '<span style="font-size: 12px; font-weight: 700; margin-top: 12px; display: block;">Coupon: BFCM2019</span>', // html content filtered with wp_kses_post()
62 ],
63 ],
64 ];
65 *
66 */
67 class Promotions {
68
69 /**
70 * CTXFeed\AppServices\Client
71 *
72 * @var Client
73 */
74 protected $client;
75
76 /**
77 * URL for Promotions source json file
78 * @var string
79 */
80 private $promotionSrc;
81
82 /**
83 * Promotions
84 * @var bool|object[]
85 */
86 private $promotions = false;
87 /**
88 * List of hidden promotions for current user
89 * @var array
90 */
91 private $hiddenPromotions;
92 /**
93 * Current User Id
94 * @var int
95 */
96 private $currentUser = 0;
97
98 /**
99 * Promotions constructor.
100 * @param Client $client The Client.
101 * @param string $data_source Data Source URL
102 * @return void
103 */
104 public function __construct( Client $client, $data_source = null ) {
105 $this->client = $client;
106 if ( ! is_null( $data_source ) ) $this->promotionSrc = esc_url( $data_source );
107 }
108
109 /**
110 * Set JSON Source File URL For getting promotion data
111 * @param string $URL Set Data Source URL.
112 *
113 * @return Promotions
114 */
115 public function set_source( $URL ) {
116 $this->promotionSrc = esc_url( $URL );
117 return $this;
118 }
119
120 /**
121 * Init Promotions
122 * @return void
123 */
124 public function init() {
125 if ( is_null( $this->promotionSrc ) ) {
126 _doing_it_wrong( __METHOD__, esc_html__( 'Promotion Source URL Not Set. see Promotions::set_source( $URL )', 'disco' ), '1.0.0' );
127 }
128 add_action( 'admin_init', [ $this, '__init_internal' ], 10 );
129 }
130
131 /**
132 * Set environment variables and init internal hooks
133 * @return void
134 */
135 public function __init_internal() {
136 $this->currentUser = get_current_user_id();
137 $this->hiddenPromotions = (array) get_user_option( $this->client->getSlug() . '_hidden_promos', $this->currentUser );
138 $this->promotions = $this->__get_promos();
139 // only run if there is active promotions.
140 if ( count( $this->promotions ) ) {
141 add_action( 'admin_notices', [ $this, '__show_promos' ], 10 );
142 add_action( 'wp_ajax_webappick_dismiss_promo', [ $this, '__webappick_dismiss_promo' ], 10 );
143 add_action( 'admin_print_styles', [ $this, '__get_promo_styles' ], 99 );
144 add_action( 'admin_enqueue_scripts', [ $this, '__enqueue_deps' ], 10 );
145 add_action( 'admin_print_footer_scripts', [ $this, '__get_promo_scripts' ], 10 );
146 }
147 }
148
149 /**
150 * Render Promotions
151 * @return void
152 */
153 public function __show_promos() {
154 foreach ( $this->promotions as $promotion ) {
155 $wrapperStyles = '';
156 $buttonStyles = '';
157 $is_dismissible = ! isset( $promotion->dismissible ) || isset( $promotion->dismissible ) && 0 == $promotion->dismissible ? false : true;
158
159 $has_columns = isset( $promotion->button, $promotion->logo );
160 if ( isset( $promotion->color ) ) {
161 $wrapperStyles .= 'color: ' . $promotion->color . ';';
162 }
163 if ( isset( $promotion->wrapperPadding ) ) {
164 $wrapperStyles .= 'padding: ' . $promotion->wrapperPadding . ';';
165 }
166 if ( isset( $promotion->backgroundColor ) ) {
167 $wrapperStyles .= 'background-color: ' . $promotion->backgroundColor . ';';
168 }
169 if ( isset( $promotion->backgroundImage ) ) {
170 $wrapperStyles .= 'background-image: url("' . esc_url( $promotion->backgroundImage ) . '");';
171 }
172 if ( isset( $promotion->backgroundRepeat ) ) {
173 $wrapperStyles .= 'background-repeat: ' . $promotion->backgroundRepeat . ';';
174 }
175 if ( isset( $promotion->backgroundSize ) ) {
176 $wrapperStyles .= 'background-size: ' . $promotion->backgroundSize . ';';
177 }
178 if ( property_exists( $promotion, 'button' ) ) {
179 if ( isset( $promotion->button->backgroundColor ) ) {
180 $buttonStyles .= 'background-color: ' . $promotion->button->backgroundColor . ';border-color: ' . $promotion->button->backgroundColor . ';';
181 }
182 if ( isset( $promotion->button->color ) ) {
183 $buttonStyles .= 'color: ' . $promotion->button->color . ';';
184 }
185 }
186 $noticeClasses = 'notice notice-success wapk-promo';
187 if ( $is_dismissible ) {
188 $noticeClasses .= ' is-dismissible';
189 }
190 ?>
191 <div class="<?php echo esc_attr( $noticeClasses ); ?> " id="<?php echo esc_attr( $promotion->hash ); ?>" data-nonce="<?php echo esc_attr( wp_create_nonce( 'wapk-dismiss-promo' ) ); ?>" style="<?php echo esc_attr( $wrapperStyles ); ?>">
192 <div class="wapk-promo-wrap<?php if ( ! $has_columns ) echo ' no-column'; ?>">
193 <?php if ( isset( $promotion->logo ) && ! empty( $promotion->logo ) ) { ?>
194 <div class="wapk-logo wapk-column">
195 <img src="<?php echo esc_url( $promotion->logo->src ); ?>" alt="<?php echo esc_attr( $promotion->logo->alt ); ?>">
196 </div>
197 <?php } ?>
198 <div class="wapk-details<?php if ( $has_columns ) echo ' wapk-column'; ?>">
199 <?php echo wp_kses_post( $promotion->content ); ?>
200 </div>
201 <?php if ( isset( $promotion->button ) && ! empty( $promotion->button ) ) { ?>
202 <div class="wapk-btn-container wapk-column">
203 <a href="<?php echo esc_url( $promotion->button->url ); ?>" class="button wapk-promo-btn" style="<?php echo esc_attr( $buttonStyles ); ?>" target="_blank"><?php echo wp_kses_post( $promotion->button->label ); ?></a>
204 <?php
205 if ( isset( $promotion->button->after ) && ! empty( $promotion->button->after ) ) {
206 echo wp_kses_post( $promotion->button->after );
207 }
208 ?>
209 </div>
210 <?php } ?>
211 <?php if ( isset( $promotion->button ) && ! empty( $promotion->button ) ) { ?>
212 <?php } ?>
213 </div>
214 </div>
215 <?php
216 }
217 }
218
219 /**
220 * Get Promotion Data
221 * Cache First then fetch source url for json data.
222 * @return array
223 */
224 private function __get_promos() {
225 $promos = get_transient( $this->client->getSlug() . '_cached_promos' );
226 if ( empty( $promos ) ) {
227 // get promotions data from json source.
228 $response = wp_safe_remote_get( $this->promotionSrc, array( 'timeout' => 15 ) ); // phpcs:ignore
229 $promos = wp_remote_retrieve_body( $response );
230 if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
231 $promos = '[]';
232 }
233 // cache data.
234 set_transient( $this->client->getSlug() . '_cached_promos', $promos, 12 * HOUR_IN_SECONDS );
235 }
236 // decode to array.
237 $promos = json_decode( $promos );
238
239 // filter promotions by date.
240 $promos = array_filter( $promos, [ $this, '__is_promo_active' ] );
241 if ( ! empty( $promos ) ) {
242 // filter promotions by list of hidden promotions by the user.
243 $promos = array_filter( $promos, [ $this, '__is_promo_hidden' ] );
244 }
245 return $promos;
246 }
247
248 /**
249 * Check if promotion is active by date.
250 * must have start and end property
251 * @param object $promo { the promo object.
252 * Single Promo Object
253 * @type string $content string. required
254 * @type string $start valid timestamp. required
255 * @type string $end valid timestamp. required
256 * }
257 *
258 * @return bool
259 */
260 public function __is_promo_active( $promo ) {
261 $ct = current_time( 'timestamp' ); // phpcs:ignore
262 return ( ! empty( $promo->content ) && strtotime( $promo->start ) < $ct && $ct < strtotime( $promo->end ) );
263 }
264
265 /**
266 * Check if promo is hidden by current user
267 * @param object $promo { the promo object.
268 * Single Promo Object
269 * @type string $hash valid unique hash for a promo
270 * }
271 *
272 * @return bool true if promo is hidden by user
273 */
274 public function __is_promo_hidden( $promo ) {
275 return ! in_array( $promo->hash, $this->hiddenPromotions );
276 }
277
278 /**
279 * Js Dependencies
280 * @return void
281 */
282 public function __enqueue_deps(){
283 wp_enqueue_script( 'wp-util' );
284 wp_enqueue_script( 'jquery' );
285 }
286
287 /**
288 * Script for hiding promo on user click
289 * @return void
290 */
291 public function __get_promo_scripts() {
292 ?>
293 <!--suppress ES6ConvertVarToLetConst -->
294 <script>
295 (function($){
296 $('body').on('click', '.wapk-promo .notice-dismiss', function (e) {
297 e.preventDefault();
298 var $parent = $(this).closest( '.wapk-promo' );
299 wp.ajax.post('webappick_dismiss_promo', {
300 dismissed: true,
301 hash: $parent.attr( 'id' ),
302 _wpnonce: $parent.data( 'nonce' ),
303 });
304 });
305 })(jQuery);
306 </script>
307 <?php
308 }
309
310 /**
311 * Global Promo Styles
312 * @return void
313 */
314 public function __get_promo_styles() {
315 ?>
316 <!--suppress CssUnusedSymbol -->
317 <style>
318 .wapk-promo { border: none; padding: 15px 0; }
319 .wapk-promo-wrap { display: flex; justify-content: center; align-items: center; text-align: center; color: inherit; max-width: 1820px; margin: 0 auto; }
320 .wapk-promo-wrap.no-column{ display: block; }
321 .wapk-column.wapk-logo { flex: 0 0 25%; }
322 .wapk-column.wapk-logo img { height: 48px; width: auto; }
323 .wapk-details {display: block;}
324 .wapk-details h3 { color: inherit; font-size: 30px; margin: 12px 0; }
325 .wapk-details p { color: inherit; font-size: 15px; }
326 .wapk-column.wapk-details { flex: 0 0 50%; }
327 .wapk-column.wapk-btn-container { flex: 0 0 25%; }
328 .wapk-promo-wrap .wapk-promo-btn { position: relative; padding: 15px; border-radius: 30px; font-size: 15px; font-weight: 700; display: block; color: inherit; text-decoration: none; max-width: 200px; margin: 0 auto; line-height: normal; height: auto; box-shadow: 1px 2px 0 rgba(0, 0, 0, 0.1); }
329 .wapk-promo-wrap .wapk-promo-btn:focus,
330 .wapk-promo-wrap .wapk-promo-btn:hover,
331 .wapk-promo-wrap .wapk-promo-btn:active { box-shadow: inset 3px 4px 6px 0 rgba(1, 9, 12, 0.25); }
332 .wapk-promo-wrap .wapk-promo-btn:active { top: 1px; }
333 @media screen and (max-width: 1200px) {
334 .wapk-promo-wrap { display: block; overflow: hidden; }
335 .wapk-column .wapk-logo { width: 100%; margin: 0 auto; }
336 .wapk-column .wapk-details { width: 68%; float: left; margin-right: 4%; margin-top: 32px; }
337 .wapk-column.wapk-btn-container { width: 28%; float: right; margin-top: 42px; }
338 }
339 @media screen and (max-width: 782px) {
340 .wapk-promo-wrap .wapk-details { float: none; width: 100%; }
341 .wapk-btn-container { float: none; width: 100%; margin-top: 32px; }
342 .wapk-column.wapk-btn-container { width: 100%; float: right; margin-top: 42px; }
343 }
344 </style>
345 <?php
346 }
347
348 /**
349 * Ajax Callback handler for hiding promo
350 * @return void
351 */
352 public function __webappick_dismiss_promo() {
353 if (
354 isset( $_REQUEST['dismissed'], $_REQUEST['hash'], $_REQUEST['_wpnonce'] ) &&
355 'true' == $_REQUEST['dismissed'] && ! empty( $_REQUEST['hash'] ) &&
356 wp_verify_nonce( sanitize_text_field( $_REQUEST['_wpnonce'] ), 'wapk-dismiss-promo' )
357 ) {
358 $this->hiddenPromotions = array_merge( $this->hiddenPromotions, [ sanitize_text_field( $_REQUEST['hash'] ) ] );
359 update_user_option( $this->currentUser, $this->client->getSlug() . '_hidden_promos', $this->hiddenPromotions );
360 wp_send_json_success( esc_html__( 'Promo hidden', 'disco' ) );
361 }
362 wp_send_json_error( esc_html__( 'Invalid Request', 'disco' ) );
363 die();
364 }
365
366 /**
367 * @noinspection PhpUnused
368 * Clear Hidden Promotion preference for User
369 * @return bool
370 */
371 public function clear_hidden_promos() {
372 if ( ! did_action( 'admin_init' ) ) {
373 _doing_it_wrong( __METHOD__, esc_html__( 'Method must be invoked inside admin_init action', 'disco' ), '1.0.0' );
374 }
375 $this->currentUser = get_current_user_id();
376 return delete_user_option( $this->currentUser, $this->client->getSlug() . '_hidden_promos' );
377 }
378
379 /**
380 * Clear Cached Promotion data
381 * @return bool
382 */
383 public function clear_cache() {
384 return delete_transient( $this->client->getSlug() . '_cached_promos' );
385 }
386 }
387 // End of file Promotions.php.
388