PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 2.8.16
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v2.8.16
3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 All 261 releases
wpfunnels / includes / class-wpfnl.php

class-wpfnl.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 2.8.16, at includes/class-wpfnl.php

761 lines 22.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The core plugin class.
4 *
5 * This is used to define internationalization, admin-specific hooks, and
6 * public-facing site hooks.
7 *
8 * Also maintains the unique identifier of this plugin as well as the current
9 * version of the plugin.
10 *
11 * @since 1.0.0
12 * @package Wpfnl
13 * @subpackage Wpfnl/includes
14 * @author RexTheme <[email protected]>
15 */
16 namespace WPFunnels;
17
18 use Wpfnl_i18n;
19 use Wpfnl_Loader;
20 use Wpfnl_Logger;
21 use WPFunnels\Admin\OptinField\OptinField;
22 use WPFunnels\Admin\SetupWizard;
23 use WPFunnels\Admin\Wpfnl_Admin as Admin;
24 use WPFunnels\Admin\Notices\Notice;
25 use WPFunnels\Admin\Banner\SpecialOccasionBanner;
26 use WPFunnels\Ajax_Handler\Ajax_Handler;
27 use WPFunnels\Classes\OrderBumpActions\Wpfnl_Order_Bump_Action;
28 use WPFunnels\Compatibility\CartLift\Wpfnl_Cart_Lift_Compatibility;
29 use WPFunnels\Compatibility\SlimSeo\Wpfnl_Slim_Seo_Compatibility;
30 use WPFunnels\Frontend\Wpfnl_Public;
31 use WPFunnels\Frontend\Wpfnl_Public as Frontend;
32 use WPFunnels\CPT\Wpfnl_CPT as CPT;
33 use WPFunnels\Data_Store\Wpfnl_Funnel_Store_Data as Funnel_Store;
34 use WPFunnels\Data_Store\Wpfnl_Steps_Store_Data as Step_Store;
35 use WPFunnels\Menu\Wpfnl_Menus as Menu;
36 use WPFunnels\Modules\Wpfnl_Modules_Manager as Module_Manager;
37 use WPFunnels\Rest\Server;
38 // use WPFunnels\Shortcodes\Wpfnl_Shortcode;
39 use WPFunnels\Shortcodes\Wpfnl_Shortcodes;
40 use WPFunnels\Widgets\Wpfnl_Widgets_Manager as Widget_Manager;
41 use WPFunnels\Batch\Elementor\Wpfnl_Batch;
42 use WPFunnels\Meta\Wpfnl_Default_Meta;
43 use WPFunnels\Compatibility\Wpfnl_Compatibility;
44
45
46
47 /**
48 * The file that defines the core plugin class
49 *
50 * A class definition that includes attributes and functions used across both the
51 * public-facing side of the site and the admin area.
52 *
53 * @link https://rextheme.com
54 * @since 1.0.0
55 *
56 * @package Wpfnl
57 * @subpackage Wpfnl/includes
58 */
59
60 class Wpfnl
61 {
62
63 /**
64 * Instance.
65 *
66 * Holds the plugin instance.
67 *
68 * @since 1.0.0
69 * @access public
70 * @static
71 *
72 * @var Wpfnl
73 */
74 public static $instance = null;
75
76 public $module_manager;
77
78 public $admin;
79
80 public $plugin_public;
81
82 public $template_manager;
83
84 public $menu;
85
86 public $cpt;
87
88 public $funnel_store;
89
90 public $step_store;
91
92 public $batch;
93
94 public $helper;
95
96 public $widget_manager;
97
98 public $page_templates;
99
100
101 public $order_bump_actions;
102
103 public $meta;
104
105 public $frontend;
106
107 public $log;
108
109 public $shortcodes;
110 public $shortcode;
111
112 /**
113 * Admin notice object
114 *
115 * @var string $admin_notice
116 */
117 protected $admin_notice;
118
119
120 /**
121 * Admin banner object
122 *
123 * @var string $admin_banner
124 */
125 protected $admin_banner;
126
127 protected $optin_field;
128
129 /**
130 * The loader that's responsible for maintaining and registering all hooks that power
131 * the plugin.
132 *
133 * @since 1.0.0
134 * @access protected
135 * @var Wpfnl_Loader $loader Maintains and registers all hooks for the plugin.
136 */
137 protected $loader;
138
139 /**
140 * The unique identifier of this plugin.
141 *
142 * @since 1.0.0
143 * @access protected
144 * @var string $plugin_name The string used to uniquely identify this plugin.
145 */
146 protected $plugin_name;
147
148
149 /**
150 * Object variable for Compatibility class
151 *
152 * @since
153 * @access protected
154 * @var $compatibility
155 */
156 protected $compatibility;
157
158 /**
159 * The current version of the plugin.
160 *
161 * @since 1.0.0
162 * @access protected
163 * @var string $version The current version of the plugin.
164 */
165 protected $version;
166
167
168 /**
169 * Ajax handler
170 *
171 * @var $ajax_handler
172 */
173 protected $ajax_handler;
174
175
176 /**
177 * Object variable for Cart_Lift_Compatibility class
178 *
179 * @since
180 * @access protected
181 * @var $cart_lift
182 */
183 protected $cart_lift;
184
185
186 /**
187 * Object variable for Slim_Seo_Compatibility class
188 *
189 * @since
190 * @access protected
191 * @var $slim_seo
192 */
193 protected $slim_seo;
194
195 /**
196 * Instance.
197 *
198 * Ensures only one instance of the plugin class is loaded or can be loaded.
199 *
200 * @since 1.0.0
201 * @access public
202 * @static
203 *
204 * @return Wpfnl An instance of the class.
205 */
206 public static function get_instance()
207 {
208 if (is_null(self::$instance)) {
209 self::$instance = new self();
210 do_action('wpfunnels/loaded');
211 }
212 return self::$instance;
213 }
214
215
216 /**
217 * Define the core functionality of the plugin.
218 *
219 * Set the plugin name and the plugin version that can be used throughout the plugin.
220 * Load the dependencies, define the locale, and set the hooks for the admin area and
221 * the public-facing side of the site.
222 *
223 * @since 1.0.0
224 */
225 public function __construct()
226 {
227 if (defined('WPFNL_VERSION')) {
228 $this->version = WPFNL_VERSION;
229 } else {
230 $this->version = '1.0.0';
231 }
232
233 $this->plugin_name = 'wpfunnels';
234 $this->load_dependencies();
235 $this->init_rest_api();
236 $this->init_setup_wizard();
237
238
239 /*if( !Wpfnl_functions::is_plugin_activated('woocommerce/woocommerce.php') ) {
240 add_action( 'admin_enqueue_scripts', [$this, 'enqueue_scripts'] );
241 add_action( 'wp_ajax_plugin_install_success', array($this, 'plugin_install_success') );
242 add_action( 'admin_notices', array('WPFunnels\Admin\Notices\Notice', 'woocommerce_dependency_notice') );
243 return;
244 }*/
245
246 // load core modules
247 add_action( 'admin_footer', array($this, 'admin_footer_style') );
248 add_action( 'wpfunnels/pro_init', array( $this, 'after_pro_plugin_init' ) );
249 add_action( 'plugins_loaded', array($this, 'load_plugin'), 99 );
250
251 $this->set_locale();
252 $this->init_hooks();
253 if( !Wpfnl_functions::is_pro_license_activated() || ( Wpfnl_functions::is_pro_license_activated() && !version_compare( WPFNL_PRO_VERSION, "1.7.3", ">=" ) ) ){
254 add_filter( 'wpfunnels/update_funnel_data_response', [$this, 'update_funnel_data_response'], 10 );
255 }
256
257 if( !Wpfnl_functions::is_pro_license_activated() || !Wpfnl_functions::is_mint_mrm_active() || ( Wpfnl_functions::is_pro_license_activated() && !version_compare( WPFNL_PRO_VERSION, "1.7.6", ">=" ) ) ){
258 add_filter( 'wpfunnels/update_funnel_data_response', [$this, 'update_mint_funnel_data_response'], 10 );
259 }
260 }
261
262
263 /**
264 * update funnel data response
265 *
266 * @param Array $response
267 *
268 * @since 1.7.8
269 * @return Array $response
270 */
271 public function update_mint_funnel_data_response( $response ){
272
273 $automation_steps = [];
274 if( is_array($response) && !empty($response['funnel_data']['drawflow']['Home']['data']) ){
275 $steps_order = $response['funnel_data']['drawflow']['Home']['data'];
276 if( is_array($steps_order) ){
277 foreach( $steps_order as $key=>$step ){
278 if( isset( $step['data']['step_id'] ) ){
279 $step_id = $step['data']['step_id'];
280 if( Wpfnl_functions::is_mint_mrm_active() ){
281 $automation_steps['step_'.$step_id]['data'] = [];
282 }
283 }
284 }
285 }
286 }
287 $response['automationSteps'] = $automation_steps;
288 return $response;
289 }
290
291
292 /**
293 * Update funnel data response
294 *
295 * @param Array $response
296 *
297 * @return Array $response
298 * @since 2.6.2
299 */
300 public function update_funnel_data_response( $response ){
301 $ab_data = [];
302 if( is_array($response) && !empty($response['funnel_data']['drawflow']['Home']['data']) ){
303 $steps_order = $steps_order = $response['funnel_data']['drawflow']['Home']['data'];
304 if( is_array($steps_order) ){
305 foreach( $steps_order as $key=>$step ){
306 if( isset( $step['data']['step_id'] ) ){
307 $step_id = $step['data']['step_id'];
308 $default_settings = $this->get_default_start_setting( $step_id );
309 $ab_data['step_'.$step_id]['data'] = $default_settings;
310 $ab_data[]['success'] = true;
311 }
312 }
313 }
314 }
315 $response['ab_data'] = $ab_data;
316 return $response;
317 }
318
319
320 /**
321 * Get default start settings for AB testing
322 *
323 * @param Int $step_id
324 *
325 * @return array
326 * @since 2.6.2
327 */
328 public function get_default_start_setting( $step_id ){
329 if( $step_id ){
330 $step_edit_link = get_edit_post_link( $step_id );
331 $funnel_id = Wpfnl_functions::get_funnel_id_from_step( $step_id );
332
333 $utm_settings = Wpfnl_functions::get_funnel_utm_settings( $funnel_id );
334 $view_link = get_post_permalink($step_id);
335
336 if ( $utm_settings[ 'utm_enable' ] == 'on' ) {
337 unset( $utm_settings[ 'utm_enable' ] );
338 $view_link = add_query_arg( $utm_settings, $view_link );
339 $view_link = strtolower( $view_link );
340 }
341
342 if( 'elementor' == Wpfnl_functions::get_builder_type() ){
343 $step_edit_link = str_replace('&amp;','&',$step_edit_link);
344 $step_edit_link = str_replace('edit','elementor',$step_edit_link);
345 }
346 $default_settings = [
347 'is_ab_enabled' => '',
348 'start_settings' => [
349 'auto_winner' => [
350 'is_enabled' => '',
351 'conditions' =>
352 [
353 'index' => 'trafiic',
354 'value' => 70
355 ]
356 ],
357 'winner' => '',
358 'is_started' => '',
359 'start_date' => date( 'Y-m-d H:i:s' ),
360 'variations' => [
361 [
362 'id' => $step_id,
363 'traffic' => 100,
364 'step_type'=> get_post_meta($step_id,'_step_type',true),
365 'variation_type' => 'original',
366 'step_edit_link' => $step_edit_link,
367 'step_view_link' => $view_link,
368 'step_title' => get_the_title($step_id),
369 'conversion' => 0,
370 'visit' => 0,
371 'shouldShowAnalytics' => false,
372 ],
373 ],
374 ]
375 ];
376 }
377 return $default_settings ?? [];
378 }
379
380
381 /**
382 * Enqueue funnel admin common scripts
383 */
384 public function enqueue_scripts() {
385 wp_enqueue_script($this->plugin_name . '-common', WPFNL_DIR_URL . 'admin/assets/js/wpfnl-admin-common.js', [ 'jquery', 'wp-i18n', 'wp-util', 'updates' ], $this->version, true);
386 wp_localize_script( $this->plugin_name. '-common', 'wpfnl_common_vars', array(
387 'ajaxurl' => admin_url( 'admin-ajax.php' ),
388 'wpfnl_activate_plugin_nonce' => wp_create_nonce('wpfnl_activate_plugin_nonce')
389 ));
390 }
391
392
393 /**
394 * Plugin activation ajax
395 */
396 public function plugin_install_success() {
397
398 if ( ! current_user_can( 'manage_options' ) ) {
399 wp_send_json_error( array(
400 'message' => __('You are not authorize to activate plugins.', 'wpfnl')
401 ) );
402 }
403
404 if ( ! check_ajax_referer( 'wpfnl_activate_plugin_nonce', 'security', false ) ) {
405 $response_data = array( 'message' => __('Nonce verification failed', 'wpfnl') );
406 wp_send_json_error( $response_data );
407 }
408
409 \wp_clean_plugins_cache();
410 $plugin_init = ( isset( $_POST['plugin_init'] ) ) ? esc_attr( $_POST['plugin_init'] ) : '';
411 $activate = \activate_plugin( $plugin_init, '', false, true );
412
413 if ( is_wp_error( $activate ) ) {
414 wp_send_json_error(
415 array(
416 'success' => false,
417 'message' => $activate->get_error_message(),
418 )
419 );
420 }
421
422 wp_send_json_success(
423 array(
424 'message' => __('Plugin activated successfully.', 'wpfnl'),
425 )
426 );
427 }
428
429
430 public function init_hooks() {
431 $this->loader->add_action( 'init', $this, 'load_admin_modules' );
432 $shortcode = new Wpfnl_Shortcodes();
433 add_action( 'init', array( $shortcode, 'init') );
434 }
435
436 public function init_rest_api() {
437 $this->loader->add_action( 'init', $this, 'load_rest_api' );
438 }
439
440 public function load_admin_modules() {
441 $this->module_manager = new Module_Manager();
442 }
443
444 public function load_rest_api() {
445 Server::instance()->init();
446 }
447
448
449 /**
450 * Load plugin classes
451 */
452 public function load_plugin() {
453 $this->batch = new Wpfnl_Batch();
454 $this->init();
455
456 do_action( 'wpfunnels/init' );
457 }
458
459
460 public function init() {
461 $this->admin = new Admin( $this->get_plugin_name(), $this->get_version() );
462 $this->frontend = Wpfnl_Public::getInstance();
463 $this->cpt = new CPT();
464 $this->menu = new Menu();
465 $this->funnel_store = new Funnel_Store();
466 $this->step_store = new Step_Store();
467 $this->template_manager = new TemplateLibrary\Manager();
468 $this->widget_manager = Widget_Manager::getInstance()->init();
469 $this->page_templates = new PageTemplates\Manager();
470 $this->admin_notice = new Notice();
471 $this->admin_banner = new SpecialOccasionBanner('black-friday', '2023-11-23 19:00:00', '2023-12-05 23:59:59', 'https://getwpfunnels.com/pricing/?utm_source=notification-cta&utm_medium=wpf-plugin&utm_campaign=BFCM23');
472 $this->order_bump_actions = new Wpfnl_Order_Bump_Action();
473 $this->meta = new Wpfnl_Default_Meta();
474 $this->shortcodes = Wpfnl_Shortcodes::getInstance()->init();
475 $this->ajax_handler = new Ajax_Handler();
476 $this->optin_field = new OptinField();
477 $this->log = Wpfnl_Logger::getInstance()->initialize_logging();
478 $this->compatibility = new Wpfnl_Compatibility();
479 }
480
481
482
483 /**
484 * Load the required dependencies for this plugin.
485 *
486 * Include the following files that make up the plugin:
487 *
488 * - Wpfnl_Loader. Orchestrates the hooks of the plugin.
489 * - Wpfnl_i18n. Defines internationalization functionality.
490 * - Wpfnl_Admin. Defines all hooks for the admin area.
491 * - Wpfnl_Public. Defines all hooks for the public side of the site.
492 *
493 * Create an instance of the loader which will be used to register the hooks
494 * with WordPress.
495 *
496 * @since 1.0.0
497 * @access private
498 */
499 private function load_dependencies()
500 {
501
502
503 /**
504 * The class responsible for auto loading all files of the
505 * core plugin.
506 */
507 require_once plugin_dir_path(dirname(__FILE__)) . 'vendor/autoload.php';
508
509 /**
510 * The class responsible for orchestrating the actions and filters of the
511 * core plugin.
512 */
513 require_once plugin_dir_path(dirname(__FILE__)) . 'includes/utils/class-wpfnl-loader.php';
514
515 /**
516 * The class responsible for defining internationalization functionality
517 * of the plugin.
518 */
519 require_once plugin_dir_path(dirname(__FILE__)) . 'includes/utils/class-wpfnl-i18n.php';
520
521 /**
522 * The class responsible for defining all actions that occur in the admin area.
523 */
524 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-wpfnl-admin.php';
525
526 /**
527 * The class responsible for defining all actions that occur in the public-facing
528 * side of the site.
529 */
530 require_once plugin_dir_path(dirname(__FILE__)) . 'public/class-wpfnl-public.php';
531
532 /**
533 * Require action scheduler for crm
534 */
535 //require_once plugin_dir_path(dirname(__FILE__)) . 'packages/action-scheduler/action-scheduler.php';
536
537 $this->loader = new Wpfnl_Loader();
538 }
539
540
541 /**
542 * After pro plugin init action
543 */
544 public function after_pro_plugin_init() {
545
546 if ( ! is_admin() ) {
547 return;
548 }
549
550 if ( version_compare( WPFNL_PRO_VERSION, WPFNL_PRO_REQUIRED_VERSION, '<' ) ) {
551 add_action( 'admin_notices', array( $this, 'required_wpf_pro_notice' ) );
552 add_action( 'after_plugin_row_'. WPFNL_BASE, 'wpfnl_pro_update_notice_after_plugin_row' );
553 }
554 }
555
556
557 /**
558 * Required pro plugin notice
559 */
560 public function required_wpf_pro_notice() {
561 $class = 'notice notice-error';
562 $message = sprintf(__("It appears you have an older version of <strong>WPFunnels Pro</strong>. This may cause some issues with the plugin's functionality. Please update <strong>WPFunnels Pro</strong> to v%s and above.","wpfnl"), WPFNL_PRO_REQUIRED_VERSION); // phpcs:ignore
563 printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message );
564 }
565
566
567 /**
568 * Show pro dependency notice
569 * after plugin row
570 */
571 public function wpfnl_pro_update_notice_after_plugin_row() {
572 $message = sprintf(__("It appears you have an older version of <strong>WPFunnels Pro</strong>. This may cause some issues with the plugin's functionality. Please update <strong>WPFunnels Pro</strong> to v%s and above.",'wpfnl'), WPFNL_PRO_REQUIRED_VERSION ); // phpcs:ignore
573 printf( '</tr><tr class="plugin-update-tr"><td colspan="5" class="plugin-update"><div class="update-message" style="background-color: #ffebe8;">%s</div></td>', $message );
574 }
575
576
577 /**
578 * Define the locale for this plugin for internationalization.
579 *
580 * Uses the Wpfnl_i18n class in order to set the domain and to register the hook
581 * with WordPress.
582 *
583 * @since 1.0.0
584 * @access private
585 */
586 private function set_locale()
587 {
588 $plugin_i18n = new Wpfnl_i18n();
589
590 $this->loader->add_action('plugins_loaded', $plugin_i18n, 'load_plugin_textdomain');
591
592 }
593
594
595 /**
596 * Run the loader to execute all of the hooks with WordPress.
597 *
598 * @since 1.0.0
599 */
600 public function run()
601 {
602 $this->loader->run();
603 }
604
605
606 /**
607 * The name of the plugin used to uniquely identify it within the context of
608 * WordPress and to define internationalization functionality.
609 *
610 * @since 1.0.0
611 * @return string The name of the plugin.
612 */
613 public function get_plugin_name()
614 {
615 return $this->plugin_name;
616 }
617
618
619 /**
620 * The reference to the class that orchestrates the hooks with the plugin.
621 *
622 * @since 1.0.0
623 * @return Wpfnl_Loader Orchestrates the hooks of the plugin.
624 */
625 public function get_loader()
626 {
627 return $this->loader;
628 }
629
630
631 /**
632 * Retrieve the version number of the plugin.
633 *
634 * @since 1.0.0
635 * @return string The version number of the plugin.
636 */
637 public function get_version()
638 {
639 return $this->version;
640 }
641
642
643 /**
644 * Render admin footer styles
645 */
646 public function admin_footer_style() {
647 echo '<style>
648 .wpfnl-notice {
649 border-left-color: #dba617;
650 }
651 .wpfnl-notice .wpfnl-notice__content {
652 padding: 10px 0;
653 }
654
655 .wpfnl-notice .notice-dismiss {
656 top: 11px;
657 }
658
659 .wpfnl-notice .wpfnl-notice__content > p {
660 font-weight: 600;
661 margin: 0;
662 }
663 .wpfnl-notice .wpfnl-notice__actions {
664 margin-top: 8px;
665 }
666
667 .wpfnl-notice .wpfnl-notice__content .wpfnl-notice-button {
668 height: 36px;
669 line-height: 36px;
670 border-radius: 6px;
671 color: #fff;
672 font-weight: 500;
673 padding: 0 20px;
674 background: #6e42d3;
675 display: inline-block;
676 text-decoration: none;
677 letter-spacing: 0.5px;
678 transition: all 0.3s ease;
679 }
680
681 .wpfnl-notice .wpfnl-notice__content .wpfnl-notice-button:hover {
682 background: #4C25A5;
683 }
684 .wpfnl-notice .wpfnl-notice__content .wpfnl-notice-button .notice-loader {
685 border: 2px solid #8265c5;
686 border-radius: 50%;
687 border-top: 2px solid #fff;
688 width: 10px;
689 height: 10px;
690 animation: spin 0.7s linear infinite;
691 display: none;
692 position: relative;
693 top: 3px;
694 margin-left: 9px;
695 }
696 @-webkit-keyframes spin {
697 0% { -webkit-transform: rotate(0deg); }
698 100% { -webkit-transform: rotate(360deg); }
699 }
700
701 @keyframes spin {
702 0% { transform: rotate(0deg); }
703 100% { transform: rotate(360deg); }
704 }
705 </style>';
706 }
707
708
709 /**
710 * Init setup wizard options
711 */
712 public function init_setup_wizard() {
713 add_action('init', array( $this, 'register_setup_wizard_page' ));
714 add_action('admin_init', array($this, 'admin_redirects'));
715 }
716
717
718 /**
719 * Register setup wizard
720 */
721 public function register_setup_wizard_page() {
722 if (!empty($_GET['page']) && 'wpfunnels-setup' == sanitize_text_field( $_GET['page'] )) {
723 add_action('admin_menu', function () {
724 add_dashboard_page('WPFunnels Setup', 'WPFunnels Setup', 'manage_options', 'wpfunnels-setup', function () {
725 return '';
726 });
727 });
728 add_action('current_screen', function () {
729 new SetupWizard();
730 }, 999);
731 }
732 }
733
734
735 /**
736 * Handle redirects to setup/welcome page after install and updates.
737 *
738 * For setup wizard, transient must be present, the user must have access rights, and we must ignore the network/bulk plugin updaters.
739 */
740 public function admin_redirects()
741 {
742 // Setup wizard redirect.
743 if (get_transient('_wpfunnels_activation_redirect')) {
744 $do_redirect = true;
745 $current_page = isset($_GET['page']) ? wc_clean(wp_unslash($_GET['page'])) : false; // phpcs:ignore WordPress.Security.NonceVerification
746
747 // On these pages, or during these events, postpone the redirect.
748 if (wp_doing_ajax() || is_network_admin() || !current_user_can('manage_options')) {
749 $do_redirect = false;
750 }
751
752 if ( $do_redirect ) {
753 delete_transient('_wpfunnels_activation_redirect');
754 $url = admin_url('admin.php?page=wpfunnels-setup');
755 wp_safe_redirect( wp_sanitize_redirect( esc_url_raw( $url ) ) );
756 exit;
757 }
758 }
759 }
760 }
761