PluginProbe
Leyka / 3.17
Leyka v3.17
3.32.3 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.6.1 2.3.7 2.3.8 2.3.9 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1 3.10 3.11 3.11.1 3.12 3.13 3.14 3.15 3.16 3.17 All 89 releases
leyka / inc / leyka-functions.php

leyka-functions.php in Leyka 3.17, at inc/leyka-functions.php

2,557 lines 82.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if( !defined('WPINC') ) die;
2
3 /**
4 * Leyka functions and template tags, irrelevant to a donation form.
5 **/
6
7 if( !function_exists('mb_substr') ) {
8 function mb_substr($str, $start, $length = null) {
9 return substr($str, $start, $length);
10 }
11 }
12
13 if( !function_exists('mb_ucfirst') ) {
14 function mb_ucfirst($str) {
15 return mb_strtoupper(mb_substr($str, 0, 1)).mb_substr($str, 1);
16 }
17 }
18
19 if( !function_exists('mb_strtolower') ) {
20 function mb_strtolower($str) {
21 return strtolower($str);
22 }
23 }
24
25 if( !function_exists('mb_strtoupper') ) {
26 function mb_strtoupper($str) {
27 return strtoupper($str);
28 }
29 }
30
31 if( !function_exists('array_key_first') ) {
32 function array_key_first(array $array) {
33
34 foreach($array as $key => $unused) {
35 return $key;
36 }
37 return NULL;
38
39 }
40 }
41
42 if( !function_exists('array_key_last') ) {
43 function array_key_last(array $array) {
44 return $array ? key(array_slice($array, -1)) : null;
45 }
46 }
47
48 if( !function_exists('leyka_strip_string_by_words') ) {
49 function leyka_strip_string_by_words($string, $length = 350, $strip_tags_shortcodes = true) {
50
51 if( !!$strip_tags_shortcodes ) {
52 $string = strip_tags(strip_shortcodes($string));
53 }
54
55 if(mb_strlen($string) <= $length || stripos($string, ' ') === false) {
56 return $string;
57 }
58
59 $characters_count = 0;
60 $result_string = array();
61 foreach(explode(' ', $string) as $word) {
62
63 $characters_count += mb_strlen($word);
64 if($characters_count <= $length) {
65 $result_string[] = $word;
66 } else {
67 break;
68 }
69
70 }
71
72 return implode(' ', $result_string);
73 }
74 }
75
76 if( !function_exists('leyka_string_has_rus_chars')) {
77 /**
78 * @param $text string
79 * @return boolean True if given string contains at least 1 cyrillic character, false otherwise.
80 */
81 function leyka_string_has_rus_chars($text) {
82 return preg_match('/[А-Яа-яЁё]/u', $text);
83 }
84 }
85
86 if( !function_exists('leyka_cyr2lat') ) {
87 function leyka_cyr2lat($string) {
88
89 $converter = array(
90 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e',
91 'ё' => 'e', 'ж' => 'zh', 'з' => 'z', 'и' => 'i', 'й' => 'y', 'к' => 'k',
92 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r',
93 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', '�
94 ' => 'h', 'ц' => 'c',
95 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sch', 'ь' => '', 'ы' => 'y', 'ъ' => '',
96 'э' => 'e', 'ю' => 'yu', 'я' => 'ya',
97
98 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E',
99 'Ё' => 'E', 'Ж' => 'Zh', 'З' => 'Z', 'И' => 'I', 'Й' => 'Y', 'К' => 'K',
100 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O', 'П' => 'P', 'Р' => 'R',
101 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C',
102 'Ч' => 'CH', 'Ш' => 'SH', 'Щ' => 'SCH', 'Ь' => '', 'Ы' => 'Y', 'Ъ' => '',
103 'Э' => 'E', 'Ю' => 'Yu', 'Я' => 'Ya',
104 );
105
106 return strtr($string, $converter);
107
108 }
109 }
110
111 if( !function_exists('leyka_maybe_encode_hostname_to_punycode') ) {
112 /**
113 * @param $url string
114 * @return string
115 */
116 function leyka_maybe_encode_hostname_to_punycode($url) {
117
118 $hostname = explode('/', str_replace(array('http://', 'https://'), '', $url));
119 $hostname = reset($hostname);
120
121 if(leyka_string_has_rus_chars($hostname)) {
122
123 require_once LEYKA_PLUGIN_DIR.'/lib/class-punycode.php';
124 return str_replace($hostname, Punycode::encodeHostName($hostname), $url);
125
126 } else {
127 return $url;
128 }
129
130 }
131 }
132 // require_once LEYKA_PLUGIN_DIR.'/lib/class-punycode.php';
133
134 if( !function_exists('leyka_set_html_content_type') ) {
135 function leyka_set_html_content_type() {
136 return 'text/html';
137 }
138 }
139
140 function leyka_user_has_role($role, $is_only_role = false, $user = false) {
141
142 if($user && is_numeric($user)) {
143 $user = get_userdata($user);
144 } else if( !$user || !is_a($user, 'WP_User') ) {
145 $user = wp_get_current_user();
146 }
147
148 if( !$user ) {
149 return false;
150 }
151
152 return !!$is_only_role ?
153 (array)$user->roles == array($role) :
154 in_array($role, (array)$user->roles);
155
156 }
157
158 /**
159 * @param $donation mixed
160 * @return Leyka_Donation|false A donation object, if parameter is valid in one way or another; false otherwise.
161 */
162 function leyka_get_validated_donation($donation) {
163
164 if(is_numeric($donation) && (int)$donation > 0) {
165 $donation = new Leyka_Donation((int)$donation);
166 } else if(is_a($donation, 'WP_Post')) {
167 $donation = new Leyka_Donation($donation);
168 } elseif( !is_a($donation, 'Leyka_Donation') ) {
169 return false;
170 }
171
172 return $donation ? $donation : false;
173
174 }
175
176 /**
177 * @param $user int|string|WP_User|Leyka_Donor
178 * @return WP_User|WP_Error
179 */
180 function leyka_get_validated_user($user) {
181
182 if(is_int($user) || is_string($user)) {
183
184 if(absint($user) > 0 && !strstr($user, '@')) {
185 $user = get_user_by('id', absint($user));
186 } else {
187 $user = get_user_by('email', esc_sql($user));
188 }
189
190 if( !$user ) {
191 return new WP_Error(__('Incorrect Donor identification data', 'leyka'));
192 }
193
194 } else if(is_a($user, 'Leyka_Donor')) {
195 $user = get_user_by('id', $user->id);
196 } else if( !is_a($user, 'WP_User') ) {
197 return new WP_Error(__('Incorrect Donor identification data', 'leyka'));
198 }
199
200 return $user;
201
202 }
203
204 /**
205 * @param $campaign mixed
206 * @return Leyka_Campaign|false A Leyka_Campaign instance if parameter is valid in one way or another; false otherwise.
207 */
208 function leyka_get_validated_campaign($campaign) {
209
210 if(is_numeric($campaign) && (int)$campaign > 0) {
211 $campaign = get_post((int)$campaign);
212 }
213
214 if(is_a($campaign, 'WP_Post') && $campaign->post_type === Leyka_Campaign_Management::$post_type) {
215 $campaign = new Leyka_Campaign($campaign);
216 } else if( !is_a($campaign, 'Leyka_Campaign') ) {
217 return false;
218 }
219
220 return $campaign ? $campaign : false;
221
222 }
223
224 /** Get WP pages list as an array. Used mainly to form a dropdowns. */
225 function leyka_get_pages_list() {
226
227 global $wpdb;
228
229 $params = apply_filters('leyka_pages_list_query', array('post_status' => 'publish', 'post_type' => 'page'));
230 foreach($params as $name => &$value) {
231 $value = "`$name` = '$value'";
232 }
233 $res = $wpdb->get_results("SELECT ID, post_title FROM $wpdb->posts WHERE ".implode(' AND ', $params));
234
235 $pages = array(0 => __('Website main page', 'leyka'),);
236 foreach($res as $page) {
237 $pages[$page->ID] = $page->post_title;
238 }
239
240 return $pages;
241
242 }
243
244 /** A service function to get a list of full IDs for all currently used PMs. The list is countries-oblivious. */
245 function leyka_get_pm_full_ids_used() {
246
247 global $wpdb;
248
249 $pm_full_ids = array();
250
251 $gateway_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT {$wpdb->postmeta}.meta_value
252 FROM {$wpdb->postmeta}
253 LEFT JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id
254 WHERE {$wpdb->postmeta}.meta_key = %s
255 AND {$wpdb->posts}.post_type = %s",
256 'leyka_gateway',
257 Leyka_Donation_Management::$post_type
258 ));
259
260 foreach($gateway_ids as $gateway_id) {
261
262 if( !$gateway_id ) {
263 continue;
264 }
265
266 $gateway_pm_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT CONCAT(%s, '-', postmeta2.meta_value)
267 FROM {$wpdb->postmeta} postmeta1
268 LEFT JOIN {$wpdb->postmeta} postmeta2 ON postmeta1.post_id = postmeta2.post_id
269 WHERE postmeta1.meta_key = %s
270 AND postmeta1.meta_value = %s
271 AND postmeta2.meta_key = %s",
272 $gateway_id,
273 'leyka_gateway',
274 $gateway_id,
275 'leyka_payment_method'
276 ));
277
278 $pm_full_ids = array_merge($pm_full_ids, $gateway_pm_ids);
279
280 }
281
282 return array_unique($pm_full_ids);
283
284 }
285
286 function leyka_get_pd_usage_info_links() {
287 return __('<a href="//te-st.ru/reports/personal-data-perm/" target="_blank" rel="noopener noreferrer">the Teplitsa article</a>.', 'leyka');
288 }
289
290 function leyka_get_default_email_from() {
291
292 $domain = explode('/', trim(str_replace('http://', '', home_url('', 'http')), '/'));
293 return 'no_reply@'.$domain[0];
294
295 }
296
297 /** DM is for "donation manager" */
298 //function leyka_get_default_dm_list() {
299 // return get_bloginfo('admin_email').',';
300 //}
301
302 function leyka_get_default_pd_terms_page() {
303
304 $default_page = get_option('leyka_pd_terms_page');
305 if($default_page) {
306 return $default_page;
307 }
308
309 $page = get_posts(apply_filters('leyka_default_pd_terms_page_query', array(
310 'post_status' => array('publish', 'pending', 'draft', 'auto-draft', 'private', 'future', 'inherit', 'trash'),
311 'post_type' => 'page',
312 'post_name__in' => array('personal-data-usage-terms'),
313 'posts_per_page' => 1,
314 )));
315 $page = reset($page);
316
317 if($page) {
318
319 if($page->post_status != 'publish') {
320 wp_update_post(array('ID' => $page->ID, 'post_status' => 'publish',));
321 }
322
323 $page = $page->ID;
324
325 } else {
326
327 // Can't use wp_insert_post due to some strange get_permastruct() notice, so insert the post manually:
328 $page = leyka_manually_insert_page(array(
329 'post_title' => leyka_tmp__('Terms of personal data usage'),
330 'post_content' => leyka_tmp__('Terms of personal data usage full text. Use <br> for line-breaks.'),
331 'post_name' => 'personal-data-usage-terms',
332 ));
333 if((int)$page > 0) {
334 do_action('leyka_default_pd_terms_page_created', $page);
335 }
336
337 }
338
339 if($page) {
340 update_option('leyka_pd_terms_page', $page);
341 }
342
343 return $page ? $page : 0;
344
345 }
346
347 function leyka_get_default_service_terms_page() {
348
349 $default_page = get_option('leyka_terms_of_service_page');
350 if($default_page) {
351 return $default_page;
352 }
353
354 $page = get_posts(apply_filters('leyka_default_service_terms_page_query', array(
355 'post_status' => array('publish', 'pending', 'draft', 'auto-draft', 'private', 'future', 'inherit', 'trash'),
356 'post_type' => 'page',
357 'post_name__in' => array('donation-service-terms'),
358 'posts_per_page' => 1,
359 )));
360 $page = reset($page);
361
362 if($page) {
363
364 if($page->post_status != 'publish') {
365 wp_update_post(array('ID' => $page->ID, 'post_status' => 'publish',));
366 }
367
368 $page = $page->ID;
369
370 } else {
371
372 // Can't use wp_insert_post due to some strange get_permastruct() notice, so insert the post manually:
373 $page = leyka_manually_insert_page(array(
374 'post_title' => leyka_tmp__('Terms of donation service'),
375 'post_content' => leyka_tmp__('Terms of donation service text. Use <br /> for line-breaks, please.'),
376 'post_name' => 'donation-service-terms',
377 ));
378 if((int)$page > 0) {
379 do_action('leyka_default_terms_of_service_page_created', $page);
380 }
381
382 }
383
384 if($page) {
385 update_option('leyka_terms_of_service_page', $page);
386 }
387
388 return $page ? $page : 0;
389
390 }
391
392 function leyka_get_terms_of_service_page_url() {
393
394 $url = leyka_options()->opt('terms_of_service_page') ?
395 get_permalink(leyka_options()->opt('terms_of_service_page')) : home_url();
396
397 if( !$url ) { // It can be in case when "last posts" is selected for homepage
398 $url = home_url();
399 }
400
401 return $url;
402
403 }
404
405 function leyka_get_terms_of_pd_usage_page_url() {
406
407 $url = leyka_options()->opt('pd_terms_page') ?
408 get_permalink(leyka_options()->opt('pd_terms_page')) : home_url();
409
410 if( !$url ) { // It can be in case when "last posts" is selected for homepage
411 $url = home_url();
412 }
413
414 return $url;
415
416 }
417
418 function leyka_get_default_success_page() {
419
420 $default_page = get_option('leyka_success_page');
421 if($default_page) {
422 return $default_page;
423 }
424
425 $page = get_posts(apply_filters('leyka_default_success_page_query', array(
426 'post_status' => array('publish', 'pending', 'draft', 'auto-draft', 'private', 'future', 'inherit', 'trash'),
427 'post_type' => 'page',
428 'post_name__in' => array('thank-you-for-your-donation'),
429 'posts_per_page' => 1,
430 )));
431 $page = reset($page);
432
433 if($page) {
434
435 if($page->post_status != 'publish') {
436 wp_update_post(array('ID' => $page->ID, 'post_status' => 'publish',));
437 }
438
439 $page = $page->ID;
440
441 } else {
442
443 // Can't use wp_insert_post due to some strange get_permastruct() notice, so insert the post manually:
444 $page = leyka_manually_insert_page(array(
445 'post_title' => leyka_tmp__('Thank you!'),
446 'post_content' => leyka_tmp__('Your donation completed. We are grateful for your help.'),
447 'post_name' => 'thank-you-for-your-donation',
448 ));
449 if((int)$page > 0) {
450 do_action('leyka_default_success_page_created', $page);
451 }
452
453 }
454
455 if($page) {
456 update_option('leyka_success_page', $page);
457 }
458
459 return $page ? $page : 0;
460
461 }
462
463 function leyka_get_success_page_url() {
464
465 $url = leyka_options()->opt('success_page') ? get_permalink(leyka_options()->opt('success_page')) : home_url();
466 $url = $url ? $url : home_url(); // The case when "last posts" is selected for homepage
467
468 $leyka_template_data = leyka_get_current_template_data();
469 if( !empty($leyka_template_data['id']) ) {
470 leyka_remembered_data('template_id', $leyka_template_data['id']);
471 }
472
473 return $url;
474
475 }
476
477 function leyka_get_default_failure_page() {
478
479 $default_page = get_option('leyka_failure_page');
480 if($default_page) {
481 return $default_page;
482 }
483
484 $page = get_posts(apply_filters('leyka_default_failure_page_query', array(
485 'post_status' => array('publish', 'pending', 'draft', 'auto-draft', 'private', 'future', 'inherit', 'trash'),
486 'post_type' => 'page',
487 'post_name__in' => array('sorry-donation-failure'),
488 'posts_per_page' => 1,
489 )));
490 $page = reset($page);
491
492 if($page) {
493
494 if($page->post_status != 'publish') {
495 wp_update_post(array('ID' => $page->ID, 'post_status' => 'publish',));
496 }
497
498 $page = $page->ID;
499
500 } else {
501
502 // Can't use wp_insert_post due to some strange get_permastruct() notice, so insert the post manually:
503 $page = leyka_manually_insert_page(array(
504 'post_title' => leyka_tmp__('Payment failure'),
505 'post_content' => leyka_tmp__('We are deeply sorry, but for some technical reason we failed to receive your donation. Your money are intact. Please try again later!'),
506 'post_name' => 'sorry-donation-failure',
507 ));
508 if((int)$page > 0) {
509 do_action('leyka_default_failure_page_created', $page);
510 }
511
512 }
513
514 if($page) {
515 update_option('leyka_failure_page', $page);
516 }
517
518 return $page ? $page : 0;
519
520 }
521
522 function leyka_get_failure_page_url() {
523
524 $url = leyka_options()->opt('failure_page') ? get_permalink(leyka_options()->opt('failure_page')) : home_url();
525 $url = $url ? $url : home_url(); // The case when "last posts" is selected for homepage
526
527 $leyka_template_data = leyka_get_current_template_data();
528 if( !empty($leyka_template_data['id']) ) {
529 leyka_remembered_data('template_id', $leyka_template_data['id']);
530 }
531
532 return $url;
533
534 }
535
536 /**
537 * Get a list of donation form templates as an array.
538 *
539 * @deprecated From v3.5, use leyka()->get_templates().
540 */
541 function leyka_get_form_templates_list() {
542
543 $list = array();
544 foreach(leyka()->get_templates() as $template) {
545
546 if( !leyka_options()->opt('plugin_debug_mode') && !empty($template['debug_only']) ) {
547 continue;
548 }
549
550 $name = $template['name'] == __($template['name'], 'leyka') ? $template['name'] : __($template['name'], 'leyka');
551 $description = $template['description'] == __($template['description'], 'leyka') ?
552 $template['description'] : __($template['description'], 'leyka');
553
554 $list[$template['id']] = $name.' ('.mb_strtolower($description).')';
555
556 }
557
558 return $list;
559
560 }
561
562
563 /**
564 * Get possible leyka_donation post type's status list as an array.
565 *
566 * @param $with_hidden boolean
567 * @return array
568 */
569 function leyka_get_donation_status_list($with_hidden = true) {
570 return leyka()->get_donation_statuses($with_hidden);
571 }
572
573 function leyka_get_donation_status_description($status) {
574
575 $status_descriptions = leyka()->get_donation_statuses_descriptions();
576 return $status && isset($status_descriptions[$status]) ? $status_descriptions[$status] : '';
577
578 }
579
580 function leyka_get_donation_types() {
581 return leyka()->get_donation_types();
582 }
583
584 function leyka_get_donation_type_description($type) {
585
586 $type = $type === 'rebill' ? 'recurring' : $type;
587 $types = leyka()->get_donation_types_descriptions();
588
589 return $type && isset($types[$type]) ? $types[$type] : '';
590
591 }
592
593 function leyka_get_pm_categories_list() {
594 return apply_filters('leyka_pm_categories', array(
595 'bank_cards' => esc_attr__('Bank cards', 'leyka'),
596 'digital_currencies' => esc_attr__('Digital currrencies', 'leyka'),
597 'online_banking' => esc_attr__('Online banking', 'leyka'),
598 'mobile_payments' => esc_attr__('Mobile payments', 'leyka'),
599 'misc' => esc_attr__('Miscellaneous', 'leyka'),
600 'offline' => esc_attr__('Offline', 'leyka'),
601 ));
602 }
603
604 function leyka_get_pm_category_label($category_id) {
605
606 $category_id = esc_attr(trim($category_id));
607 $categories_list = leyka_get_pm_categories_list();
608
609 return $category_id && !empty($categories_list[$category_id]) ? $categories_list[$category_id] : false;
610
611 }
612
613 /**
614 * Gateways filter categories main source
615 * @return array
616 */
617 function leyka_get_gateways_filter_categories_list() {
618 return apply_filters('leyka_gateways_filter_categories', array(
619 'legal' => esc_attr__('Legal persons', 'leyka'),
620 'physical' => esc_attr__('Physical persons', 'leyka'),
621 'recurring' => mb_ucfirst(esc_html_x('recurring', 'a "recurring donations" in one word (like "recurrings")', 'leyka')),
622 ));
623 }
624
625 function leyka_get_filter_category_label($category_id) {
626
627 $category_id = esc_attr(trim($category_id));
628 $categories_list = leyka_get_gateways_filter_categories_list();
629
630 return $category_id && !empty($categories_list[$category_id]) ? $categories_list[$category_id] : false;
631
632 }
633
634 /**
635 * Gateway activation status labels
636 * @return string
637 */
638 function leyka_get_gateway_activation_status_label($activation_status) {
639
640 $activation_status_labels = array(
641 'active' => __('Active', 'leyka'),
642 'inactive' => __('Inactive', 'leyka'),
643 'activating' => __('Connection is in process', 'leyka'),
644 );
645
646 return $activation_status && !empty($activation_status_labels[$activation_status]) ?
647 $activation_status_labels[$activation_status] : false;
648
649 }
650
651 /**
652 * @param string $wizard_id
653 * @return bool
654 */
655 function leyka_wizard_started($wizard_id) {
656
657 try {
658 $wizard_controller = Leyka_Settings_Factory::get_instance()->get_controller($wizard_id);
659 } catch(Exception $e) {
660 return false;
661 }
662
663 return count($wizard_controller->history) > 0;
664
665 }
666
667 /**
668 * @param $extension_id string
669 * @return Leyka_Extension|false An extension object or false if none found.
670 */
671 function leyka_get_extension_by_id($extension_id) {
672 return Leyka_Extension::get_by_id($extension_id);
673 }
674
675 /**
676 * @param Leyka_Extension $extension
677 * @return string
678 */
679 function leyka_get_extension_settings_url(Leyka_Extension $extension) {
680 return $extension->get_settings_url();
681 }
682
683 /**
684 * @param Leyka_Extension $extension
685 * @return string|false A Wizard suffix or false if wizard unavailable for given extension.
686 */
687 function leyka_extension_setup_wizard(Leyka_Extension $extension) {
688 return $extension->wizard_id;
689 }
690
691 /**
692 * Gateway receiver description.
693 *
694 * @param $receiver_types array Receiver types array.
695 * @return string
696 */
697 function leyka_get_receiver_description($receiver_types) {
698
699 $type = count($receiver_types) > 1 ? 'all' : $receiver_types[0];
700
701 $labels = array(
702 'all' => esc_attr__('Legal & physical persons allowed as a receiver.', 'leyka'),
703 'legal' => esc_attr__('Only legal persons allowed as a receiver.', 'leyka'),
704 'physical' => esc_attr__('Only physical persons allowed as a receiver.', 'leyka'),
705 );
706
707 return $type && !empty($labels[$type]) ? $labels[$type] : '';
708
709 }
710
711 /**
712 * Get all possible campaign target states.
713 **/
714 function leyka_get_campaign_target_states_list() {
715 return leyka()->get_campaign_target_states();
716 }
717
718 /**
719 * Get campaign target - template tag
720 *
721 * @var $campaign integer Campaign ID.
722 * @return mixed Array of campaign target info, false if wrong campaign ID given, or int 0 if a campaign doesn't have a target.
723 */
724 function leyka_get_campaign_target($campaign) {
725
726 $campaign = (int)$campaign;
727 if($campaign <= 0) {
728 return false;
729 }
730
731 $campaign = new Leyka_Campaign($campaign);
732 if( !$campaign->id ) {
733 return false;
734 }
735
736 // Currently, target is always in RUB:
737 return $campaign->target ? array('amount' => $campaign->target, 'currency' => 'rur',) : 0;
738
739 }
740
741 /**
742 * Get campaign collected amount - template tag
743 *
744 * @var $campaign integer Campaign ID.
745 * @return mixed Array of campaign collected amount info, or false if wrong campaign ID given.
746 */
747 function leyka_get_campaign_collections($campaign) {
748
749 $campaign = (int)$campaign;
750 if($campaign <= 0) {
751 return false;
752 }
753
754 $campaign = new Leyka_Campaign($campaign);
755 if( !$campaign->id ) {
756 return false;
757 }
758
759 // Currently, collections are all in RUB:
760 return array('amount' => $campaign->total_funded, 'currency' => 'rur',);
761
762 }
763
764 /**
765 * Scale
766 **/
767 function leyka_scale_compact($campaign) {
768
769 if( !is_a($campaign, 'Leyka_Campaign') ) {
770 $campaign = new Leyka_Campaign($campaign);
771 }
772
773 $target = (float)$campaign->target;
774 if($target <= 0.0) {
775 return;
776 }
777
778 $curr_label = leyka_get_currency_label();
779
780 $percentage = round(($campaign->total_funded/$target)*100);
781 if($percentage > 100) {
782 $percentage = 100;
783 }?>
784
785 <div class="leyka-scale-compact">
786 <div class="leyka-scale-scale">
787 <div class="target">
788 <div style="width:<?php echo $percentage;?>%" class="collected">&nbsp;</div>
789 </div>
790 </div>
791 <div class="leyka-scale-label">
792 <?php $target_f = number_format($target, ($target - round($target) > 0.0 ? 2 : 0), '.', ' ');
793 $collected_f = number_format($campaign->total_funded, ($campaign->total_funded - round($campaign->total_funded) > 0.0 ? 2 : 0), '.', ' ');
794
795 if($campaign->total_funded == 0) {
796 printf(esc_html__('Needed %s %s', 'leyka'), '<b>'.$target_f.'</b>', $curr_label);
797 } else {
798 printf(esc_html__('Collected %s of %s %s', 'leyka'), '<b>'.$collected_f.'</b>', '<b>'.$target_f.'</b>', $curr_label);
799 }?>
800 </div>
801 </div>
802 <?php
803 }
804
805 function leyka_scale_ultra($campaign) {
806
807 if( !is_a($campaign, 'Leyka_Campaign') ) {
808 $campaign = new Leyka_Campaign($campaign);
809 }
810
811 $target = (float)$campaign->target;
812 $curr_label = leyka_get_currency_label();
813
814 if($target == 0) {
815 return;
816 }
817
818 $percentage = round(($campaign->total_funded/$target)*100);
819 $percentage = $percentage > 100 ? 100 : $percentage;?>
820
821 <div class="leyka-scale-ultra">
822 <div class="leyka-scale-scale">
823 <div class="target">
824 <div style="width:<?php echo $percentage;?>%" class="collected">&nbsp;</div>
825 </div>
826 </div>
827 <div class="leyka-scale-label">
828 <span>
829
830 <?php $target_f = number_format($target, ($target - round($target) > 0.0 ? 2 : 0), '.', ' ');
831 $collected_f = number_format($campaign->total_funded, ($campaign->total_funded - round($campaign->total_funded) > 0.0 ? 2 : 0), '.', ' ');
832
833 printf(esc_html_x('%s of %s %s', 'Label on ultra-compact scale', 'leyka'), '<b>'.$collected_f.'</b>', '<b>'.$target_f.'</b>', $curr_label);?>
834
835 </span>
836 </div>
837 </div>
838 <?php
839 }
840
841 function leyka_fake_scale_ultra($campaign) {
842
843 if( !is_a($campaign, 'Leyka_Campaign') ) {
844 $campaign = new Leyka_Campaign($campaign);
845 }
846
847 $curr_label = leyka_get_currency_label();
848 $collected_f = number_format($campaign->total_funded, ($campaign->total_funded - round($campaign->total_funded) > 0.0 ? 2 : 0), '.', ' ');?>
849
850 <div class="leyka-scale-ultra-fake">
851 <div class="leyka-scale-scale">
852 <div class="target"> </div>
853 </div>
854 <div class="leyka-scale-label"><span>
855 <?php printf(_x('Collected: %s', 'Label on ultra-compact fake scale', 'leyka'), "<b>{$collected_f}</b> {$curr_label}");?>
856 </span></div>
857 </div>
858
859 <?php
860 }
861
862 /** @return array An array of possible payment types with labels */
863 function leyka_get_payment_types_list() {
864 return array(
865 'single' => __('Single', 'leyka'),
866 'rebill' => __('Recurrent (rebill)', 'leyka'),
867 'correction' => __('Correction', 'leyka'),
868 );
869 }
870
871 function leyka_get_payment_type_label($type) {
872
873 if( !$type ) {
874 return false;
875 }
876
877 $types = leyka_get_payment_types_list();
878
879 return in_array($type, array_keys($types)) ? $types[$type] : false;
880
881 }
882
883 function leyka_get_countries_full_info($country_id = null) {
884
885 $countries = apply_filters('leyka_supported_countries_full_info', array(
886 'ru' => array('title' => __('Russia', 'leyka'), 'currency' => 'rur',),
887 'by' => array('title' => __('Belarus Republic', 'leyka'), 'currency' => 'byn'),
888 'ua' => array('title' => __('Ukraine', 'leyka'), 'currency' => 'uah'),
889 ));
890
891 if(empty($country_id)) {
892 return $countries;
893 }
894
895 return empty($countries[$country_id]) ? false : $countries[$country_id];
896
897 }
898
899 /**
900 * A service function to get countries list as a simple array of [country_id => country_title] pairs.
901 *
902 * @return array
903 */
904 function leyka_get_countries_list() {
905
906 $countries_simple_list = array();
907 foreach(leyka_get_countries_full_info() as $country_id => $info) {
908 $countries_simple_list[$country_id] = $info['title'];
909 }
910
911 return apply_filters('leyka_supported_countries_list', $countries_simple_list);
912
913 }
914
915 /** A service function to get the default receiver country ID */
916 function leyka_get_default_receiver_country_id() {
917 return 'ru';
918 }
919
920 /**
921 * A high-level function to get country associated with given currency ID.
922 *
923 * @param string $currency_id
924 * @return string|false Either country ID, or false if no coountry found for given currency ID.
925 */
926 function leyka_get_currency_country($currency_id) {
927
928 foreach(leyka_get_countries_full_info() as $country_id => $data) {
929
930 if($data['currency'] === $currency_id) {
931 return $country_id;
932 }
933
934 }
935
936 return false;
937
938 }
939
940 /**
941 * A service function to get currencies list as a simple array of [currency_id => currency_title] pairs.
942 *
943 * @return array
944 */
945 function leyka_get_currencies_list() {
946
947 $currencies_simple_list = array();
948
949 foreach(leyka_get_main_currencies_full_info() as $currency_id => $data) { // Can't use leyka_get_currencies_data() here
950
951 if( !leyka_get_currency_country($currency_id) ) {
952 continue;
953 }
954
955 $currencies_simple_list[$currency_id] = $data['title'].' ('.$data['label'].')';
956
957 }
958
959 return apply_filters('leyka_supported_currencies_list', $currencies_simple_list);
960
961 }
962
963 function leyka_get_main_currencies_full_info() {
964 return apply_filters('leyka_main_currencies_list', array(
965 'rur' => array(
966 'title' => __('Russian Rouble', 'leyka'),
967 'label' => __('', 'leyka'),
968 'min_amount' => 10,
969 'max_amount' => 30000,
970 'flexible_default_amount' => 500,
971 'fixed_amounts' => '100,300,500,1000',
972 ),
973 'byn' => array(
974 'title' => __('Belarus Rouble', 'leyka'),
975 'label' => __('BYN', 'leyka'),
976 'min_amount' => 1,
977 'max_amount' => 30000,
978 'flexible_default_amount' => 10,
979 'fixed_amounts' => '5,10,20,50',
980 ),
981 'uah' => array(
982 'title' => __('Ukraine Hryvnia', 'leyka'),
983 'label' => __('', 'leyka'),
984 'min_amount' => 10,
985 'max_amount' => 30000,
986 'flexible_default_amount' => 500,
987 'fixed_amounts' => '100,300,500,1000',
988 ),
989 ));
990 }
991
992 function leyka_get_secondary_currencies_full_info($country_id = null) {
993 return apply_filters('leyka_secondary_currencies_list', array(
994 'usd' => array(
995 'title' => __('US Dollar', 'leyka'),
996 'label' => __('$', 'leyka'),
997 'min_amount' => 1,
998 'max_amount' => 1000,
999 'flexible_default_amount' => 10,
1000 'fixed_amounts' => '1,3,5,10,15,50',
1001 ),
1002 'eur' => array(
1003 'title' => __('Euro', 'leyka'),
1004 'label' => __('', 'leyka'),
1005 'min_amount' => 1,
1006 'max_amount' => 650,
1007 'flexible_default_amount' => 5,
1008 'fixed_amounts' => '1,3,5,10,100',
1009 ),
1010 ), $country_id);
1011 }
1012
1013 /**
1014 * A low-level function to get all supported currencies & their default settings for all supported countries.
1015 *
1016 * @param string $currency_id
1017 * @return array|false Either an array of all currencies default settings, or an array of given currency settings,
1018 * or false if no given currency found.
1019 */
1020 function leyka_get_currencies_full_info($currency_id = null) {
1021
1022 $currencies = array_merge(leyka_get_main_currencies_full_info(), leyka_get_secondary_currencies_full_info());
1023
1024 if(empty($currency_id)) {
1025 return $currencies;
1026 }
1027
1028 return empty($currencies[$currency_id]) ? false : $currencies[$currency_id];
1029
1030 }
1031
1032 /**
1033 * Get the default main currency for given country.
1034 * If none given, currently selected receiver county will be used.
1035 *
1036 * @param string $country_id
1037 * @return mixed Either string Country ID, or false if no given Country found.
1038 */
1039 function leyka_get_country_currency($country_id = null) {
1040
1041 $country_id = $country_id ? trim($country_id) : Leyka_Options_Controller::get_option_value('leyka_receiver_country');
1042 $country_id = $country_id ? $country_id : leyka_get_default_receiver_country_id();
1043
1044 $country = leyka_get_countries_full_info($country_id);
1045
1046 return $country && !empty($country['currency']) ? $country['currency'] : false;
1047
1048 }
1049
1050 /**
1051 * A high-level function to get all supported currencies ACTUAL (not default) data.
1052 * The client code users should use it.
1053 *
1054 * @param string $currency_id
1055 * @return mixed If $currency_id is given, either it's data will return, or false (if the ID is not found). If no $currency_id is geiven, all currencies data will be returned as an array of [currency_id => currency_data] pairs.
1056 */
1057 function leyka_get_currencies_data($currency_id = null) {
1058
1059 $currencies = array();
1060
1061 foreach(leyka_get_currencies_full_info() as $id => $data) {
1062 $currencies[$id] = array(
1063 'label' => leyka_options()->opt('currency_'.$id.'_label'),
1064 'top' => leyka_options()->opt('currency_'.$id.'_max_sum'),
1065 'bottom' => leyka_options()->opt('currency_'.$id.'_min_sum'),
1066 'amount_settings' => array(
1067 'flexible' => leyka_options()->opt('currency_'.$id.'_flexible_default_amount'),
1068 'fixed' => leyka_options()->opt('currency_'.$id.'_fixed_amounts'),
1069 ),
1070 );
1071 }
1072
1073 if(empty($currencies['rub']) && !empty($currencies['rur'])) {
1074 $currencies['rub'] = $currencies['rur'];
1075 }
1076
1077 return $currency_id && !empty($currencies[$currency_id]) ? $currencies[$currency_id] : $currencies;
1078
1079 }
1080
1081 function leyka_get_actual_currencies_data($currency_id = null) {
1082 return leyka_get_currencies_data($currency_id);
1083 }
1084
1085 /**
1086 * @deprecated Use leyka_get_currencies_data($currency_id) instead.
1087 * @param bool $currency_id string
1088 * @return array|false
1089 */
1090 function leyka_get_active_currencies($currency_id = null) {
1091 return leyka_get_currencies_data($currency_id);
1092 }
1093
1094 /**
1095 * A high-level function to get all current settings of given currency ID.
1096 *
1097 * @param string $currency_id If none given, the current main currency is used.
1098 * @return string|false A current currency settings, or false if no given currency ID is found.
1099 */
1100 function leyka_get_currency_data($currency_id = null) {
1101
1102 $currency_id = empty($currency_id) ? leyka_options()->opt_safe('currency_main') : mb_strtolower($currency_id);
1103 $currency = leyka_get_currencies_data($currency_id);
1104
1105 return empty($currency[$currency_id]) ?
1106 false : apply_filters('leyka_'.$currency_id.'_currency_data', $currency[$currency_id]);
1107
1108 }
1109
1110 /**
1111 * A high-level function to get a label of given currency ID.
1112 *
1113 * @param string $currency_id If none given, the current main currency is used.
1114 * @return string|false A current currency label, or false if no given currency ID is found.
1115 */
1116 function leyka_get_currency_label($currency_id = null) {
1117
1118 $currency_id = empty($currency_id) ? leyka_options()->opt_safe('currency_main') : mb_strtolower($currency_id);
1119 $currency = leyka_get_currencies_data($currency_id);
1120
1121 return empty($currency['label']) ? false : apply_filters('leyka_'.$currency_id.'_currency_label', $currency['label']);
1122
1123 }
1124
1125 /**
1126 * Service function to get an actual rates from cbr.ru
1127 * @return array An assoc array of currency_code => it's rate to RUR
1128 */
1129 function leyka_get_actual_currency_rates() {
1130
1131 $url = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req='.date('d.m.Y');
1132 $currencies = array();
1133
1134 if(class_exists('XMLReader')) {
1135
1136 function leyka_xml2assoc(XMLReader $xml) {
1137
1138 $tree = null;
1139 while($xml->read()) {
1140
1141 switch($xml->nodeType) {
1142
1143 case XMLReader::END_ELEMENT: return $tree;
1144 case XMLReader::ELEMENT:
1145 $node = array('tag' => $xml->name, 'value' => $xml->isEmptyElement ? '' : leyka_xml2assoc($xml));
1146 if($xml->hasAttributes) {
1147 while($xml->moveToNextAttribute()) {
1148 $node['attributes'][$xml->name] = $xml->value;
1149 }
1150 }
1151 $tree[] = $node;
1152 break;
1153 case XMLReader::TEXT:
1154 case XMLReader::CDATA:
1155 $tree .= $xml->value;
1156 }
1157 }
1158
1159 return $tree;
1160 }
1161
1162 $xml = new XMLReader();
1163 if( @$xml->open($url) ) {
1164
1165 $currencies_tmp = leyka_xml2assoc($xml);
1166 $xml->close();
1167
1168 if( !empty($currencies_tmp[0]) ) {
1169 foreach($currencies_tmp[0]['value'] as $currency) {
1170
1171 $currency = $currency['value']; // Just to shorten this things a bit
1172
1173 $code = $currency[1]['value']; // USD, EUR etc.
1174 $rate = (float)str_replace(',', '.', $currency[4]['value']);
1175 if($code == 'USD' || $code == 'EUR') {
1176 $currencies[$code] = $rate;
1177 }
1178 }
1179 }
1180 }
1181
1182 } else if(class_exists('DOMDocument')) {
1183
1184 $xml = new DOMDocument();
1185 if( @$xml->load($url) ) {
1186
1187 foreach($xml->documentElement->getElementsByTagName('Valute') as $item) {
1188
1189 /** @var $item DOMElement */
1190
1191 $currency = $item->getElementsByTagName('CharCode')->item(0)->nodeValue;
1192 if($currency == 'USD' || $currency == 'EUR') {
1193 $currencies[$currency] = (float)str_replace(
1194 ',', '.',
1195 $item->getElementsByTagName('Value')->item(0)->nodeValue
1196 );
1197 }
1198 }
1199 }
1200 }
1201
1202 return $currencies;
1203
1204 }
1205
1206 function leyka_are_settings_complete($settings_tab) {
1207
1208 $settings_complete = true;
1209 $tab_options = leyka_opt_alloc()->get_tab_options($settings_tab); // Specially to support PHP strict standards
1210
1211 $receiver_legal_type = leyka_options()->opt_safe('receiver_legal_type');
1212 $exclude_legal_type_fields_regex = array('legal' => '/^person_/', 'physical' => '/^org_/',);
1213
1214 foreach($tab_options as $option_section) {
1215 foreach($option_section['section']['options'] as $option_name) {
1216 if(empty($exclude_legal_type_fields_regex[$receiver_legal_type]) || preg_match($exclude_legal_type_fields_regex[$receiver_legal_type], $option_name)) {
1217 continue;
1218 }
1219
1220 if(!leyka_options()->opt_safe($option_name) && leyka_options()->is_required($option_name) ) {
1221 $settings_complete = false;
1222 break;
1223 }
1224 }
1225 }
1226
1227 return $settings_complete;
1228
1229 }
1230
1231 function leyka_is_min_payment_settings_complete() {
1232
1233 $pm_list = leyka_get_pm_list(true, false, false);
1234 if( !$pm_list ) {
1235 return false;
1236 }
1237
1238 $gateway_options_valid = array(); // Array of already validated gateways
1239
1240 foreach($pm_list as $pm) { /** @var $pm Leyka_Payment_Method */
1241
1242 $gateway = leyka_get_gateway_by_id($pm->gateway_id);
1243
1244 if( !$pm || !$gateway ) {
1245 continue;
1246 }
1247
1248 $min_settings_complete = true;
1249 foreach($pm->get_pm_options_names() as $option_name) {
1250
1251 if( !leyka_options()->is_valid($option_name) ) {
1252
1253 $min_settings_complete = false;
1254 break;
1255 }
1256 }
1257
1258 if( !isset($gateway_options_valid[$gateway->id]) ) {
1259
1260 foreach($gateway->get_options_names() as $option_name) {
1261 if( !leyka_options()->is_valid($option_name) ) {
1262
1263 $gateway_options_valid[$gateway->id] = false;
1264 break;
1265 }
1266 }
1267
1268 if( !isset($gateway_options_valid[$gateway->id]) ) {
1269 $gateway_options_valid[$gateway->id] = true;
1270 }
1271 }
1272
1273 if($min_settings_complete && !empty($gateway_options_valid[$gateway->id])) {
1274 return true;
1275 }
1276 }
1277
1278 return false;
1279
1280 }
1281
1282 //function leyka_is_campaign_published() {
1283 //
1284 // global $wpdb;
1285 //
1286 // return $wpdb->get_var("SELECT COUNT(*)
1287 // FROM $wpdb->posts
1288 // WHERE post_type='".Leyka_Campaign_Management::$post_type."' AND post_status = 'publish' LIMIT 0,1"
1289 // ) > 0;
1290 //
1291 //}
1292
1293 function leyka_get_campaigns_list($params = array(), $simple_format = true) {
1294
1295 $campaigns = get_posts(array_merge(array(
1296 'post_type' => Leyka_Campaign_Management::$post_type,
1297 'posts_per_page' => -1,
1298 ), $params));
1299
1300 if( !!$simple_format ) { // Array of WP_Post objects
1301
1302 $list = array();
1303 foreach($campaigns as $campaign) {
1304
1305 $campaign = new Leyka_Campaign($campaign);
1306 $list[$campaign->id] = $campaign->title;
1307
1308 }
1309
1310 return $list;
1311
1312 } else { // Simple assoc. array of ID => title
1313
1314 foreach($campaigns as $campaign) {
1315 $campaign->post_title = htmlentities($campaign->post_title, ENT_QUOTES, 'UTF-8');
1316 }
1317
1318 return $campaigns;
1319
1320 }
1321
1322 }
1323
1324 function leyka_get_campaigns_select_default() {
1325
1326 $default_campaign = get_transient('leyka_default_campaign_id'); // Default campaign ID cache
1327
1328 if( !$default_campaign ) {
1329
1330 $default_campaign = array_keys(
1331 leyka_get_campaigns_list(array('orderby' => 'title', 'order' => 'ASC', 'posts_per_page' => 1,), true)
1332 );
1333 set_transient('leyka_default_campaign_id', reset($default_campaign));
1334
1335 }
1336
1337 return $default_campaign;
1338
1339 }
1340
1341 function leyka_get_terms_text() {
1342 return apply_filters(
1343 'leyka_terms_of_service_text',
1344 leyka_options()->opt('receiver_legal_type') === 'legal' ?
1345 leyka_options()->opt('terms_of_service_text') : leyka_options()->opt('person_terms_of_service_text')
1346 );
1347 }
1348
1349 function leyka_get_pd_terms_text() {
1350 return apply_filters(
1351 'leyka_terms_of_pd_usage_text',
1352 leyka_options()->opt('receiver_legal_type') === 'legal' ?
1353 leyka_options()->opt('pd_terms_text') : leyka_options()->opt('person_pd_terms_text')
1354 );
1355 }
1356
1357 /** Default campaign ID cache invalidation */
1358 function leyka_flush_cache_default_campaign_id($new_status, $old_status, WP_Post $campaign) {
1359
1360 if(
1361 $campaign->post_type !== Leyka_Campaign_Management::$post_type ||
1362 ($old_status !== 'publish' && $new_status !== 'publish')
1363 ) {
1364 return;
1365 }
1366
1367 delete_transient('leyka_default_campaign_id');
1368
1369 }
1370 add_action('transition_post_status', 'leyka_flush_cache_default_campaign_id', 10, 3);
1371
1372 function leyka_is_widget_active() {
1373
1374 // is_active_widget() is not working for some reason, so emulate it:
1375 foreach(wp_get_sidebars_widgets() as $sidebar => $widgets) {
1376 foreach((array)$widgets as $widget) {
1377 if(stristr($widget, 'leyka_') !== false) {
1378 return true;
1379 }
1380 }
1381 }
1382
1383 return false;
1384
1385 }
1386
1387 /** @return boolean */
1388 function leyka_are_bank_essentials_set() {
1389
1390 if(leyka_options()->opt('receiver_legal_type') === 'legal') {
1391 return !!leyka_options()->opt('org_full_name')
1392 && !!leyka_options()->opt('org_inn')
1393 && !!leyka_options()->opt('org_kpp')
1394 && !!leyka_options()->opt('org_bank_account')
1395 && !!leyka_options()->opt('org_bank_name')
1396 && !!leyka_options()->opt('org_bank_bic')
1397 && !!leyka_options()->opt('org_bank_corr_account')
1398 && !!leyka_options()->opt('org_state_reg_number');
1399 } else {
1400 return !!leyka_options()->opt('person_full_name')
1401 && !!leyka_options()->opt('person_inn')
1402 && !!leyka_options()->opt('person_bank_name')
1403 && !!leyka_options()->opt('person_bank_account')
1404 && !!leyka_options()->opt('person_bank_bic')
1405 && !!leyka_options()->opt('person_bank_corr_account');
1406 }
1407
1408 }
1409
1410 function leyka_get_empty_bank_essentials_options() {
1411
1412 if(leyka_are_bank_essentials_set()) {
1413 return array();
1414 }
1415
1416 $bank_essentials_options = leyka_options()->opt('receiver_legal_type') === 'legal' ?
1417 array('org_full_name', 'org_inn', 'org_kpp', 'org_bank_account', 'org_bank_name', 'org_bank_bic', 'org_bank_corr_account', 'org_state_reg_number') :
1418 array('person_full_name', 'person_inn', 'person_bank_name', 'person_bank_account', 'person_bank_bic', 'person_bank_corr_account',);
1419
1420 $result = array();
1421 foreach($bank_essentials_options as $option_id) {
1422 if( !leyka_options()->opt($option_id) ) {
1423 $result[] = $option_id;
1424 }
1425 }
1426
1427 return $result;
1428
1429 }
1430
1431 function leyka_is_campaign_link_in_menu() {
1432
1433 // foreach(get_registered_nav_menus() as $menu_id => $menu_name) {
1434 // wp_get_nav_menu_items($menu_id);
1435 // }
1436
1437 return false;
1438
1439 }
1440
1441 function leyka_get_shortcodes() {
1442
1443 global $shortcode_tags;
1444
1445 $leyka_shortcodes = array();
1446
1447 foreach($shortcode_tags as $shortcode_tag => $function_name) {
1448 if(stripos($shortcode_tag, 'leyka') !== false) {
1449 $leyka_shortcodes[] = $shortcode_tag;
1450 }
1451 }
1452
1453 return $leyka_shortcodes;
1454
1455 }
1456
1457 /** @return boolean True if at least one Leyka form is currently on the screen, false otherwise */
1458 function leyka_form_is_screening($widgets_also = true) {
1459
1460 if( !leyka_options()->opt('load_scripts_if_need') || apply_filters('leyka_form_is_screening', false)) {
1461 return true;
1462 }
1463
1464 $template = get_page_template_slug();
1465
1466 $content_has_shortcode = false;
1467 if(get_post()) {
1468 foreach(leyka_get_shortcodes() as $shortcode_tag) {
1469 if(has_shortcode(get_post()->post_content, $shortcode_tag)) {
1470
1471 $content_has_shortcode = true;
1472 break;
1473
1474 }
1475 }
1476 }
1477
1478 return leyka()->form_is_screening ||
1479 is_singular(Leyka_Campaign_Management::$post_type) ||
1480 stristr($template, 'home-campaign_one') !== false ||
1481 stripos($template, 'leyka') !== false ||
1482 $content_has_shortcode ||
1483 ( !!$widgets_also ? leyka_is_widget_active() : false );
1484
1485 }
1486
1487 function leyka_revo_template_displayed() {
1488
1489 $revo_displayed = false;
1490
1491 if(is_singular(Leyka_Campaign_Management::$post_type)) {
1492
1493 $campaign = new Leyka_Campaign(get_post());
1494 if($campaign->template == 'default') {
1495
1496 $leyka_template_data = leyka_get_current_template_data();
1497 $revo_displayed = $leyka_template_data['id'] == 'revo';
1498
1499 } else {
1500 $revo_displayed = $campaign->template == 'revo';
1501 }
1502
1503 } else if(get_post() && has_shortcode(get_post()->post_content, 'leyka_inline_campaign')) {
1504 $revo_displayed = true;
1505 }
1506
1507 return apply_filters('leyka_revo_template_displayed', $revo_displayed);
1508
1509 }
1510
1511 function leyka_modern_template_displayed($template_id = false) {
1512
1513 $modern_template_displayed = false;
1514 $modern_templates = $template_id ? array($template_id) : array('revo', 'star', 'need-help',);
1515
1516 $post = get_post();
1517
1518 if(get_query_var('leyka-screen')) {
1519 $modern_template_displayed = true;
1520 } else if(is_singular(Leyka_Campaign_Management::$post_type)) {
1521
1522 $campaign = new Leyka_Campaign(get_post());
1523 if($campaign->template === 'default') {
1524
1525 $leyka_template_data = leyka_get_current_template_data();
1526 $modern_template_displayed = in_array($leyka_template_data['id'], $modern_templates);
1527
1528 } else {
1529 $modern_template_displayed = in_array($campaign->template, $modern_templates);
1530 }
1531
1532 } else if($post) {
1533
1534 $content_has_shortcodes = false;
1535 foreach(leyka_get_shortcodes() as $shortcode_tag) {
1536 if(has_shortcode(get_post()->post_content, $shortcode_tag)) {
1537
1538 $content_has_shortcodes = true;
1539 break;
1540
1541 }
1542 }
1543
1544 if($content_has_shortcodes) {
1545 $modern_template_displayed = true;
1546 } else if(
1547 has_shortcode($post->post_content, 'leyka_campaign_form')
1548 || has_shortcode($post->post_content, 'leyka_payment_form')
1549 ) {
1550
1551 if(preg_match_all('/'.get_shortcode_regex().'/s', $post->post_content, $matches)) {
1552
1553 $attr_id_match = array();
1554 foreach($matches[2] as $key => $value) {
1555 if(in_array($value, array('leyka_campaign_form', 'leyka_payment_form'))) {
1556
1557 $get = str_replace(" ", "&" , $matches[3][$key] );
1558 parse_str($get, $atts);
1559
1560 if(array_key_exists('id', $atts)) {
1561
1562 $campaign_id = preg_match_all("/(\d+)/", $atts['id'], $attr_id_match);
1563 $campaign_id = isset($attr_id_match[1][0]) ? (int)$attr_id_match[1][0] : 0;
1564
1565 if( !$campaign_id ) {
1566 continue;
1567 }
1568
1569 $campaign = new Leyka_Campaign($campaign_id);
1570 if($campaign && in_array($campaign->template, $modern_templates)) {
1571
1572 $modern_template_displayed = true;
1573 break;
1574
1575 }
1576
1577 }
1578 }
1579 }
1580
1581 }
1582
1583 }
1584
1585 }
1586
1587 return apply_filters('leyka_modern_template_displayed', $modern_template_displayed);
1588
1589 }
1590
1591 function leyka_persistent_campaign_donated() {
1592
1593 $result = is_page(leyka_options()->opt('success_page')) || is_page(leyka_options()->opt('failure_page'));
1594
1595 if($result) {
1596
1597 $donation_id = leyka_remembered_data('donation_id');
1598 $donation = $donation_id ? new Leyka_Donation($donation_id) : null;
1599 $campaign_id = $donation ? $donation->campaign_id : null;
1600 $campaign = $campaign_id ? new Leyka_Campaign($campaign_id) : null;
1601
1602 $result = $campaign && $campaign->campaign_type === 'persistent' && $campaign->template == 'star';
1603
1604 }
1605
1606 return $result;
1607
1608 }
1609
1610 function leyka_success_widget_displayed() {
1611 return leyka_options()->opt_template('show_success_widget_on_success') && is_page(leyka_options()->opt('success_page'));
1612 }
1613
1614 function leyka_failure_widget_displayed() {
1615 return leyka_options()->opt_template('show_failure_widget_on_failure') && is_page(leyka_options()->opt('failure_page'));
1616 }
1617
1618 function leyka_validate_donor_name($name, $is_correctional = false) {
1619 return $name && !$is_correctional ? !preg_match('/[^\\x{0410}-\\x{044F}\w\s\-_\'\.]/iu', $name) : true;
1620 }
1621
1622 function leyka_validate_email($email) {
1623 return $email ? preg_match("/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|expert|[a-z]+)|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i", $email) : true;
1624 }
1625
1626 if( !function_exists('leyka_is_phone_number') ) {
1627 /**
1628 * @param string $phone A phone number to validate. If empty, will always return true.
1629 * @return boolean True if given phone is valid (or empty), false otherwise.
1630 * @deprecated Please use leyka_validate_donor_phone($phone) instead.
1631 */
1632 function leyka_is_phone_number($phone) {
1633 return leyka_validate_donor_phone($phone);
1634 }
1635 }
1636
1637 if( !function_exists('leyka_validate_donor_phone') ) {
1638 /**
1639 * @param string $phone A phone number to validate. If empty, will always return true.
1640 * @return boolean True if given phone is valid (or empty), false otherwise.
1641 */
1642 function leyka_validate_donor_phone($phone) {
1643
1644 $phone = trim($phone);
1645 return $phone ? preg_match('/^[0-9\+\-\. ]{10,}$/i', $phone) : true;
1646
1647 }
1648 }
1649
1650 if( !function_exists('leyka_validate_donor_date') ) {
1651 /**
1652 * @param string $date A date to validate (format: DD.MM.YYYY). If empty, will always return true.
1653 * @return boolean True if given date is valid (or empty), false otherwise.
1654 */
1655 function leyka_validate_donor_date($date) {
1656
1657 $date = trim($date);
1658 return $date ? preg_match('/^[0-9]{2}\.[0-9]{2}\.[0-9]{4}$/i', $date) : true;
1659
1660 }
1661 }
1662
1663 /** @return string URL of a current page, according to permalinks stucture setting. */
1664 function leyka_get_current_url() {
1665
1666 global $wp;
1667 return add_query_arg($wp->query_string, '', home_url($wp->request));
1668
1669 }
1670
1671 // For some reason wp_validate_redirect() aren't get defined in WP 3.6.1, so define it if needed:
1672 if( !function_exists('wp_validate_redirect') ) {
1673 function wp_validate_redirect($location, $default = '') {
1674
1675 $location = trim($location);
1676
1677 // browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//'
1678 if(substr($location, 0, 2) == '//') {
1679 $location = 'http:' . $location;
1680 }
1681
1682 // In php 5 parse_url may fail if the URL query part contains http://, bug #38143
1683 $test = ($cut = strpos($location, '?')) ? substr($location, 0, $cut) : $location;
1684
1685 $lp = parse_url($test);
1686
1687 // Give up if malformed URL
1688 if ( false === $lp )
1689 return $default;
1690
1691 // Allow only http and https schemes. No data:, etc.
1692 if ( isset($lp['scheme']) && !('http' == $lp['scheme'] || 'https' == $lp['scheme']) )
1693 return $default;
1694
1695 // Reject if scheme is set but host is not. This catches urls like https:host.com
1696 // for which parse_url does not set the host field:
1697 if ( isset($lp['scheme']) && !isset($lp['host']) )
1698 return $default;
1699
1700 $wpp = parse_url(home_url());
1701 $allowed_hosts = (array)apply_filters('allowed_redirect_hosts', array($wpp['host']), isset($lp['host']) ? $lp['host'] : '');
1702
1703 if( isset($lp['host']) && ( !in_array($lp['host'], $allowed_hosts) && $lp['host'] != strtolower($wpp['host'])) ) {
1704 $location = $default;
1705 }
1706
1707 return $location;
1708
1709 }
1710 }
1711
1712 /**
1713 * @param $campaign_id int
1714 * @param $limit int|false False to get all donations (unlimited number).
1715 * @return array|false An array of Leyka_Donation objects, or false if wrong campaign ID given.
1716 */
1717 function leyka_get_campaign_donations($campaign_id = false, $limit = false) {
1718
1719 $campaign_id = $campaign_id ? absint($campaign_id) : false;
1720 $limit = (int)$limit > 0 ? (int)$limit : false;
1721
1722 $params = array('post_type' => Leyka_Donation_Management::$post_type, 'post_status' => 'funded', 'meta_query' => array(),);
1723 if($campaign_id) {
1724 $params['meta_query'][] = array('key' => 'leyka_campaign_id', 'value' => $campaign_id, 'compare' => '=',);
1725 }
1726
1727 if($limit) {
1728 $params['posts_per_page'] = $limit;
1729 } else {
1730
1731 $params['posts_per_page'] = -1;
1732 $params['nopaging'] = true;
1733
1734 }
1735
1736 $donations = array();
1737 foreach(get_posts($params) as $donation) {
1738 $donations[] = new Leyka_Donation($donation);
1739 }
1740
1741 return $donations;
1742
1743 }
1744
1745 function leyka_get_donations_archive_url($campaign_id = false) {
1746
1747 if(absint($campaign_id) > 0) {
1748
1749 $campaign = get_post($campaign_id);
1750
1751 $donations_permalink = trim(get_permalink($campaign_id), '/');
1752 if(mb_strpos($donations_permalink, '?')) {
1753 $donations_permalink = home_url('?post_type='.Leyka_Donation_Management::$post_type.'&leyka_campaign_filter='.$campaign->post_name);
1754 } else {
1755 $donations_permalink = $donations_permalink.'/donations/';
1756 }
1757
1758 } else {
1759 $donations_permalink = get_option('permalink-structure') ?
1760 home_url('/donations/') : home_url('?post_type='.Leyka_Donation_Management::$post_type);
1761 }
1762
1763 return $donations_permalink;
1764
1765 }
1766
1767 function leyka_remembered_data($name, $value = null, $delete = false) {
1768
1769 $name = mb_stripos($name, 'leyka_') === false ? 'leyka_'.$name : $name;
1770
1771 if($value) {
1772 return headers_sent() ?
1773 null : setcookie($name, trim($value), current_time('timestamp') + 60*60, COOKIEPATH, COOKIE_DOMAIN, false);
1774 } else if( !!$delete ) {
1775 return headers_sent() ?
1776 null : setcookie($name, '', current_time('timestamp') - 3600, COOKIEPATH, COOKIE_DOMAIN, false);
1777 } else {
1778 return empty($_COOKIE[$name]) ? '' : trim($_COOKIE[$name]);
1779 }
1780
1781 }
1782
1783 function leyka_calculate_donation_total_amount($donation = false, $amount = 0.0, $pm_full_id = '') {
1784
1785 if($donation) {
1786 $donation = leyka_get_validated_donation($donation);
1787 }
1788
1789 $amount = $amount ? $amount : ($donation ? $donation->amount : floatval($amount));
1790 $pm_full_id = $pm_full_id ? $pm_full_id : ($donation ? $donation->pm_full_id : false);
1791
1792 if( !$amount || !$pm_full_id ) {
1793 return 0.0;
1794 }
1795
1796 $commission = leyka_options()->opt('commission');
1797 $commission = empty($commission[$pm_full_id]) ? 0.0 : $commission[$pm_full_id]/100.0;
1798
1799 return $commission && $commission > 0.0 ? $amount - round($amount*$commission, 2) : $amount;
1800
1801 }
1802
1803 function leyka_get_pm_commission($pm_full_id) {
1804
1805 $commission = leyka_options()->opt('commission');
1806
1807 return empty($commission[$pm_full_id]) ? 0.0 : $commission[$pm_full_id]/100.0;
1808
1809 }
1810
1811 /**
1812 * A helper function to insert posts manually. Used only when wp_insert_post() leads to notices & fatal errors.
1813 *
1814 * @param $post_data array New page data.
1815 * @return integer|false
1816 */
1817 function leyka_manually_insert_page(array $post_data) {
1818
1819 global $wpdb;
1820
1821 $post_date = current_time('mysql');
1822 $wpdb->insert($wpdb->prefix.'posts', array(
1823 'post_type' => 'page',
1824 'post_status' => 'publish',
1825 'post_title' => $post_data['post_title'],
1826 'post_content' => $post_data['post_content'],
1827 'post_name' => $post_data['post_name'],
1828 'post_author' => get_current_user_id(),
1829 'post_excerpt' => '',
1830 'post_date' => $post_date,
1831 'post_date_gmt' => get_gmt_from_date($post_date),
1832 'post_modified' => $post_date,
1833 'post_modified_gmt' => get_gmt_from_date($post_date),
1834 ));
1835
1836 return $wpdb->insert_id;
1837
1838 }
1839
1840 /** @return array An assoc array of all Leyka options from leyka-option-meta file and some environment data */
1841 function leyka_get_env_and_options() {
1842 return array_merge(leyka_get_all_options(), leyka_get_env(), leyka_get_db_stats());
1843 }
1844
1845 function humanaize_debug_data($debug_data) {
1846
1847 $humanized_options = array();
1848
1849 foreach($debug_data['options'] as $k => $v) {
1850 $option_info = leyka_options()->get_info_of($k);
1851 $option_title = empty($option_info['title']) || $option_info['title'] == $k ? $k : $option_info['title'];
1852 $humanized_options[$option_title] = $v;
1853 }
1854 $debug_data['options'] = $humanized_options;
1855
1856 foreach(array_keys($debug_data['plugins']) as $status) {
1857
1858 $humanized_options = array();
1859
1860 foreach($debug_data['plugins'][$status] as $plugin) {
1861 $humanized_options[] = sprintf("%s %s", $plugin['name'], $plugin['ver']);
1862 }
1863
1864 $debug_data['plugins'][$status] = $humanized_options;
1865
1866 }
1867
1868 return $debug_data;
1869
1870 }
1871
1872 function format_debug_data($list, $level = 0) {
1873
1874 $fomatted_ret = '';
1875
1876 if($level > 0) {
1877 ksort($list);
1878 }
1879
1880 foreach($list as $k => $v) {
1881 $fomatted_ret .= str_repeat(" ", $level) . "<strong>$k:</strong> ";
1882 if(is_array($v)) {
1883 $fomatted_ret .= "\n" . format_debug_data($v, $level + 1) . ($level == 0 ? "\n" : "");
1884 }
1885 else {
1886 $fomatted_ret .= trim($v) . "\n";
1887 }
1888 }
1889
1890 return $fomatted_ret;
1891
1892 }
1893
1894 /** @return array An assoc array of some db stats */
1895 function leyka_get_db_stats() {
1896
1897 global $wpdb;
1898
1899 $query_time_start = microtime(true);
1900
1901 $payments_count = $wpdb->get_var(
1902 $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->posts WHERE post_type = %s", Leyka_Donation_Management::$post_type)
1903 );
1904
1905 $all_posts_count = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts");
1906
1907 $db_stats = array(
1908 'db_stats' =>array(
1909 'all_posts_count' => $all_posts_count,
1910 'payments_count' => $payments_count,
1911 'query_exec_time' => sprintf("%.10f", microtime(true) - $query_time_start),
1912 ),
1913 );
1914
1915 return $db_stats;
1916
1917 }
1918
1919 /** @return array An assoc array of some environment data */
1920 function leyka_get_env() {
1921
1922 if( !function_exists('get_plugins') ) {
1923 require_once ABSPATH.'wp-admin/includes/plugin.php';
1924 }
1925
1926 global $wp_version;
1927
1928 $res = array(
1929 'wp_core' => $wp_version,
1930 'env' => array('php_version' => phpversion(), 'php_extensions' => get_loaded_extensions()),
1931 );
1932
1933 // Server data:
1934 $forbidden_data = array(
1935 'MIBDIRS', 'OPENSSL_CONF', 'HTTP_COOKIE', 'PATH', 'SystemRoot', 'COMSPEC', 'WINDIR', 'DOCUMENT_ROOT',
1936 'CONTEXT_DOCUMENT_ROOT', 'SCRIPT_FILENAME', 'APACHE_LOG_DIR', 'APACHE_RUN_GROUP', 'APACHE_RUN_USER', 'LANG', 'PWD',
1937 'APACHE_LOCK_DIR', 'APACHE_PID_FILE', 'APACHE_RUN_DIR', 'APACHE_CONFDIR', 'argc', 'argv', 'PHP_SELF', 'SCRIPT_NAME',
1938 'REDIRECT_URL', 'REMOTE_PORT', 'REQUEST_SCHEME', 'SERVER_PORT', 'SERVER_ADDR', 'SERVER_SIGNATURE', 'CONTENT_TYPE',
1939 'HTTP_ACCEPT', 'CONTENT_LENGTH', 'HTTP_CONNECTION', 'REQUEST_URI', 'REMOTE_ADDR',
1940 );
1941 foreach($_SERVER as $key => $value) {
1942
1943 if(in_array($key, $forbidden_data)) {
1944 continue;
1945 }
1946
1947 $res['env']['server_'.$key] = is_array($value) ? serialize($value) : strip_tags($value);
1948
1949 }
1950 foreach($_ENV as $key => $value) {
1951
1952 if(in_array($key, $forbidden_data)) {
1953 continue;
1954 }
1955
1956 $res['env']['env_'.$key] = is_array($value) ? serialize($value) : strip_tags($value);
1957
1958 }
1959
1960 // WP core/Theme/plugins data:
1961 $res['plugins'] = array('active' => array(), 'inactive' => array(),);
1962
1963 foreach(get_plugins() as $key => $plugin_data) {
1964 if(in_array($key, get_option('active_plugins'))) {
1965 $res['plugins']['active'][] = array('name' => $plugin_data['Name'], 'ver' => $plugin_data['Version']);
1966 } else {
1967 $res['plugins']['inactive'][] = array('name' => $plugin_data['Name'], 'ver' => $plugin_data['Version']);
1968 }
1969 }
1970
1971 $theme = wp_get_theme();
1972 $res['theme'] = array(
1973 'name' => $theme->Name,
1974 'ver' => $theme->Version,
1975 'template' => $theme->template,
1976 'parent' => $theme->parent ?
1977 array('name' => $theme->Name, 'ver' => $theme->Version, 'template' => $theme->parent->template,) : array(),
1978 );
1979
1980 return $res;
1981
1982 }
1983
1984 /** @return array An assoc array of Leyka options (from leyka-options-meta) & settings (other "leyka_something"-named options) */
1985 function leyka_get_all_options() {
1986
1987 $res = array('options' => array(), 'settings' => array());
1988 $leyka_options_keys = leyka_options()->get_options_names();
1989
1990 $forbidden_options = array(
1991 'person_pd_terms_text', 'person_terms_of_service_text', 'pd_terms_text', 'terms_of_service_text', 'org_bank_account',
1992 'email_thanks_text', 'org_face_fio_ip', 'org_face_fio_rp', 'org_address', 'person_full_name', 'person_address',
1993 '_transient_leyka_wizards_activities', '_transient_leyka_default_campaign_id', 'permalinks_flushed', 'org_bank_name',
1994 'org_actual_address_differs', 'plugin_stats_option_sync_done', 'widget_leyka_donations_list', 'org_bank_bic', 'org_inn',
1995 'widget_leyka_campaigns_list', 'paypal_client_id', 'paypal_api_signature', 'paypal_api_password', 'paypal_api_username',
1996 'quittance_redirect_page', 'rbk_api_web_hook_key', 'rbk_api_key', 'rbk_shop_id', 'chronopay_ip', 'chronopay_shared_sec',
1997 'chronopay_use_payment_uniqueness_control', 'chronopay_card_rebill_product_id_eur', 'org_bank_corr_account', 'org_kpp',
1998 'chronopay_card_rebill_product_id_usd', 'chronopay_card_rebill_product_id_rur', 'yandex-yandex_card_private_key_password',
1999 'yandex-yandex_card_private_key_path', 'yandex-yandex_card_certificate_path', 'org_face_position', 'yandex_secret_key',
2000 'yandex_shop_password', 'yandex_shop_article_id', 'yandex_scid', 'yandex_shop_id', 'cp_ip', 'cp_public_id',
2001 'options:robokassa_shop_password2', 'robokassa_shop_password1', 'robokassa_shop_id', 'chronopay_card_product_id_rur',
2002 'chronopay_card_product_id_usd', 'chronopay_card_product_id_eur', 'text_box_details', 'yandex_money_account',
2003 'yandex_money_secret', 'mixplat-mobile_details', 'mixplat-sms_default_campaign_id', 'mixplat-sms_description',
2004 'mixplat-sms_details', 'mixplat_service_id', 'mixplat_secret_key', 'paymaster_merchant_id', 'paymaster_secret_word',
2005 'paymaster_hash_method', 'failure_page', 'success_page', 'pd_terms_page', 'terms_of_service_page',
2006 );
2007
2008 foreach(wp_load_alloptions() as $name => $value) {
2009
2010 $name_clear = strpos($name, 'leyka_') === 0 ? substr_replace($name, '', 0, strlen('leyka_')) : $name;
2011
2012 if(in_array($name_clear, $forbidden_options) || preg_match("/^knd_val_hash_leyka_/", $name)) {
2013 continue;
2014 } else if(in_array($name_clear, $leyka_options_keys)) {
2015 $res['options'][$name_clear] = $value;
2016 } else if(stristr($name, 'leyka_') !== false && !preg_match('/^(leyka_)(.+)(_description)$/i', $name)) {
2017 $res['settings'][$name] = $value;
2018 }
2019
2020 }
2021
2022 return $res;
2023
2024 }
2025
2026 function leyka_is_tab_valid($tab_id) {
2027
2028 $tab_options = Leyka_Options_Allocator::get_instance()->get_tab_options($tab_id);
2029
2030 if( !$tab_options ) {
2031 return false;
2032 }
2033
2034 foreach($tab_options as $key => $option_params) {
2035
2036 if($key === 'section') {
2037
2038 if( !empty($option_params['options']) ) { // Noramal section - validate all options
2039 foreach($option_params['options'] as $option_id) {
2040 if( !leyka_options()->is_valid($option_id) ) {
2041 return false;
2042 }
2043 }
2044 } else if( !empty($option_params['tabs']) ) {
2045
2046 foreach($option_params['tabs'] as $sub_tab_id => $sub_tab_content) {
2047
2048 if( !empty($sub_tab_content['sections']) ) {
2049 foreach($sub_tab_content['sections'] as $sub_section) {
2050 if( !empty($sub_section['options']) ) {
2051 foreach($sub_section['options'] as $sub_section_option_id) {
2052 if( !leyka_options()->is_valid($sub_section_option_id) ) {
2053 return false;
2054 }
2055 }
2056 }
2057 }
2058 }
2059
2060 }
2061
2062 }
2063
2064 } else if( !leyka_options()->is_valid($key) ) { // Validate single option
2065 return false;
2066 }
2067
2068 }
2069
2070 return true;
2071
2072 }
2073
2074 if( !function_exists('array_key_last') ) {
2075 function array_key_last($array) {
2076
2077 if( !is_array($array) || empty($array) ) {
2078 return null;
2079 }
2080
2081 return array_keys($array)[count($array) - 1];
2082
2083 }
2084 }
2085
2086 if( !function_exists('leyka_get_delta_percent') ) {
2087 function leyka_get_delta_percent($prev_value, $new_value, $handle_incomparabe_cases = true) {
2088
2089 $handle_incomparabe_cases = !!$handle_incomparabe_cases;
2090
2091 if( !$prev_value ) {
2092 $delta_percent = $handle_incomparabe_cases ? NULL : ($new_value ? 100.0 : 0);
2093 } else {
2094 $delta_percent = $handle_incomparabe_cases && !$new_value ?
2095 NULL : round(100.0*($new_value - $prev_value)/$prev_value, 2);
2096 }
2097
2098 return $delta_percent;
2099
2100 }
2101 }
2102
2103 if( !function_exists('leyka_amount_format') ) {
2104 function leyka_amount_format($amount) {
2105
2106 // Display amount decimal part only if there is one:
2107 $amount = round((float)$amount, 2);
2108 return (abs($amount) - abs((int)$amount) > 0) ? number_format_i18n($amount, 2) : number_format_i18n($amount);
2109
2110 }
2111 }
2112
2113 abstract class Leyka_Singleton {
2114
2115 protected static $_instance = null;
2116
2117 /**
2118 * @param $params array Assoc. array of Singleton object params. Not required.
2119 * @return static
2120 */
2121 public static function get_instance(array $params = array()) {
2122
2123 if(null === static::$_instance) {
2124 static::$_instance = new static($params);
2125 }
2126
2127 return static::$_instance;
2128
2129 }
2130
2131 final protected function __clone() {}
2132
2133 protected function __construct(array $params = array()) {
2134 }
2135
2136 }
2137
2138 if( !function_exists('leyka_save_option') ) {
2139 function leyka_save_option($setting_id) {
2140
2141 $option_type = leyka_options()->get_type_of($setting_id);
2142
2143 if($option_type === 'checkbox') {
2144 leyka_options()->opt($setting_id, isset($_POST["leyka_$setting_id"]) ? 1 : 0);
2145 } elseif($option_type == 'multi_checkbox') {
2146
2147 if(isset($_POST["leyka_$setting_id"]) && leyka_options()->opt($setting_id) !== $_POST["leyka_$setting_id"]) {
2148 leyka_options()->opt($setting_id, (array)$_POST["leyka_$setting_id"]);
2149 }
2150
2151 } else if($option_type === 'html' || $option_type === 'rich_html') {
2152
2153 if(isset($_POST["leyka_$setting_id"]) && leyka_options()->opt($setting_id) !== $_POST["leyka_$setting_id"]) {
2154 leyka_options()->opt($setting_id, esc_attr(stripslashes($_POST["leyka_$setting_id"])));
2155 }
2156
2157 } else if(mb_stristr($option_type, 'custom_') !== false && isset($_POST["leyka_$setting_id"])) { // Custom field types
2158 do_action("leyka_save_custom_option-$setting_id", $_POST["leyka_$setting_id"]);
2159 } else if(isset($_POST["leyka_$setting_id"])) { // Simple field types
2160
2161 $old_value = leyka_options()->opt($setting_id);
2162 if($old_value != $_POST["leyka_$setting_id"]) {
2163 leyka_options()->opt($setting_id, esc_attr(stripslashes($_POST["leyka_$setting_id"])));
2164 }
2165
2166 do_action("leyka_after_save_option-$setting_id", $old_value, $_POST["leyka_$setting_id"]);
2167
2168 }
2169
2170 }
2171 }
2172
2173 if( !function_exists('leyka_save_commission_field') ) {
2174 /** An utility function to save the Gateways commission fields. For "leyka_save_custom_option-commission" hook only. */
2175 function leyka_save_commission_field() {
2176 if( !empty($_POST['leyka_commission']) && is_array($_POST['leyka_commission']) ) {
2177
2178 foreach($_POST['leyka_commission'] as &$commission) {
2179 $commission = $commission >= 0.0 ? (float)$commission : 0.0;
2180 }
2181
2182 leyka_options()->opt('commission', array_merge(leyka_options()->opt('commission'), $_POST['leyka_commission']));
2183
2184 }
2185 }
2186 }
2187 add_action('leyka_save_custom_option-commission', 'leyka_save_commission_field');
2188
2189 if( !function_exists('leyka_add_editor_css') ) {
2190 function leyka_add_editor_css() {
2191 add_editor_style(LEYKA_PLUGIN_BASE_URL.'assets/css/editor.css');
2192 }
2193 }
2194 add_action('after_setup_theme', 'leyka_add_editor_css');
2195
2196 if( !function_exists('leyka_get_l18n_date') ) {
2197 function leyka_get_i18n_date($timestamp) {
2198 return date_i18n(get_option('date_format'), (int)$timestamp);
2199 }
2200 }
2201 if( !function_exists('leyka_get_l18n_time') ) {
2202 function leyka_get_i18n_time($timestamp) {
2203 return date_i18n(get_option('time_format'), (int)$timestamp);
2204 }
2205 }
2206 if( !function_exists('leyka_get_l18n_datetime') ) {
2207 function leyka_get_i18n_datetime($timestamp) {
2208 return date_i18n(get_option('date_format').', '.get_option('time_format'), (int)$timestamp);
2209 }
2210 }
2211
2212 // Localize tags to replace in JS:
2213 if( !function_exists('leyka_localize_rich_html_text_tags') ) {
2214 function leyka_localize_rich_html_text_tags() {
2215
2216 $is_legal = leyka_options()->opt('receiver_legal_type') === 'legal';
2217
2218 wp_localize_script('leyka-settings', 'leykaRichHTMLTags', array(
2219 'termsKeys' => array(
2220 array(
2221 '#LEGAL_NAME#',
2222 '#LEGAL_FACE#',
2223 '#LEGAL_FACE_POSITION#',
2224 '#LEGAL_ADDRESS#',
2225 '#STATE_REG_NUMBER#',
2226 '#KPP#',
2227 '#INN#',
2228 '#BANK_ACCOUNT#',
2229 '#BANK_NAME#',
2230 '#BANK_BIC#',
2231 '#BANK_CORR_ACCOUNT#',
2232 '#SITE_NAME#',
2233 '#SITE_URL#',
2234 '#ORG_NAME#',
2235 '#ORG_SHORT_NAME#',
2236 ),
2237 array(
2238 $is_legal ? leyka_options()->opt('org_full_name') : leyka_options()->opt('person_full_name'),
2239 $is_legal ? leyka_options()->opt('org_face_fio_ip') : leyka_options()->opt('person_full_name'),
2240 $is_legal ? leyka_options()->opt('org_face_position') : '',
2241 $is_legal ? leyka_options()->opt('org_address') : leyka_options()->opt('person_address'),
2242 $is_legal ? leyka_options()->opt('org_state_reg_number') : '',
2243 $is_legal ? leyka_options()->opt('org_kpp') : '',
2244 $is_legal ? leyka_options()->opt('org_inn') : leyka_options()->opt('person_inn'),
2245 $is_legal ? leyka_options()->opt('org_bank_account') : leyka_options()->opt('person_bank_account'),
2246 $is_legal ? leyka_options()->opt('org_bank_name') : leyka_options()->opt('person_bank_name'),
2247 $is_legal ? leyka_options()->opt('org_bank_bic') : leyka_options()->opt('person_bank_bic'),
2248 $is_legal ? leyka_options()->opt('org_bank_corr_account') : leyka_options()->opt('person_bank_corr_account'),
2249 get_bloginfo('name'),
2250 home_url(),
2251 $is_legal ? leyka_options()->opt('org_full_name') : leyka_options()->opt('person_full_name'),
2252 $is_legal ? leyka_options()->opt('org_short_name') : leyka_options()->opt('person_full_name'),
2253 ),
2254 ),
2255 'pdKeys' => array(
2256 array(
2257 '#LEGAL_NAME#',
2258 '#LEGAL_ADDRESS#',
2259 '#SITE_URL#',
2260 '#PD_TERMS_PAGE_URL#',
2261 '#ADMIN_EMAIL#',
2262 ),
2263 array(
2264 $is_legal ? leyka_options()->opt('org_full_name') : leyka_options()->opt('person_full_name'),
2265 $is_legal ? leyka_options()->opt('org_address') : leyka_options()->opt('person_address'),
2266 home_url(),
2267 leyka_get_terms_of_pd_usage_page_url(),
2268 get_option('admin_email'),
2269 ),
2270 ),
2271 ));
2272
2273 }
2274 }
2275
2276 function leyka_is_donor_account() {
2277
2278 if( !leyka()->opt('donor_accounts_available') ) {
2279 return false;
2280 }
2281
2282 return stristr($_SERVER['REQUEST_URI'], 'donor-account') !== false;
2283
2284 }
2285
2286 function leyka_get_upload_max_filesize() {
2287
2288 if(defined('WP_MEMORY_LIMIT')) {
2289 $max_filesize = WP_MEMORY_LIMIT;
2290 } else {
2291 $max_filesize = ini_get('upload_max_filesize');
2292 }
2293
2294 return $max_filesize;
2295
2296 }
2297
2298 function leyka_use_leyka_campaign_template($template) {
2299
2300 $campaign_id = null;
2301
2302 if(is_singular(Leyka_Campaign_Management::$post_type)) {
2303 $campaign_id = get_post()->ID;
2304 } else if(is_page(leyka_options()->opt('success_page')) || is_page(leyka_options()->opt('failure_page'))) {
2305
2306 $donation_id = leyka_remembered_data('donation_id');
2307 $donation = $donation_id ? new Leyka_Donation($donation_id) : null;
2308 $campaign_id = $donation ? $donation->campaign_id : null;
2309
2310 }
2311
2312 if($campaign_id) {
2313
2314 $campaign = leyka_get_validated_campaign($campaign_id);
2315 if($campaign && $campaign->campaign_type === 'persistent' && $campaign->template === 'star') {
2316 $template = LEYKA_PLUGIN_DIR.'templates/campaign/type-persistent.php';
2317 }
2318
2319 }
2320
2321 return $template;
2322
2323 }
2324 add_filter('single_template', 'leyka_use_leyka_campaign_template', 10, 1);
2325 add_filter('page_template', 'leyka_use_leyka_campaign_template', 10, 1);
2326
2327 function leyka_use_leyka_donations_list_template($archive_template) {
2328
2329 $leyka_screen = get_query_var('leyka-screen');
2330 if(is_post_type_archive(Leyka_Donation_Management::$post_type)) {
2331 switch($leyka_screen) {
2332 case 'account':
2333 $archive_template = LEYKA_PLUGIN_DIR.'templates/account/account.php';
2334 break;
2335 case 'login':
2336 $archive_template = LEYKA_PLUGIN_DIR.'templates/account/login.php';
2337 break;
2338 case 'reset-password':
2339 $archive_template = LEYKA_PLUGIN_DIR.'templates/account/reset-password.php';
2340 break;
2341 case 'cancel-subscription':
2342 $archive_template = LEYKA_PLUGIN_DIR.'templates/account/cancel-subscription.php';
2343 break;
2344 default:
2345 }
2346 }
2347
2348 return $archive_template;
2349
2350 }
2351 add_filter('archive_template', 'leyka_use_leyka_donations_list_template');
2352
2353 function leyka_get_website_tech_support_email() {
2354 return leyka()->opt('tech_support_email') ? leyka()->opt('tech_support_email') : get_option('admin_email');
2355 }
2356
2357 function leyka_get_cancel_subscription_reasons() {
2358 return array(
2359 'uncomfortable_pm' => __('Unconfortable payment method', 'leyka'),
2360 'too_much' => __('Too much donation', 'leyka'),
2361 'not_match' => __('Does not meet my interests', 'leyka'),
2362 'better_use' => __('I have found better use of money', 'leyka'),
2363 'other' => __('Other reason', 'leyka'),
2364 );
2365 }
2366
2367 function get_donor_init_recurring_donation_for_campaign($donor_user, $campaign_id) {
2368
2369 $donations = new WP_Query(array(
2370 'post_type' => Leyka_Donation_Management::$post_type,
2371 'post_status' => 'funded',
2372 'post_parent' => 0,
2373 'meta_query' => array(
2374 'relation' => 'AND',
2375 array('key' => 'leyka_payment_type', 'value' => 'rebill'),
2376 array('key' => 'leyka_campaign_id', 'value' => $campaign_id),
2377 array(
2378 'relation' => 'OR',
2379 array('key' => 'leyka_recurrents_cancelled', 'value' => false),
2380 array('key' => 'leyka_recurrents_cancelled', 'compare' => 'NOT EXISTS'),
2381 ),
2382 array(
2383 'relation' => 'OR',
2384 array('key' => 'leyka_cancel_recurring_requested', 'value' => false),
2385 array('key' => 'leyka_cancel_recurring_requested', 'compare' => 'NOT EXISTS'),
2386 ),
2387 array(
2388 'relation' => 'OR',
2389 array('key' => 'leyka_donor_email', 'value' => $donor_user->user_email),
2390 array('key' => 'leyka_donor_account', 'value' => $donor_user->ID),
2391 ),
2392 ),
2393 'posts_per_page' => 1,
2394 'orderby' => 'ID',
2395 'order' => 'ASC',
2396 ));
2397
2398 return $donations->have_posts() ? new Leyka_Donation($donations->posts[0]) : null;
2399
2400 }
2401
2402 function leyka_get_dm_list_or_alternatives() {
2403
2404 $dm_list = array();
2405
2406 foreach(explode(',', leyka_options()->opt('leyka_donations_managers_emails')) as $email) {
2407 if($email) {
2408 $dm_list[] = $email;
2409 }
2410 }
2411
2412 if( !$dm_list ) {
2413
2414 $alt_emails = array(leyka()->opt('tech_support_email'), get_bloginfo('admin_email'),);
2415
2416 foreach($alt_emails as $alt_email) {
2417
2418 $alt_email = trim($alt_email);
2419 if($alt_email) {
2420 $dm_list[] = $alt_email;
2421 break;
2422 }
2423
2424 }
2425
2426 }
2427
2428 return $dm_list;
2429
2430 }
2431
2432 /** Service function to prepare a singular object data value for export as a CSV cell. */
2433 function leyka_export_data_prepare($text) {
2434 return '"'.str_replace(array(';', '"'), array('', ''), $text).'"';
2435 }
2436
2437 /** Service function to prepare some object data array for export as a CSV line. */
2438 function leyka_prepare_data_line_for_export(array $line_data) {
2439
2440 foreach($line_data as &$data) {
2441 $data = leyka_export_data_prepare($data);
2442 }
2443
2444 return $line_data;
2445
2446 }
2447
2448 // By default, wp_attachment_is() doesn't treat SVGs as images. It's a f*ckin oppression, we think.
2449 if( !function_exists('leyka_attachment_is') ) {
2450 function leyka_attachment_is($type, $attachment = null) {
2451
2452 if($type !== 'image') {
2453 return wp_attachment_is($type, $attachment);
2454 }
2455
2456 $attachment = get_post($attachment);
2457 if( !$attachment ) {
2458 return false;
2459 }
2460
2461 $file = get_attached_file($attachment->ID);
2462 if( !$file ) {
2463 return false;
2464 }
2465
2466 $check = wp_check_filetype($file);
2467
2468 return empty($check['ext']) ? false : in_array($check['ext'], array('jpg', 'jpeg', 'jpe', 'gif', 'png', 'svg',));
2469
2470 }
2471 }
2472
2473 if( !function_exists('leyka_delete_dir') ) {
2474 /**
2475 * Recursively delete given directory & all it's files.
2476 *
2477 * @param $path string Absolute path to dir.
2478 * @return boolean True if deletion succeeded, false otherwise.
2479 */
2480 function leyka_delete_dir($path) {
2481
2482 if(leyka_options()->opt('plugin_debug_mode')) {
2483 return file_exists($path) && is_dir($path);
2484 }
2485
2486 if( !$path || $path === '/' ) {
2487 return false;
2488 }
2489
2490 return is_file($path) ? @unlink($path) : (array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path));
2491
2492 }
2493 }
2494
2495 /** @todo Move the function to the special GA integration class */
2496 if( !function_exists('leyka_gua_generate_uuid') ) {
2497 function leyka_gua_generate_uuid() {
2498 return '1234567890.1234567890';
2499 }
2500 }
2501
2502 /** @todo Move the function to the special GA integration class */
2503 if( !function_exists('leyka_gua_get_client_id') ) {
2504 function leyka_gua_get_client_id() {
2505
2506 if( !empty($_COOKIE['_ga']) ) {
2507
2508 list($version, $domain_depth, $cid1, $cid2) = explode('.', $_COOKIE['_ga'], 4);
2509
2510 $contents = array('version' => $version, 'domainDepth' => $domain_depth, 'cid' => $cid1.'.'.$cid2);
2511 $cid = $contents['cid'];
2512
2513 } else {
2514 $cid = leyka_gua_generate_uuid();
2515 }
2516
2517 return $cid;
2518
2519 }
2520 }
2521
2522 if( !function_exists('leyka_get_client_ip') ) {
2523 function leyka_get_client_ip() {
2524
2525 $client_ip = getenv('HTTP_CLIENT_IP') ? :
2526 getenv('HTTP_X_FORWARDED_FOR') ? :
2527 getenv('HTTP_X_FORWARDED') ? :
2528 getenv('HTTP_FORWARDED_FOR') ? :
2529 getenv('HTTP_FORWARDED') ? :
2530 getenv('REMOTE_ADDR');
2531
2532 $client_ip = is_array($client_ip) ? reset($client_ip) : $client_ip;
2533
2534 return trim($client_ip);
2535
2536 }
2537 }
2538
2539 /** Some gateways give their callbacks IPs only as CIDR ranges. */
2540 if( !function_exists('is_ip_in_range') ) {
2541 function is_ip_in_range($ip, $range) {
2542
2543 $range .= strpos(trim($range), '/') == false ? '/32' : ''; // No CIDR range is given, add the default one
2544
2545 list($net, $mask) = explode('/', $range);
2546
2547 $ip_net = ip2long($net);
2548 $ip_mask = ~((1 << (32 - $mask)) - 1);
2549
2550 $ip_ip = ip2long($ip);
2551
2552 $ip_ip_net = $ip_ip & $ip_mask;
2553
2554 return $ip_ip_net == $ip_net;
2555
2556 }
2557 }