Plugin Directory

Changeset 3251904


Ignore:
Timestamp:
03/06/2025 09:55:03 PM (13 months ago)
Author:
acteamintegrations
Message:

Version 2.9.0

Location:
activecampaign-for-woocommerce
Files:
2 added
43 edited
14 copied

Legend:

Unmodified
Added
Removed
  • activecampaign-for-woocommerce/tags/2.9.0/README.txt

    r3242090 r3251904  
    44Requires at least: 6.0
    55Tested up to: 6.7.1
    6 Stable tag: 2.8.7
     6Stable tag: 2.9.0
    77Requires PHP: 7.4
    88License: GPLv2 or later
     
    6868
    6969= WooCommerce Compatibility =
    70 * Tested up to version: 9.6.1
     70* Tested up to version: 9.7.1
    7171* Minimal version requirement: 7.4.0
    7272* HPOS Compatible
     
    9494
    9595== Changelog ==
     96
     97= 2.9.0 2025-03-06 =
     98* Improvement - Order sync scheduling rebuilt
     99* Improvement - Action Schedule will be preferred with fallback to cron
     100* Bugfix - Order sync and abandon sync process bugs resolved
    96101
    97102= 2.8.7 2025-02-13 =
  • activecampaign-for-woocommerce/tags/2.9.0/ac_vendor/autoload.php

    r3242090 r3251904  
    55require_once __DIR__ . '/composer/autoload_real.php';
    66
    7 return ComposerAutoloaderInitd9bb3bd7e18ccd70aab112aebbce8079::getLoader();
     7return ComposerAutoloaderInit175e130378661b488bf176f44e675036::getLoader();
  • activecampaign-for-woocommerce/tags/2.9.0/ac_vendor/composer/autoload_classmap.php

    r3220303 r3251904  
    382382    'Activecampaign_For_Woocommerce_Run_Abandonment_Sync_Command' => $baseDir . '/includes/abandoned_carts/class-activecampaign-for-woocommerce-run-abandonment-sync-command.php',
    383383    'Activecampaign_For_Woocommerce_Save_Abandoned_Cart_Command' => $baseDir . '/includes/abandoned_carts/class-activecampaign-for-woocommerce-save-abandoned-cart-command.php',
     384    'Activecampaign_For_Woocommerce_Scheduler_Handler' => $baseDir . '/includes/events/class-activecampaign-for-woocommerce-scheduler-handler.php',
    384385    'Activecampaign_For_Woocommerce_Set_Connection_Id_Cache_Command' => $baseDir . '/includes/commands/class-activecampaign-for-woocommerce-set-connection-id-cache-command.php',
    385386    'Activecampaign_For_Woocommerce_Simple_Graphql_Serializer' => $baseDir . '/includes/models/serializers/class-activecampaign-for-woocommerce-simple-graphql-serializer.php',
  • activecampaign-for-woocommerce/tags/2.9.0/ac_vendor/composer/autoload_real.php

    r3242090 r3251904  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInitd9bb3bd7e18ccd70aab112aebbce8079
     5class ComposerAutoloaderInit175e130378661b488bf176f44e675036
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInitd9bb3bd7e18ccd70aab112aebbce8079', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit175e130378661b488bf176f44e675036', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
    29         spl_autoload_unregister(array('ComposerAutoloaderInitd9bb3bd7e18ccd70aab112aebbce8079', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit175e130378661b488bf176f44e675036', 'loadClassLoader'));
    3030
    3131        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
     
    3333            require __DIR__ . '/autoload_static.php';
    3434
    35             call_user_func(\Composer\Autoload\ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::getInitializer($loader));
     35            call_user_func(\Composer\Autoload\ComposerStaticInit175e130378661b488bf176f44e675036::getInitializer($loader));
    3636        } else {
    3737            $map = require __DIR__ . '/autoload_namespaces.php';
     
    5454
    5555        if ($useStaticLoader) {
    56             $includeFiles = Composer\Autoload\ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::$files;
     56            $includeFiles = Composer\Autoload\ComposerStaticInit175e130378661b488bf176f44e675036::$files;
    5757        } else {
    5858            $includeFiles = require __DIR__ . '/autoload_files.php';
    5959        }
    6060        foreach ($includeFiles as $fileIdentifier => $file) {
    61             composerRequired9bb3bd7e18ccd70aab112aebbce8079($fileIdentifier, $file);
     61            composerRequire175e130378661b488bf176f44e675036($fileIdentifier, $file);
    6262        }
    6363
     
    6666}
    6767
    68 function composerRequired9bb3bd7e18ccd70aab112aebbce8079($fileIdentifier, $file)
     68function composerRequire175e130378661b488bf176f44e675036($fileIdentifier, $file)
    6969{
    7070    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
  • activecampaign-for-woocommerce/tags/2.9.0/ac_vendor/composer/autoload_static.php

    r3242090 r3251904  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079
     7class ComposerStaticInit175e130378661b488bf176f44e675036
    88{
    99    public static $files = array (
     
    465465        'Activecampaign_For_Woocommerce_Run_Abandonment_Sync_Command' => __DIR__ . '/../..' . '/includes/abandoned_carts/class-activecampaign-for-woocommerce-run-abandonment-sync-command.php',
    466466        'Activecampaign_For_Woocommerce_Save_Abandoned_Cart_Command' => __DIR__ . '/../..' . '/includes/abandoned_carts/class-activecampaign-for-woocommerce-save-abandoned-cart-command.php',
     467        'Activecampaign_For_Woocommerce_Scheduler_Handler' => __DIR__ . '/../..' . '/includes/events/class-activecampaign-for-woocommerce-scheduler-handler.php',
    467468        'Activecampaign_For_Woocommerce_Set_Connection_Id_Cache_Command' => __DIR__ . '/../..' . '/includes/commands/class-activecampaign-for-woocommerce-set-connection-id-cache-command.php',
    468469        'Activecampaign_For_Woocommerce_Simple_Graphql_Serializer' => __DIR__ . '/../..' . '/includes/models/serializers/class-activecampaign-for-woocommerce-simple-graphql-serializer.php',
     
    493494    {
    494495        return \Closure::bind(function () use ($loader) {
    495             $loader->prefixLengthsPsr4 = ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::$prefixLengthsPsr4;
    496             $loader->prefixDirsPsr4 = ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::$prefixDirsPsr4;
    497             $loader->classMap = ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::$classMap;
     496            $loader->prefixLengthsPsr4 = ComposerStaticInit175e130378661b488bf176f44e675036::$prefixLengthsPsr4;
     497            $loader->prefixDirsPsr4 = ComposerStaticInit175e130378661b488bf176f44e675036::$prefixDirsPsr4;
     498            $loader->classMap = ComposerStaticInit175e130378661b488bf176f44e675036::$classMap;
    498499
    499500        }, null, ClassLoader::class);
  • activecampaign-for-woocommerce/tags/2.9.0/activecampaign-for-woocommerce.php

    r3242090 r3251904  
    1717 * Plugin URI:           https://www.activecampaign.com/
    1818 * Description:          Add Abandoned Cart functionality to your WooCommerce store, synchronize order & customer information using ActiveCampaign.
    19  * Version:              2.8.7
     19 * Version:              2.9.0
    2020 * WC requires at least: 7.4.0
    21  * WC tested up to:      9.6.1
     21 * WC tested up to:      9.7.1
    2222 * Requires at least:    6.0
    2323 * Requires PHP:         7.4
  • activecampaign-for-woocommerce/tags/2.9.0/admin/class-activecampaign-for-woocommerce-admin-historical-sync.php

    r3232769 r3251904  
    1313use Activecampaign_For_Woocommerce_Logger as Logger;
    1414use Activecampaign_For_Woocommerce_Historical_Sync_Prep as Historical_Prep;
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1516
    1617/**
     
    4849        return false;
    4950    }
     51
    5052    /**
    5153     * Fetches the next historical sync cron time.
     
    5759        $data   = null;
    5860
    59         try {
    60             if ( function_exists( 'wp_get_scheduled_event' ) ) {
    61                 $historical_order_schedule = wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    62                 if ( $historical_order_schedule ) {
    63                     $data['historical_order_schedule']['error']     = false;
    64                     $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule->timestamp );
    65                     $data['historical_order_schedule']['schedule']  = $historical_order_schedule->schedule;
    66                     if ( $historical_order_schedule->timestamp && $historical_order_schedule->interval ) {
    67                         $next = $historical_order_schedule->timestamp + $historical_order_schedule->interval - time();
    68                         $data['historical_order_schedule']['next_scheduled'] = $next;
    69                     }
    70                 } else {
    71                     $data['historical_order_schedule']['error'] = true;
    72                     $logger->warning(
    73                         'Historical order sync is not scheduled.',
    74                         array(
    75                             'historical_order_schedule' => $historical_order_schedule,
    76                         )
    77                     );
    78                 }
    79             } elseif ( function_exists( 'wp_next_scheduled' ) ) {
    80                 $logger->warning( 'The wp_get_scheduled_event function may not exist. Performing wp_next_scheduled instead.' );
    81                 $historical_order_schedule                      = wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    82                 $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule );
    83             }
    84         } catch ( Throwable $t ) {
    85             $logger->warning(
    86                 'There was an issue getting the historical sync cron information.',
    87                 array(
    88                     'message' => $t->getMessage(),
    89                     'trace'   => $t->getTrace(),
    90                     'ac_code' => 'AHS_80',
    91                 )
    92             );
     61        $historical_order_schedule = AC_Scheduler::get_schedule( AC_Scheduler::RECURRING_HISTORICAL_SYNC );
     62
     63        if ( ! $historical_order_schedule ) {
     64            $data['historical_order_schedule']['error'] = true;
     65            $logger->warning(
     66                'Historical order sync is not scheduled.',
     67                array(
     68                    'historical_order_schedule' => $historical_order_schedule,
     69                )
     70            );
     71        } elseif (is_int( $historical_order_schedule ) ) {
     72            $data['historical_order_schedule']['error']          = false;
     73            $data['historical_order_schedule']['timestamp']      = wp_date( DATE_ATOM, $historical_order_schedule );
     74            $data['historical_order_schedule']['schedule']       = false;
     75            $data['historical_order_schedule']['next_scheduled'] = false;
     76        } else {
     77            $data['historical_order_schedule']['error']     = false;
     78            $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule->timestamp );
     79            $data['historical_order_schedule']['schedule']  = $historical_order_schedule->schedule;
     80
     81            if ( $historical_order_schedule->timestamp && $historical_order_schedule->interval ) {
     82                $next = $historical_order_schedule->timestamp + $historical_order_schedule->interval - time();
     83                $data['historical_order_schedule']['next_scheduled'] = $next;
     84            }
    9385        }
    9486
     
    134126            do_action( 'activecampaign_for_woocommerce_ready_existing_historical_data' );
    135127
    136             wp_schedule_single_event(
    137                 time() + 30,
    138                 'activecampaign_for_woocommerce_prep_historical_data',
    139                 array('current_page' => 0)
    140             );
     128            // schedule activecampaign_for_woocommerce_prep_historical_data
     129            AC_Scheduler::schedule_ac_event( AC_Scheduler::PREP_HISTORICAL_SYNC, array('current_page' => 0), false, false );
    141130
    142131            wp_send_json_success( 'Historical sync scheduled.' );
  • activecampaign-for-woocommerce/tags/2.9.0/admin/class-activecampaign-for-woocommerce-admin-status.php

    r3227747 r3251904  
    1313use Activecampaign_For_Woocommerce_Logger as Logger;
    1414use Automattic\WooCommerce\Utilities\RestApiUtil;
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Schedule;
    1516
    1617/**
     
    500501    }
    501502
     503    private function check_for_event_data( $event_schedule ) {
     504        $logger     = new Logger();
     505        $event_data = array();
     506
     507        if ( ! empty( $event_schedule ) ) {
     508            $event_data['timestamp']      = wp_date( DATE_ATOM, $event_schedule );
     509            $event_data['next_scheduled'] = wp_date( DATE_ATOM, $event_schedule );
     510            $event_data['error']          = false;
     511
     512            if ( ! empty( $event_data['timestamp'] ) ) {
     513                return $event_data;
     514            }
     515        }
     516        if ( is_object( $event_schedule ) && ! empty( $event_schedule->timestamp ) ) {
     517            $event_data['timestamp'] = wp_date( DATE_ATOM, $event_schedule->timestamp );
     518
     519            if ( $event_schedule->timestamp && $event_schedule->interval ) {
     520                $next = $event_schedule->timestamp + $event_schedule->interval - time();
     521                $data['abandoned_schedule']['next_scheduled'] = $next;
     522            }
     523
     524            $event_data['schedule'] = $event_schedule->schedule;
     525            $event_data['error']    = false;
     526        }
     527
     528        return $event_data;
     529    }
     530
    502531    /**
    503532     * Gets the cron related data.
     
    510539        $logger = new Logger();
    511540
    512         try {
    513             if ( function_exists( 'wp_get_scheduled_event' ) ) {
    514                 $abandoned_schedule        = wp_get_scheduled_event( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    515                 $new_order_schedule        = wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    516                 $historical_order_schedule = wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    517 
    518                 if ( $abandoned_schedule ) {
    519                     $data['abandoned_schedule']['timestamp'] = wp_date( DATE_ATOM, $abandoned_schedule->timestamp );
    520 
    521                     if ( $abandoned_schedule->timestamp && $abandoned_schedule->interval ) {
    522                         $next = $abandoned_schedule->timestamp + $abandoned_schedule->interval - time();
    523                         $data['abandoned_schedule']['next_scheduled'] = $next;
    524                     }
    525 
    526                     $data['abandoned_schedule']['schedule'] = $abandoned_schedule->schedule;
    527                     $data['abandoned_schedule']['error']    = false;
    528                 } else {
    529                     $data['abandoned_schedule']['error'] = true;
    530                     $logger->warning(
    531                         'Abandoned cart is not scheduled.',
    532                         array(
    533                             'abandoned_cart_schedule' => $abandoned_schedule,
    534                         )
    535                     );
    536                 }
    537 
    538                 if ( $new_order_schedule ) {
    539                     $data['new_order_schedule']['error']     = false;
    540                     $data['new_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $new_order_schedule->timestamp );
    541                     $data['new_order_schedule']['schedule']  = $new_order_schedule->schedule;
    542                     if ( $new_order_schedule->timestamp && $new_order_schedule->interval ) {
    543                         $next = $new_order_schedule->timestamp + $new_order_schedule->interval - time();
    544                         $data['new_order_schedule']['next_scheduled'] = $next;
    545                     }
    546                 } else {
    547                     $data['new_order_schedule']['error'] = true;
    548                     $logger->warning(
    549                         'New order sync is not scheduled.',
    550                         array(
    551                             'new_order_schedule' => $new_order_schedule,
    552                         )
    553                     );
    554                 }
    555 
    556                 if ( $historical_order_schedule ) {
    557                     $data['historical_order_schedule']['error']     = false;
    558                     $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule->timestamp );
    559                     $data['historical_order_schedule']['schedule']  = $historical_order_schedule->schedule;
    560                     if ( $historical_order_schedule->timestamp && $historical_order_schedule->interval ) {
    561                         $next = $historical_order_schedule->timestamp + $historical_order_schedule->interval - time();
    562                         $data['historical_order_schedule']['next_scheduled'] = $next;
    563                     }
    564                 } else {
    565                     $data['historical_order_schedule']['error'] = true;
    566                     $logger->warning(
    567                         'Historical order sync is not scheduled.',
    568                         array(
    569                             'historical_order_schedule' => $historical_order_schedule,
    570                         )
    571                     );
    572                 }
    573             } elseif ( function_exists( 'wp_next_scheduled' ) ) {
    574                 $logger->warning( 'The wp_get_scheduled_event function may not exist. Performing wp_next_scheduled instead.' );
    575                 $abandoned_schedule                             = wp_next_scheduled( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    576                 $new_order_schedule                             = wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    577                 $historical_order_schedule                      = wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    578                 $data['abandoned_schedule']['timestamp']        = wp_date( DATE_ATOM, $abandoned_schedule );
    579                 $data['new_order_schedule']['timestamp']        = wp_date( DATE_ATOM, $new_order_schedule );
    580                 $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule );
    581                 $data['new_order_schedule']['error']            = false;
    582                 if ( ! $new_order_schedule || ! $abandoned_schedule ) {
    583                     $logger->warning(
    584                         'An order sync is not scheduled.',
    585                         array(
    586                             'new_order_schedule'        => $new_order_schedule,
    587                             'historical_order_schedule' => $historical_order_schedule,
    588                             'abandoned_cart_schedule'   => $abandoned_schedule,
    589                         )
    590                     );
    591                 }
    592             } else {
    593                 $data['new_order_schedule']['error'] = true;
    594                 $logger->warning( 'One of the cron syncs may not be scheduled.' );
    595             }
    596         } catch ( Throwable $t ) {
    597             $logger->warning(
    598                 'ActiveCampaign status page threw an error',
    599                 array(
    600                     'message' => $t->getMessage(),
    601                 )
    602             );
     541        $abandoned_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_ABANDONED_SYNC );
     542        $data['abandoned_schedule'] = $this->check_for_event_data( $abandoned_schedule );
     543        if ( ! $data['abandoned_schedule'] ) {
     544            AC_Schedule::schedule_ac_event( AC_Schedule::RECURRING_ABANDONED_SYNC, array(), true, false );
     545
     546            $abandoned_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_ABANDONED_SYNC );
     547            $data['abandoned_schedule'] = $this->check_for_event_data( $abandoned_schedule );
     548        }
     549        if ( ! $data['abandoned_schedule'] ) {
     550            $data['abandoned_schedule']['error'] = true;
     551            $logger->warning( 'Abandoned cart is not scheduled.', array( 'abandoned_cart_schedule' => $data['abandoned_schedule'] ) );
     552        }
     553
     554        $new_order_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_ORDER_SYNC );
     555        $data['new_order_schedule'] = $this->check_for_event_data( $new_order_schedule );
     556        if ( ! $data['new_order_schedule'] ) {
     557            AC_Schedule::schedule_ac_event( AC_Schedule::RECURRING_ORDER_SYNC, array(), true, false );
     558
     559            $new_order_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_ORDER_SYNC );
     560            $data['new_order_schedule'] = $this->check_for_event_data( $new_order_schedule );
     561        }
     562        if ( ! $data['new_order_schedule'] ) {
    603563            $data['new_order_schedule']['error'] = true;
     564            $logger->warning( 'New order sync is not scheduled.', array( 'new_order_schedule' => $data['new_order_schedule'] ) );
     565        }
     566
     567        $historical_order_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_HISTORICAL_SYNC );
     568        $data['historical_order_schedule'] = $this->check_for_event_data( $historical_order_schedule );
     569        if ( ! $data['historical_order_schedule'] ) {
     570            AC_Schedule::schedule_ac_event( AC_Schedule::RECURRING_HISTORICAL_SYNC, array(), true, false );
     571
     572            $historical_order_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_HISTORICAL_SYNC );
     573            $data['historical_order_schedule'] = $this->check_for_event_data( $historical_order_schedule );
     574        }
     575        if ( ! $data['historical_order_schedule'] ) {
     576            $data['historical_order_schedule']['error'] = true;
     577            $logger->warning( 'Historical order sync is not scheduled.', array( 'historical_order_schedule' => $data['historical_order_schedule'] ) );
    604578        }
    605579
  • activecampaign-for-woocommerce/tags/2.9.0/admin/class-activecampaign-for-woocommerce-admin.php

    r3242090 r3251904  
    2222use Activecampaign_For_Woocommerce_Ac_Tracking_Repository as AC_Tracking;
    2323use Activecampaign_For_Woocommerce_Whitelist_Repository as AC_Whitelist_Repository;
     24use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    2425
    2526/**
     
    104105    private $api_client;
    105106
     107
    106108    /**
    107109     * Initialize the class and set its properties.
     
    126128    }
    127129
     130    /**
     131     * Adds a cron task for every 10 minutes.
     132     *
     133     * @param mixed $schedules The schedules.
     134     *
     135     * @return mixed
     136     */
    128137    public function cron_add_ten_minute( $schedules ) {
    129138        // Adds once weekly to the existing schedules.
     
    779788
    780789                if ( ! isset( $storage['connection_id'] ) || empty( $storage['connection_id'] ) ) {
    781                     $this->clear_cron_syncs();
     790                    AC_Scheduler::remove_all_events();
    782791                }
    783792            }
     
    11761185     */
    11771186    public function schedule_cron_syncs() {
    1178         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    1179         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    1180         wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    1181 
    11821187        try {
    11831188            if (
     
    11861191                $this->is_configured()
    11871192            ) {
    1188                 wp_schedule_event( time() + 10, 'ten_minute', 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    1189                 wp_schedule_event( time() + 10, 'ten_minute', ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    1190                 wp_schedule_event( time() + 15, 'every_minute', ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
     1193                $ac_scheduler = new AC_Scheduler();
     1194                // clear and reschedule all of these events ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR, ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME, activecampaign_for_woocommerce_cart_updated_recurring_event
     1195                $ac_scheduler->schedule_all_recurring_events( true );
    11911196            }
    11921197        } catch ( Throwable $t ) {
     
    12021207
    12031208    /**
    1204      * Unschedules cron syncs
    1205      */
    1206     public function clear_cron_syncs() {
    1207         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    1208         wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    1209         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    1210     }
    1211 
    1212     /**
    12131209     * Callback function to validate the user can save settings
    12141210     *
     
    12511247        try {
    12521248            if ( delete_option( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_DB_SETTINGS_NAME ) && delete_option( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_DB_CONNECTION_STORAGE_NAME ) ) {
    1253                 wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    1254                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    1255                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_PRODUCT_SYNC_NAME );
    1256                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    1257                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_SYNC_NAME );
    1258                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_HISTORICAL_SYNC_SCHEDULED_STATUS_NAME );
    1259                 wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_prep_historical_data' );
     1249                AC_Scheduler::remove_all_events();
    12601250                delete_transient( 'activecampaign_for_woocommerce_all_connections' );
    12611251                delete_transient( 'activecampaign_for_woocommerce_connection' );
  • activecampaign-for-woocommerce/tags/2.9.0/admin/trait-activecampaign-for-woocommerce-admin-connections.php

    r3242090 r3251904  
    174174                do_action( 'activecampaign_for_woocommerce_run_sync_connection' );
    175175                do_action( 'activecampaign_for_woocommerce_update_connection_options', array('new_connection') );
     176                Activecampaign_For_Woocommerce_Scheduler_Handler::schedule_all_recurring_events( true );
    176177                wp_send_json_success( 'Connection saved: ' . wp_json_encode( $connection->serialize_to_array() ) );
    177178            } else {
     
    219220                $this->delete_options_from_storage();
    220221                $this->update_storage_from_connection( $connection );
     222                Activecampaign_For_Woocommerce_Scheduler_Handler::schedule_all_recurring_events( false );
    221223                do_action( 'activecampaign_for_woocommerce_retrieve_connection_options', array('select_connection') );
    222224                wp_send_json_success( 'Connection saved.' );
    223225            }
    224226        }
     227
     228        Activecampaign_For_Woocommerce_Scheduler_Handler::remove_all_events();
    225229        wp_send_json_error( 'Something went wrong with setting the connection.' );
    226230    }
  • activecampaign-for-woocommerce/tags/2.9.0/admin/trait-activecampaign-for-woocommerce-admin-utilities.php

    r3220303 r3251904  
    217217        return $options_to_be_saved;
    218218    }
     219
     220    private function debug_mode() {
     221        if (defined( 'ACFWC_DEBUG' ) ) {
     222            if (
     223                ACFWC_DEBUG !== null &&
     224                in_array( ACFWC_DEBUG, array(true, 1, '1') )
     225            ) {
     226                return true;
     227            }
     228        }
     229
     230        return false;
     231    }
    219232}
  • activecampaign-for-woocommerce/tags/2.9.0/admin/views/activecampaign-for-woocommerce-abandoned-cart-display.php

    r3232769 r3251904  
    3030}
    3131
     32$activecampaign_for_woocommerce_now_datetime    = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
    3233$activecampaign_for_woocommerce_expire_datetime = new DateTime( 'now -' . $activecampaign_for_woocommerce_expire_time . ' hours', new DateTimeZone( 'UTC' ) );
    3334
     
    120121                    <?php endif; ?>
    121122                </h3>
     123                <table><tr>
     124                        <td>Abandonment cutoff time UTC:</td><td><?php echo esc_html( $activecampaign_for_woocommerce_expire_datetime->format( DATE_ATOM ) ); ?></td>
     125                    </tr><tr>
     126                        <td>Current time UTC:</td><td><?php echo esc_html( $activecampaign_for_woocommerce_now_datetime->format( DATE_ATOM ) ); ?></td>
     127                    </tr></table>
    122128                <h3>
    123129                    Total Abandoned Carts
  • activecampaign-for-woocommerce/tags/2.9.0/admin/views/activecampaign-for-woocommerce-admin-display.php

    r3242090 r3251904  
    765765                                > Off
    766766                            </label>
    767                             <label class="radio" style="display:none;">
     767                            <label class="radio"
     768                            <?php
     769                            if ( ! $this->debug_mode() ) :
     770                                ?>
     771                                style="display:none;"<?php endif; ?>>
    768772                                <input type="radio" id="browse_tracking3" name="browse_tracking" value="3"
    769773                                <?php
  • activecampaign-for-woocommerce/tags/2.9.0/includes/abandoned_carts/class-activecampaign-for-woocommerce-run-abandonment-sync-command.php

    r3220303 r3251904  
    135135        set_transient( 'acforwc_abandoned_task_hook', wp_date( DATE_ATOM ), 604800 );
    136136
    137         $now      = date_create( 'NOW' );
    138         $last_run = get_option( 'activecampaign_for_woocommerce_abandoned_cart_last_run' );
     137        $now              = date_create( 'NOW' );
     138        $last_run         = get_option( 'activecampaign_for_woocommerce_abandoned_cart_last_run' );
     139        $interval_minutes = 0;
    139140
    140141        if ( false !== $last_run ) {
    141142            $interval         = date_diff( $now, $last_run );
    142143            $interval_minutes = $interval->format( '%i' );
    143         } else {
    144             $interval_minutes = 0;
    145144        }
    146145
    147146        if ( false === $last_run || 5 <= $interval_minutes ) {
    148147            do_action( 'activecampaign_for_woocommerce_verify_tables' );
    149 
    150148            $this->run_abandoned_carts();
    151149        }
     
    169167        }
    170168
    171         // Check for legacy abandoned carts
    172         $abandoned_carts = $this->get_all_abandoned_carts_from_table_legacy();
     169        // Process first failure records
     170        $abandoned_carts = $this->get_all_abandoned_carts_from_table( self::STATUS_ABANDONED_CART_NETWORK_FAIL_RETRY );
    173171        if ( ! empty( $abandoned_carts ) ) {
    174172            $this->process_abandoned_carts_per_record( $abandoned_carts ); // Process this group
    175173            $cart_count += count( $abandoned_carts );
    176         } else {
    177             $this->logger->debug_excess( 'Abandoned cart hourly task: No legacy abandoned carts to process...' );
    178174        }
    179175
     
    187183        }
    188184
     185        $abandoned_carts = $this->get_all_abandoned_carts_from_table_use_code_sort();
     186        if ( ! empty( $abandoned_carts ) ) {
     187            $this->process_abandoned_carts_per_record( $abandoned_carts ); // Process this group
     188            $cart_count += count( $abandoned_carts );
     189        } else {
     190            $this->logger->debug_excess( 'Abandoned cart hourly task: No code based abandoned carts to process...' );
     191        }
     192
    189193        $this->clean_old_synced_abandoned_carts();
    190194        $this->clean_all_old_abandoned_carts();
     
    262266
    263267    /**
    264      * Get all active carts.
    265      *
    266      * @return mixed Whether or not there are abandoned carts.
    267      * @throws Throwable Thrown message.
     268     * Get all abandoned carts.
     269     *
     270     * @param int $synced_to_ac Status to request.
     271     *
     272     * @return array|false|object|stdClass[]|void
    268273     */
    269274    private function get_all_abandoned_carts_from_table( $synced_to_ac = self::STATUS_ABANDONED_CART_UNSYNCED ) {
     
    298303                    )
    299304                    AND order_date IS NULL
    300                     AND synced_to_ac = ' . $synced_to_ac . ';'
     305                    AND synced_to_ac = ' . $synced_to_ac . ' LIMIT 50;'
    301306            );
    302307            // phpcs:enable
     
    314319            }
    315320
    316             $this->clean_old_synced_abandoned_carts();
    317             $this->clean_all_old_abandoned_carts();
    318 
    319321            if ( ! empty( $abandoned_carts ) ) {
    320322                return $abandoned_carts; // abandoned carts found
     
    335337
    336338    /**
    337      * Get all active carts.
    338      *
    339      * @deprecated This will need to be removed after a few versions as we moved from a common unsynced value of 0 to 20 for abandoned carts specifically.
    340      *
    341      * @return mixed Whether or not there are abandoned carts.
    342      * @throws Throwable Thrown message.
    343      */
    344     private function get_all_abandoned_carts_from_table_legacy() {
     339     * Use code to sort out if the cart is ready to sync.
     340     *
     341     * @return array|false|void
     342     */
     343    private function get_all_abandoned_carts_from_table_use_code_sort() {
    345344        global $wpdb;
    346345
    347346        // default is 1 hour abandon cart expiration
    348347        $this->expire_time = 1;
     348        $synced_to_ac      = array( self::STATUS_ABANDONED_CART_UNSYNCED, self::STATUS_ABANDONED_CART_FAILED_WAIT, self::STATUS_ABANDONED_CART_FAILED_2, self::STATUS_ABANDONED_CART_NETWORK_FAIL_RETRY );
    349349
    350350        // Get the expire time period from the db
     
    361361            // Get the expired carts from our table
    362362            // phpcs:disable
    363             $abandoned_carts = $wpdb->get_results(
    364                 'SELECT id, synced_to_ac, customer_ref_json, cart_ref_json, cart_totals_ref_json, removed_cart_contents_ref_json, activecampaignfwc_order_external_uuid, last_access_time, ADDTIME(last_access_time, "' . $this->expire_time . ':00:00") as calc_abandoned_date
    365                     FROM
    366                         `' . $wpdb->prefix . ACTIVECAMPAIGN_FOR_WOOCOMMERCE_TABLE_NAME . '`
    367                     WHERE
    368                         ( last_access_time < "' . $expire_datetime->format( 'Y-m-d H:i:s' ) . '"
    369                         OR last_access_time < str_to_date("' . $expire_datetime->format( 'Y-m-d H:i:s' ) . '", "Y-m-d H:i:s") )
    370                         AND order_date IS NULL
    371                         AND synced_to_ac = 0;'
     363            $all_carts = $wpdb->get_results( '
     364                SELECT
     365                    id, synced_to_ac, customer_ref_json, cart_ref_json, cart_totals_ref_json, removed_cart_contents_ref_json, activecampaignfwc_order_external_uuid, last_access_time, abandoned_date
     366                FROM
     367                    `' . $wpdb->prefix . ACTIVECAMPAIGN_FOR_WOOCOMMERCE_TABLE_NAME . '`
     368                WHERE
     369                    last_access_time IS NOT NULL
     370                    AND order_date IS NULL
     371                    AND synced_to_ac IN (' . implode(',', $synced_to_ac) . ') ORDER BY order_date ASC LIMIT 50;'
    372372            );
    373373            // phpcs:enable
    374374
     375            $parsed_carts = array();
     376            foreach ($all_carts as $cart ) {
     377                $last = new DateTime( $cart->last_access_time );
     378                if ($last->getTimestamp() < $expire_datetime->getTimestamp() ) {
     379                    $parsed_carts[] = $cart;
     380                }
     381            }
    375382            if ( $wpdb->last_error ) {
    376                 $this->logger->notice(
    377                     'Abandonment sync: There was an error getting results for abandoned cart records.',
    378                     array(
    379                         'wpdb_last_error' => $wpdb->last_error,
    380                     )
    381                 );
    382             }
    383 
    384             $this->clean_all_old_abandoned_carts();
    385 
    386             if ( ! empty( $abandoned_carts ) ) {
    387                 // abandoned carts found
    388                 return $abandoned_carts;
     383                $this->logger->error(
     384                    'A database error was encountered while getting results for abandoned cart records.',
     385                    array(
     386                        'wpdb_last_error'  => $wpdb->last_error,
     387                        'wpdb_last_query'  => $wpdb->last_query,
     388                        'suggested_action' => 'Please verify that the query is correct and cron process has read access to the ' . ACTIVECAMPAIGN_FOR_WOOCOMMERCE_TABLE_NAME . ' table',
     389                        'ac_code'          => 'RASC_301',
     390                    )
     391                );
     392            }
     393
     394            if ( ! empty( $parsed_carts ) ) {
     395                return $parsed_carts; // abandoned carts found
    389396            } else {
    390                 // no abandoned carts
    391                 return false;
     397                return false; // no abandoned carts to process
    392398            }
    393399        } catch ( Throwable $t ) {
    394             $this->logger->notice(
    395                 'Abandonment Sync: There was an error with preparing or getting abandoned cart results.',
     400            $this->logger->error(
     401                'An error was thrown while preparing or getting abandoned cart results.',
    396402                array(
    397403                    'message' => $t->getMessage(),
     404                    'ac_code' => 'RASC_320',
    398405                    'trace'   => $this->logger->clean_trace( $t->getTrace() ),
    399406                )
     
    10271034    private function calculate_abandoned_date( $cart ) {
    10281035        $logger = new Logger();
     1036        $now    = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
    10291037
    10301038        if ( isset( $cart->last_access_time ) && ( ! isset( $cart->abandoned_date ) || empty( $cart->abandoned_date ) ) ) {
    1031 
    1032                 $now = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
    1033 
    1034                 // 1 hour is the default
     1039            // 1 hour is the default
    10351040            if ( ! isset( $this->expire_time ) || empty( $this->expire_time ) ) {
    10361041                $this->expire_time = 1;
    10371042            }
    10381043
    1039                 $expire_datetime = new DateTime( 'now -' . $this->expire_time . ' hours', new DateTimeZone( 'UTC' ) );
    1040                 $ab_date         = new DateTime( $cart->last_access_time . ' + ' . $this->expire_time . ' hours', new DateTimeZone( 'UTC' ) );
    1041 
    1042                 $i        = 0;
    1043                 $hourdiff = 0;
     1044            // The expiration datetime limit
     1045            $expire_datetime = new DateTime( 'now -' . $this->expire_time . ' hours', new DateTimeZone( 'UTC' ) );
     1046            // The calculated abandoned date if we used the last access time with added expiration
     1047            $ab_date = new DateTime( $cart->last_access_time . ' + ' . $this->expire_time . ' hours', new DateTimeZone( 'UTC' ) );
     1048
     1049            $i        = 0;
     1050            $hourdiff = 0;
    10441051
    10451052            try {
    1046                 $diff           = $expire_datetime->diff( $ab_date, true );
     1053                $diff           = $expire_datetime->diff( $ab_date, true ); // The difference from expiration to abandonment
    10471054                $hours_in_days  = $diff->format( '%d' ) * 24; // get number of hours in days
    1048                 $hours_in_hours = $diff->format( '%h' ); // add number of hours in hours
     1055                $hours_in_hours = $diff->format( '%h' ); // add number of hours in hours for total hours
    10491056
    10501057                if ( ! empty( $hours_in_days ) ) {
     
    10701077            try {
    10711078                // secondary method to check
    1072                 $hourdiff = round( ( strtotime( $cart->last_access_time + $this->expire_time ) - strtotime( $expire_datetime->format( 'Y-m-d H:i:s' ) ) ) / 3600, 0 );
     1079                $timestamp_offset = $this->expire_time * 3600; // offset in hours (expire_time is in hours)
     1080                $hourdiff         = ( strtotime( $expire_datetime->format( 'Y-m-d H:i:s' ) ) - strtotime( $cart->last_access_time ) + $timestamp_offset ) / 3600;
    10731081            } catch ( Throwable $t ) {
    10741082                // cannot use this method
     
    10831091                );
    10841092            }
     1093
    10851094            try {
    10861095                // calc_abandoned_date is calculated by the DB
    10871096                if ( ! empty( $cart->calc_abandoned_date ) && empty( $cart->abandoned_date ) ) {
    10881097                    $c_ab_date = new DateTime( $cart->calc_abandoned_date, new DateTimeZone( 'UTC' ) );
     1098
    10891099                    return $c_ab_date->format( 'Y-m-d H:i:s e' );
    10901100                } elseif ( empty( $cart->calc_abandoned_date ) && empty( $cart->abandoned_date ) ) {
     
    10961106                }
    10971107
    1098                 // If this is manually force synced and not old enough use now as the time
     1108                // This is manually force synced and not old enough, use now as the time
    10991109                return $now->format( 'Y-m-d H:i:s e' );
    11001110            } catch ( Throwable $t ) {
     
    11091119                if ( isset( $cart->calc_abandoned_date ) && ! empty( $cart->calc_abandoned_date ) ) {
    11101120                    $ab_date = new DateTime( $cart->abandoned_date, new DateTimeZone( 'UTC' ) );
     1121
     1122                    // Return the abandoned date
    11111123                    return $ab_date->format( 'Y-m-d H:i:s e' );
    11121124                }
    11131125            }
    11141126        } elseif ( isset( $cart->abandoned_date ) && ! empty( $cart->abandoned_date ) ) {
     1127            // pass back the recorded date in UTC
    11151128            $ab_date = new DateTime( $cart->abandoned_date, new DateTimeZone( 'UTC' ) );
     1129
    11161130            return $ab_date->format( 'Y-m-d H:i:s e' );
    11171131        }
    11181132
    1119         $now = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
     1133        // Just return now
    11201134        return $now->format( 'Y-m-d H:i:s e' );
    11211135    }
  • activecampaign-for-woocommerce/tags/2.9.0/includes/abandoned_carts/class-activecampaign-for-woocommerce-save-abandoned-cart-command.php

    r3232769 r3251904  
    1313use Activecampaign_For_Woocommerce_User_Meta_Service as User_Meta_Service;
    1414use Activecampaign_For_Woocommerce_Synced_Status_Interface as Synced_Status;
    15 
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1616/**
    1717 * Save the cart to a table to keep the record in case it gets abandoned
     
    7575        }
    7676        // Schedule single event for a logged in user if there's a cart
    77         $this->schedule_recurring_abandon_cart_task();
     77        // $this->schedule_recurring_abandon_cart_task(); removed
     78        $scheduler = new Activecampaign_For_Woocommerce_Scheduler_Handler();
     79
     80        try {
     81            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::RECURRING_ABANDONED_SYNC ) ) {
     82                AC_Scheduler::schedule_ac_event( AC_Scheduler::RECURRING_ABANDONED_SYNC, array(), true );
     83            }
     84        } catch ( Throwable $t ) {
     85            $this->logger->debug(
     86                'There was an issue scheduling the abandoned cart event.',
     87                array(
     88                    'message' => $t->getMessage(),
     89                )
     90            );
     91        }
    7892    }
    7993
     
    99113                $this->logger->debug( 'Could not prep abandoned cart data' );
    100114            }
    101             $this->schedule_recurring_abandon_cart_task();
     115            // removed function
     116            // $this->schedule_recurring_abandon_cart_task();
     117            $scheduler = new Activecampaign_For_Woocommerce_Scheduler_Handler();
     118
     119            try {
     120                if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::RECURRING_ABANDONED_SYNC ) ) {
     121                    AC_Scheduler::schedule_ac_event( AC_Scheduler::RECURRING_ABANDONED_SYNC, array(), true );
     122                }
     123            } catch ( Throwable $t ) {
     124                $this->logger->debug(
     125                    'There was an issue scheduling the abandoned cart event.',
     126                    array(
     127                        'message' => $t->getMessage(),
     128                    )
     129                );
     130            }
    102131
    103132            return true;
  • activecampaign-for-woocommerce/tags/2.9.0/includes/abandoned_carts/trait-activecampaign-for-woocommerce-abandoned-cart-utilities.php

    r3220303 r3251904  
    1313use Activecampaign_For_Woocommerce_Customer_Utilities as Customer_Utilities;
    1414use Activecampaign_For_Woocommerce_Logger as Logger;
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1516
    1617/**
     
    4344                    WHERE
    4445                        id = %s
    45                         AND order_date IS NULL',
     46                        AND order_date IS NULL LIMIT 50',
    4647                    $id
    4748                )
     
    240241    /**
    241242     * This schedules the recurring event and verifies it's still set up
     243     *
     244     * @deprecated
    242245     */
    243246    public function schedule_recurring_abandon_cart_task() {
     
    246249
    247250        try {
    248             if ( ! wp_next_scheduled( 'activecampaign_for_woocommerce_cart_updated_recurring_event' ) ) {
    249                 wp_schedule_event( time() + 10, 'every_minute', 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
     251            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::RECURRING_ABANDONED_SYNC ) ) {
     252                AC_Scheduler::schedule_ac_event( AC_Scheduler::RECURRING_ABANDONED_SYNC, array(), true, false );
    250253            } elseif ( function_exists( 'wp_get_scheduled_event' ) ) {
    251                     $logger->debug_excess(
    252                         'Recurring cron already scheduled',
    253                         array(
    254                             'time_now' => time(),
    255                             'myevent'  => wp_get_scheduled_event( 'activecampaign_for_woocommerce_cart_updated_recurring_event' ),
    256                         )
    257                     );
     254                $logger->debug_excess(
     255                    'Recurring cron already scheduled',
     256                    array(
     257                        'time_now' => time(),
     258                        'myevent'  => AC_Scheduler::get_schedule( AC_Scheduler::RECURRING_ABANDONED_SYNC ),
     259                    )
     260                );
    258261            }
    259262        } catch ( Throwable $t ) {
  • activecampaign-for-woocommerce/tags/2.9.0/includes/class-activecampaign-for-woocommerce-deactivator.php

    r3220303 r3251904  
    1212
    1313use Activecampaign_For_Woocommerce_Logger as Logger;
     14use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1415
    1516/**
     
    4142        // Should we clean the table out on deactivation?
    4243        $this->logger->info( 'Deactivation running...' );
    43         $this->clear_events();
     44        AC_Scheduler::remove_all_events();
    4445        $this->logger->info( 'ActiveCampaign for WooCommerce Deactivated.' );
    4546    }
    46 
    47     /**
    48      * Clears the events that have been created.
    49      */
    50     private function clear_events() {
    51         // clear activecampaign_for_woocommerce_cart_updated_recurring_event
    52         wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    53         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    54 
    55         if ( wp_next_scheduled( 'activecampaign_for_woocommerce_cart_updated_recurring_event' ) ) {
    56             $this->logger->info( 'Clearing scheduled events...' );
    57 
    58             wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    59 
    60             if ( function_exists( 'wp_get_scheduled_event' ) ) {
    61                 $this->logger->info(
    62                     'Verify that the scheduled event was removed...',
    63                     array(
    64                         'activecampaign_for_woocommerce_cart_updated_recurring_event' => wp_get_scheduled_event( 'activecampaign_for_woocommerce_cart_updated_recurring_event' ),
    65                     )
    66                 );
    67             }
    68         } else {
    69             $this->logger->info( 'Abandoned cart event not scheduled. Nothing to deactivate.' );
    70         }
    71 
    72         // Clear activecampaign_for_woocommerce_run_order_sync
    73         if ( wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME ) ) {
    74             $this->logger->info( 'Clearing scheduled events...' );
    75 
    76             wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    77 
    78             if ( function_exists( 'wp_get_scheduled_event' ) ) {
    79                 $this->logger->info(
    80                     'Verify that the scheduled event was removed...',
    81                     array(
    82                         'activecampaign_for_woocommerce_run_order_sync_event' => wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME ),
    83                     )
    84                 );
    85             }
    86         } else {
    87             $this->logger->info( 'Order sync event not scheduled. Nothing to deactivate.' );
    88         }
    89     }
    9047}
  • activecampaign-for-woocommerce/tags/2.9.0/includes/class-activecampaign-for-woocommerce-plugin-upgrade.php

    r3232769 r3251904  
    350350            wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    351351            // erase and reconfigure to use a faster time sequence.
    352             wp_schedule_event( time() + 10, 'every_minute', 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    353352        } catch ( Throwable $t ) {
    354353            $this->logger->error(
  • activecampaign-for-woocommerce/tags/2.9.0/includes/config/activecampaign-for-woocommerce-global-constants.php

    r3242090 r3251904  
    2626 */
    2727if ( ! defined( 'ACTIVECAMPAIGN_FOR_WOOCOMMERCE_VERSION' ) ) {
    28     define( 'ACTIVECAMPAIGN_FOR_WOOCOMMERCE_VERSION', '2.8.7' );
     28    define( 'ACTIVECAMPAIGN_FOR_WOOCOMMERCE_VERSION', '2.9.0' );
    2929}
    3030
  • activecampaign-for-woocommerce/tags/2.9.0/includes/orders/class-activecampaign-for-woocommerce-new-order-created-event.php

    r3239596 r3251904  
    1616use Activecampaign_For_Woocommerce_Customer_Utilities as Customer_Utilities;
    1717use Activecampaign_For_Woocommerce_Synced_Status_Interface as Synced_Status;
    18 
     18use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1919/**
    2020 * The Order_Finished Event Class.
     
    504504        try {
    505505            // wp_clear_scheduled_hook('activecampaign_for_woocommerce_cart_updated_recurring_event');
    506             if ( ! wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME ) ) {
    507                 wp_schedule_event( time() + 10, 'ten_minute', ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
     506            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::RECURRING_ORDER_SYNC ) ) {
     507                AC_Scheduler::schedule_ac_event( AC_Scheduler::RECURRING_ORDER_SYNC, array(), true, false );
    508508            } elseif ( function_exists( 'wp_get_scheduled_event' ) ) {
    509509                $logger->debug_excess(
     
    511511                    array(
    512512                        'time_now' => time(),
    513                         'myevent'  => wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME ),
     513                        'myevent'  => AC_Scheduler::get_schedule( AC_Scheduler::RECURRING_ORDER_SYNC ),
    514514                    )
    515515                );
     
    533533    private function schedule_sync_job( $order_id ) {
    534534        try {
    535             if ( ! wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME, array( 'wc_order_id' => $order_id, 'event' => 'onetime' ) ) ) {
    536                 wp_schedule_single_event(
    537                     time() + 40,
    538                     'activecampaign_for_woocommerce_admin_sync_single_order_active',
     535            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::SYNC_ONE_ORDER_ACTIVE, array( 'wc_order_id' => $order_id, 'event' => 'onetime' ) ) ) {
     536                AC_Scheduler::schedule_ac_event(
     537                    AC_Scheduler::SYNC_ONE_ORDER_ACTIVE,
    539538                    array(
    540539                        'wc_order_id' => $order_id,
    541540                        'event'       => 'onetime',
    542541                    ),
    543                     true
     542                    false,
     543                    false
    544544                );
    545545            }
     
    551551                    'current_time'        => time(),
    552552                    'scheduled_time'      => time() + 40,
    553                     'schedule validation' => wp_get_scheduled_event( 'activecampaign_for_woocommerce_admin_sync_single_order_active', array( 'wc_order_id' => $order_id, 'event' => 'onetime' ) ),
     553                    'schedule validation' => AC_Scheduler::get_schedule( AC_Scheduler::SYNC_ONE_ORDER_ACTIVE, array( 'wc_order_id' => $order_id, 'event' => 'onetime' ) ),
    554554                )
    555555            );
  • activecampaign-for-woocommerce/tags/2.9.0/includes/orders/class-activecampaign-for-woocommerce-new-order-sync-job.php

    r3232769 r3251904  
    152152                    'message'     => $t->getMessage(),
    153153                    'stack_trace' => $t->getTrace(),
     154                    'ac_code'     => 'NOSJ_154',
    154155                )
    155156            );
     
    277278                    'message'     => $t->getMessage(),
    278279                    'stack_trace' => $t->getTrace(),
     280                    'ac_code'     => 'NOSJ_280',
    279281                )
    280282            );
     
    603605            } catch ( Throwable $t ) {
    604606                $this->logger->warning(
    605                     'customerid not set or threw an error',
     607                    'New order sync on customerid not set or threw an error',
    606608                    array(
    607609                        'unsynced_order' => $unsynced_order,
     
    674676            if ( $wpdb->last_error ) {
    675677                $this->logger->error(
    676                     'Abandonement sync: There was an error updating an abandoned cart record as synced.',
     678                    'There was an error checking if this order record synced.',
    677679                    array(
    678680                        'wpdb_last_error' => $wpdb->last_error,
     681                        'ac_code'         => 'NOSJ_681',
    679682                    )
    680683                );
     
    793796            if ( $wpdb->last_error ) {
    794797                $this->logger->error(
    795                     'Abandonment sync: There was an error getting results for abandoned cart records.',
     798                    'There was an error getting results for unsynced records.',
    796799                    array(
    797800                        'wpdb_last_error' => $wpdb->last_error,
     801                        'ac_code'         => 'NOSJ_801',
    798802                    )
    799803                );
     
    811815                    'message' => $t->getMessage(),
    812816                    'trace'   => $this->logger->clean_trace( $t->getTrace() ),
     817                    'ac_code' => 'NOSJ_813',
    813818                )
    814819            );
  • activecampaign-for-woocommerce/tags/2.9.0/includes/orders/class-activecampaign-for-woocommerce-order-action-events.php

    r3232769 r3251904  
    1313use Activecampaign_For_Woocommerce_Ecom_Order_Repository as Order_Repository;
    1414use Activecampaign_For_Woocommerce_Api_Client as Api_Client;
    15 
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1616/**
    1717 * The Order_Finished Event Class.
     
    4646
    4747            if ( isset( $order_id ) && null !== $order_id && ! empty( $order_id ) ) {
    48                 if ( ! wp_get_scheduled_event( 'activecampaign_for_woocommerce_ready_new_order', array( 'order_id' => $order_id ) ) ) {
    49                     wp_schedule_single_event(
    50                         time() + 30,
    51                         'activecampaign_for_woocommerce_ready_new_order',
    52                         array( 'order_id' => $order_id )
    53                     );
     48                $schedule_array = array( 'order_id' => $order_id );
     49
     50                if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::SYNC_ONE_NEW_ORDER, $schedule_array ) ) {
     51                    AC_Scheduler::schedule_ac_event( AC_Scheduler::SYNC_ONE_NEW_ORDER, $schedule_array, false, false );
    5452                }
    5553
     
    110108            if ( self::validate_object( $wc_order, 'get_data' ) && $this->check_update_validity( $wc_order ) ) {
    111109                set_transient( 'acforwc_order_updated_hook', wp_date( DATE_ATOM ), 604800 );
    112 
    113                 if ( ! wp_get_scheduled_event(
    114                     'activecampaign_for_woocommerce_admin_sync_single_order_active',
    115                     array(
    116                         'wc_order_id' => $order_id,
    117                         'status'      => $wc_order->get_status(),
    118                     )
    119                 ) &&
    120                     ! wp_get_scheduled_event(
    121                         'activecampaign_for_woocommerce_admin_sync_single_order_status',
    122                         array(
    123                             'wc_order_id' => $order_id,
    124                             'status'      => $wc_order->get_status(),
    125                         )
    126                     ) ) {
    127                     wp_schedule_single_event(
    128                         time() + 10,
    129                         'activecampaign_for_woocommerce_admin_sync_single_order_status',
    130                         array(
    131                             'wc_order_id' => $order_id,
    132                             'status'      => $wc_order->get_status(),
    133                         )
    134                     );
     110                $event_array = array(
     111                    'wc_order_id' => $order_id,
     112                    'status'      => $wc_order->get_status(),
     113                );
     114
     115                if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::SYNC_ONE_ORDER_ACTIVE, $event_array )
     116                    && ! AC_Scheduler::is_scheduled( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $event_array )
     117                ) {
     118                    // Schedule one time event
     119                    AC_Scheduler::schedule_ac_event( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $event_array, false, false );
    135120                }
    136121            } else {
     
    191176            if ( self::validate_object( $wc_order, 'get_data' ) ) {
    192177                set_transient( 'acforwc_order_updated_hook', wp_date( DATE_ATOM ), 604800 );
    193 
    194                 if ( ! wp_get_scheduled_event(
    195                     'activecampaign_for_woocommerce_admin_sync_single_order_status',
    196                     array(
    197                         'wc_order_id' => $order_id,
    198                         'status'      => $to_status,
    199                     )
    200                 ) ) {
    201                     wp_schedule_single_event(
    202                         time() + 10,
    203                         'activecampaign_for_woocommerce_admin_sync_single_order_status',
    204                         array(
    205                             'wc_order_id' => $order_id,
    206                             'status'      => $to_status,
    207                         )
    208                     );
     178                $event_array = array(
     179                    'wc_order_id' => $order_id,
     180                    'status'      => $to_status,
     181                );
     182                if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $event_array ) ) {
     183                    AC_Scheduler::schedule_ac_event( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $event_array, false, false );
    209184                }
    210185            }
     
    238213            }
    239214
    240             if ( ! wp_get_scheduled_event(
    241                 'activecampaign_for_woocommerce_admin_sync_single_order_status',
    242                 array(
    243                     'wc_order_id' => $order_id,
    244                     'event_type'  => 'status_' . $new_status,
    245                 )
    246             ) ) {
    247                 wp_schedule_single_event(
    248                     time() + 10,
    249                     'activecampaign_for_woocommerce_admin_sync_single_order_status',
    250                     array(
    251                         'wc_order_id' => $order_id,
    252                         'status'      => $new_status,
    253                     )
     215            $schedule_array = array(
     216                'wc_order_id' => $order_id,
     217                'status'      => $new_status,
     218            );
     219
     220            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $schedule_array ) ) {
     221                AC_Scheduler::schedule_ac_event(
     222                    AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER,
     223                    $schedule_array,
     224                    false,
     225                    false
    254226                );
    255227            }
  • activecampaign-for-woocommerce/tags/2.9.0/includes/orders/historical/class-activecampaign-for-woocommerce-historical-sync-contacts.php

    r3220303 r3251904  
    1717use Activecampaign_For_Woocommerce_AC_Contact_Batch as AC_Contact_Batch;
    1818use Activecampaign_For_Woocommerce_AC_Contact_Batch_Repository as AC_Contact_Batch_Repository;
     19use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1920
    2021/**
     
    194195
    195196    private function schedule_next( $start ) {
    196         wp_schedule_single_event(
    197             time() + 50,
    198             'activecampaign_for_woocommerce_run_historical_sync_contacts',
    199             array( 'start' => $start )
    200         );
     197        AC_Scheduler::schedule_ac_event( AC_Scheduler::HISTORICAL_SYNC_CONTACTS, array( 'start' => $start ), false, false );
    201198    }
    202199
  • activecampaign-for-woocommerce/tags/2.9.0/includes/orders/trait-activecampaign-for-woocommerce-order-data-gathering.php

    r3220303 r3251904  
    286286                    'coupon'  => $coupon,
    287287                    'trace'   => $logger->clean_trace( $t->getTrace() ),
     288                    'ac_code' => 'ODG_288',
    288289                )
    289290            );
     
    382383            if ( $wpdb->last_error ) {
    383384                $logger->error(
    384                     'Abandonment sync: There was an error getting results for abandoned cart records.',
     385                    'There was an error getting external checkout ID for record.',
    385386                    array(
    386387                        'wpdb_last_error' => $wpdb->last_error,
     388                        'order_id'        => $order_id,
     389                        'ac_code'         => 'ODG_388',
    387390                    )
    388391                );
     
    395398        } catch ( Throwable $t ) {
    396399            $logger->error(
    397                 'Abandonment Sync: There was an error with preparing or getting abandoned cart results.',
     400                'There was an error getting external checkout ID for record.',
    398401                array(
    399402                    'message' => $t->getMessage(),
    400403                    'trace'   => $logger->clean_trace( $t->getTrace() ),
     404                    'ac_code' => 'ODG_402',
    401405                )
    402406            );
     
    431435            if ( $wpdb->last_error ) {
    432436                $logger->error(
    433                     'Abandonment sync: There was an error getting results for abandoned cart records.',
     437                    'There was an error getting AC order id from the order record',
    434438                    array(
    435439                        'wpdb_last_error' => $wpdb->last_error,
     440                        'order_id'        => $order_id,
     441                        'ac_code'         => 'ODG_438',
    436442                    )
    437443                );
     
    444450        } catch ( Throwable $t ) {
    445451            $logger->error(
    446                 'Abandonment Sync: There was an error with preparing or getting abandoned cart results.',
     452                'There was a fatal error retrieving AC order id from order record.',
    447453                array(
    448454                    'message' => $t->getMessage(),
    449455                    'trace'   => $logger->clean_trace( $t->getTrace() ),
     456                    'ac_code' => 'ODG_453',
    450457                )
    451458            );
  • activecampaign-for-woocommerce/tags/2.9.0/includes/subscriptions/class-activecampaign-for-woocommerce-subscription-events.php

    r3232769 r3251904  
    1313use Activecampaign_For_Woocommerce_Logger as Logger;
    1414use Activecampaign_For_Woocommerce_Synced_Status_Interface as Synced_Status;
    15 
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Schedule;
    1616/**
    1717 * The Subscription Event Class.
     
    114114
    115115            if ( isset( $subscription_id ) && null !== $subscription_id && ! empty( $subscription_id ) ) {
    116                 if ( ! wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ) ) ) {
    117                     wp_schedule_single_event(
    118                         time() + 30,
    119                         'activecampaign_for_woocommerce_update_subscription',
    120                         array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ),
    121                         true
    122                     );
    123                 }
     116                AC_Schedule::schedule_ac_event( AC_Schedule::SYNC_ONE_SUBSCRIPTION_ORDER, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ), false, false );
    124117            }
    125118        } catch ( Throwable $t ) {
     
    159152            $this->update_status( $wc_subscription, 0 );
    160153            if ( isset( $subscription_id ) && null !== $subscription_id && ! empty( $subscription_id ) ) {
    161                 if ( ! wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ) ) ) {
    162                     wp_schedule_single_event(
    163                         time() + 30,
    164                         'activecampaign_for_woocommerce_update_subscription',
    165                         array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ),
    166                         true
    167                     );
     154
     155                if ( ! AC_Schedule::is_scheduled( AC_Schedule::SYNC_UPDATE_ONE_SUBSCRIPTION, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ) ) ) {
     156                    AC_Schedule::schedule_ac_event( AC_Schedule::SYNC_UPDATE_ONE_SUBSCRIPTION, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ), false, false );
    168157                }
    169158            }
  • activecampaign-for-woocommerce/tags/2.9.0/includes/subscriptions/trait-activecampaign-for-woocommerce-subscription-gathering.php

    r3220303 r3251904  
    2828    use Activecampaign_For_Woocommerce_Order_Line_Item_Gathering;
    2929
     30    /**
     31     * The connection id.
     32     *
     33     * @var string
     34     */
     35    private $connection_id;
     36
    3037    private function init() {
    3138        $admin_storage = get_option( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_DB_CONNECTION_STORAGE_NAME );
  • activecampaign-for-woocommerce/trunk/README.txt

    r3242090 r3251904  
    44Requires at least: 6.0
    55Tested up to: 6.7.1
    6 Stable tag: 2.8.7
     6Stable tag: 2.9.0
    77Requires PHP: 7.4
    88License: GPLv2 or later
     
    6868
    6969= WooCommerce Compatibility =
    70 * Tested up to version: 9.6.1
     70* Tested up to version: 9.7.1
    7171* Minimal version requirement: 7.4.0
    7272* HPOS Compatible
     
    9494
    9595== Changelog ==
     96
     97= 2.9.0 2025-03-06 =
     98* Improvement - Order sync scheduling rebuilt
     99* Improvement - Action Schedule will be preferred with fallback to cron
     100* Bugfix - Order sync and abandon sync process bugs resolved
    96101
    97102= 2.8.7 2025-02-13 =
  • activecampaign-for-woocommerce/trunk/ac_vendor/autoload.php

    r3242090 r3251904  
    55require_once __DIR__ . '/composer/autoload_real.php';
    66
    7 return ComposerAutoloaderInitd9bb3bd7e18ccd70aab112aebbce8079::getLoader();
     7return ComposerAutoloaderInit175e130378661b488bf176f44e675036::getLoader();
  • activecampaign-for-woocommerce/trunk/ac_vendor/composer/autoload_classmap.php

    r3220303 r3251904  
    382382    'Activecampaign_For_Woocommerce_Run_Abandonment_Sync_Command' => $baseDir . '/includes/abandoned_carts/class-activecampaign-for-woocommerce-run-abandonment-sync-command.php',
    383383    'Activecampaign_For_Woocommerce_Save_Abandoned_Cart_Command' => $baseDir . '/includes/abandoned_carts/class-activecampaign-for-woocommerce-save-abandoned-cart-command.php',
     384    'Activecampaign_For_Woocommerce_Scheduler_Handler' => $baseDir . '/includes/events/class-activecampaign-for-woocommerce-scheduler-handler.php',
    384385    'Activecampaign_For_Woocommerce_Set_Connection_Id_Cache_Command' => $baseDir . '/includes/commands/class-activecampaign-for-woocommerce-set-connection-id-cache-command.php',
    385386    'Activecampaign_For_Woocommerce_Simple_Graphql_Serializer' => $baseDir . '/includes/models/serializers/class-activecampaign-for-woocommerce-simple-graphql-serializer.php',
  • activecampaign-for-woocommerce/trunk/ac_vendor/composer/autoload_real.php

    r3242090 r3251904  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInitd9bb3bd7e18ccd70aab112aebbce8079
     5class ComposerAutoloaderInit175e130378661b488bf176f44e675036
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInitd9bb3bd7e18ccd70aab112aebbce8079', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit175e130378661b488bf176f44e675036', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
    29         spl_autoload_unregister(array('ComposerAutoloaderInitd9bb3bd7e18ccd70aab112aebbce8079', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit175e130378661b488bf176f44e675036', 'loadClassLoader'));
    3030
    3131        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
     
    3333            require __DIR__ . '/autoload_static.php';
    3434
    35             call_user_func(\Composer\Autoload\ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::getInitializer($loader));
     35            call_user_func(\Composer\Autoload\ComposerStaticInit175e130378661b488bf176f44e675036::getInitializer($loader));
    3636        } else {
    3737            $map = require __DIR__ . '/autoload_namespaces.php';
     
    5454
    5555        if ($useStaticLoader) {
    56             $includeFiles = Composer\Autoload\ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::$files;
     56            $includeFiles = Composer\Autoload\ComposerStaticInit175e130378661b488bf176f44e675036::$files;
    5757        } else {
    5858            $includeFiles = require __DIR__ . '/autoload_files.php';
    5959        }
    6060        foreach ($includeFiles as $fileIdentifier => $file) {
    61             composerRequired9bb3bd7e18ccd70aab112aebbce8079($fileIdentifier, $file);
     61            composerRequire175e130378661b488bf176f44e675036($fileIdentifier, $file);
    6262        }
    6363
     
    6666}
    6767
    68 function composerRequired9bb3bd7e18ccd70aab112aebbce8079($fileIdentifier, $file)
     68function composerRequire175e130378661b488bf176f44e675036($fileIdentifier, $file)
    6969{
    7070    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
  • activecampaign-for-woocommerce/trunk/ac_vendor/composer/autoload_static.php

    r3242090 r3251904  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079
     7class ComposerStaticInit175e130378661b488bf176f44e675036
    88{
    99    public static $files = array (
     
    465465        'Activecampaign_For_Woocommerce_Run_Abandonment_Sync_Command' => __DIR__ . '/../..' . '/includes/abandoned_carts/class-activecampaign-for-woocommerce-run-abandonment-sync-command.php',
    466466        'Activecampaign_For_Woocommerce_Save_Abandoned_Cart_Command' => __DIR__ . '/../..' . '/includes/abandoned_carts/class-activecampaign-for-woocommerce-save-abandoned-cart-command.php',
     467        'Activecampaign_For_Woocommerce_Scheduler_Handler' => __DIR__ . '/../..' . '/includes/events/class-activecampaign-for-woocommerce-scheduler-handler.php',
    467468        'Activecampaign_For_Woocommerce_Set_Connection_Id_Cache_Command' => __DIR__ . '/../..' . '/includes/commands/class-activecampaign-for-woocommerce-set-connection-id-cache-command.php',
    468469        'Activecampaign_For_Woocommerce_Simple_Graphql_Serializer' => __DIR__ . '/../..' . '/includes/models/serializers/class-activecampaign-for-woocommerce-simple-graphql-serializer.php',
     
    493494    {
    494495        return \Closure::bind(function () use ($loader) {
    495             $loader->prefixLengthsPsr4 = ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::$prefixLengthsPsr4;
    496             $loader->prefixDirsPsr4 = ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::$prefixDirsPsr4;
    497             $loader->classMap = ComposerStaticInitd9bb3bd7e18ccd70aab112aebbce8079::$classMap;
     496            $loader->prefixLengthsPsr4 = ComposerStaticInit175e130378661b488bf176f44e675036::$prefixLengthsPsr4;
     497            $loader->prefixDirsPsr4 = ComposerStaticInit175e130378661b488bf176f44e675036::$prefixDirsPsr4;
     498            $loader->classMap = ComposerStaticInit175e130378661b488bf176f44e675036::$classMap;
    498499
    499500        }, null, ClassLoader::class);
  • activecampaign-for-woocommerce/trunk/activecampaign-for-woocommerce.php

    r3242090 r3251904  
    1717 * Plugin URI:           https://www.activecampaign.com/
    1818 * Description:          Add Abandoned Cart functionality to your WooCommerce store, synchronize order & customer information using ActiveCampaign.
    19  * Version:              2.8.7
     19 * Version:              2.9.0
    2020 * WC requires at least: 7.4.0
    21  * WC tested up to:      9.6.1
     21 * WC tested up to:      9.7.1
    2222 * Requires at least:    6.0
    2323 * Requires PHP:         7.4
  • activecampaign-for-woocommerce/trunk/admin/class-activecampaign-for-woocommerce-admin-historical-sync.php

    r3232769 r3251904  
    1313use Activecampaign_For_Woocommerce_Logger as Logger;
    1414use Activecampaign_For_Woocommerce_Historical_Sync_Prep as Historical_Prep;
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1516
    1617/**
     
    4849        return false;
    4950    }
     51
    5052    /**
    5153     * Fetches the next historical sync cron time.
     
    5759        $data   = null;
    5860
    59         try {
    60             if ( function_exists( 'wp_get_scheduled_event' ) ) {
    61                 $historical_order_schedule = wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    62                 if ( $historical_order_schedule ) {
    63                     $data['historical_order_schedule']['error']     = false;
    64                     $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule->timestamp );
    65                     $data['historical_order_schedule']['schedule']  = $historical_order_schedule->schedule;
    66                     if ( $historical_order_schedule->timestamp && $historical_order_schedule->interval ) {
    67                         $next = $historical_order_schedule->timestamp + $historical_order_schedule->interval - time();
    68                         $data['historical_order_schedule']['next_scheduled'] = $next;
    69                     }
    70                 } else {
    71                     $data['historical_order_schedule']['error'] = true;
    72                     $logger->warning(
    73                         'Historical order sync is not scheduled.',
    74                         array(
    75                             'historical_order_schedule' => $historical_order_schedule,
    76                         )
    77                     );
    78                 }
    79             } elseif ( function_exists( 'wp_next_scheduled' ) ) {
    80                 $logger->warning( 'The wp_get_scheduled_event function may not exist. Performing wp_next_scheduled instead.' );
    81                 $historical_order_schedule                      = wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    82                 $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule );
    83             }
    84         } catch ( Throwable $t ) {
    85             $logger->warning(
    86                 'There was an issue getting the historical sync cron information.',
    87                 array(
    88                     'message' => $t->getMessage(),
    89                     'trace'   => $t->getTrace(),
    90                     'ac_code' => 'AHS_80',
    91                 )
    92             );
     61        $historical_order_schedule = AC_Scheduler::get_schedule( AC_Scheduler::RECURRING_HISTORICAL_SYNC );
     62
     63        if ( ! $historical_order_schedule ) {
     64            $data['historical_order_schedule']['error'] = true;
     65            $logger->warning(
     66                'Historical order sync is not scheduled.',
     67                array(
     68                    'historical_order_schedule' => $historical_order_schedule,
     69                )
     70            );
     71        } elseif (is_int( $historical_order_schedule ) ) {
     72            $data['historical_order_schedule']['error']          = false;
     73            $data['historical_order_schedule']['timestamp']      = wp_date( DATE_ATOM, $historical_order_schedule );
     74            $data['historical_order_schedule']['schedule']       = false;
     75            $data['historical_order_schedule']['next_scheduled'] = false;
     76        } else {
     77            $data['historical_order_schedule']['error']     = false;
     78            $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule->timestamp );
     79            $data['historical_order_schedule']['schedule']  = $historical_order_schedule->schedule;
     80
     81            if ( $historical_order_schedule->timestamp && $historical_order_schedule->interval ) {
     82                $next = $historical_order_schedule->timestamp + $historical_order_schedule->interval - time();
     83                $data['historical_order_schedule']['next_scheduled'] = $next;
     84            }
    9385        }
    9486
     
    134126            do_action( 'activecampaign_for_woocommerce_ready_existing_historical_data' );
    135127
    136             wp_schedule_single_event(
    137                 time() + 30,
    138                 'activecampaign_for_woocommerce_prep_historical_data',
    139                 array('current_page' => 0)
    140             );
     128            // schedule activecampaign_for_woocommerce_prep_historical_data
     129            AC_Scheduler::schedule_ac_event( AC_Scheduler::PREP_HISTORICAL_SYNC, array('current_page' => 0), false, false );
    141130
    142131            wp_send_json_success( 'Historical sync scheduled.' );
  • activecampaign-for-woocommerce/trunk/admin/class-activecampaign-for-woocommerce-admin-status.php

    r3227747 r3251904  
    1313use Activecampaign_For_Woocommerce_Logger as Logger;
    1414use Automattic\WooCommerce\Utilities\RestApiUtil;
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Schedule;
    1516
    1617/**
     
    500501    }
    501502
     503    private function check_for_event_data( $event_schedule ) {
     504        $logger     = new Logger();
     505        $event_data = array();
     506
     507        if ( ! empty( $event_schedule ) ) {
     508            $event_data['timestamp']      = wp_date( DATE_ATOM, $event_schedule );
     509            $event_data['next_scheduled'] = wp_date( DATE_ATOM, $event_schedule );
     510            $event_data['error']          = false;
     511
     512            if ( ! empty( $event_data['timestamp'] ) ) {
     513                return $event_data;
     514            }
     515        }
     516        if ( is_object( $event_schedule ) && ! empty( $event_schedule->timestamp ) ) {
     517            $event_data['timestamp'] = wp_date( DATE_ATOM, $event_schedule->timestamp );
     518
     519            if ( $event_schedule->timestamp && $event_schedule->interval ) {
     520                $next = $event_schedule->timestamp + $event_schedule->interval - time();
     521                $data['abandoned_schedule']['next_scheduled'] = $next;
     522            }
     523
     524            $event_data['schedule'] = $event_schedule->schedule;
     525            $event_data['error']    = false;
     526        }
     527
     528        return $event_data;
     529    }
     530
    502531    /**
    503532     * Gets the cron related data.
     
    510539        $logger = new Logger();
    511540
    512         try {
    513             if ( function_exists( 'wp_get_scheduled_event' ) ) {
    514                 $abandoned_schedule        = wp_get_scheduled_event( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    515                 $new_order_schedule        = wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    516                 $historical_order_schedule = wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    517 
    518                 if ( $abandoned_schedule ) {
    519                     $data['abandoned_schedule']['timestamp'] = wp_date( DATE_ATOM, $abandoned_schedule->timestamp );
    520 
    521                     if ( $abandoned_schedule->timestamp && $abandoned_schedule->interval ) {
    522                         $next = $abandoned_schedule->timestamp + $abandoned_schedule->interval - time();
    523                         $data['abandoned_schedule']['next_scheduled'] = $next;
    524                     }
    525 
    526                     $data['abandoned_schedule']['schedule'] = $abandoned_schedule->schedule;
    527                     $data['abandoned_schedule']['error']    = false;
    528                 } else {
    529                     $data['abandoned_schedule']['error'] = true;
    530                     $logger->warning(
    531                         'Abandoned cart is not scheduled.',
    532                         array(
    533                             'abandoned_cart_schedule' => $abandoned_schedule,
    534                         )
    535                     );
    536                 }
    537 
    538                 if ( $new_order_schedule ) {
    539                     $data['new_order_schedule']['error']     = false;
    540                     $data['new_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $new_order_schedule->timestamp );
    541                     $data['new_order_schedule']['schedule']  = $new_order_schedule->schedule;
    542                     if ( $new_order_schedule->timestamp && $new_order_schedule->interval ) {
    543                         $next = $new_order_schedule->timestamp + $new_order_schedule->interval - time();
    544                         $data['new_order_schedule']['next_scheduled'] = $next;
    545                     }
    546                 } else {
    547                     $data['new_order_schedule']['error'] = true;
    548                     $logger->warning(
    549                         'New order sync is not scheduled.',
    550                         array(
    551                             'new_order_schedule' => $new_order_schedule,
    552                         )
    553                     );
    554                 }
    555 
    556                 if ( $historical_order_schedule ) {
    557                     $data['historical_order_schedule']['error']     = false;
    558                     $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule->timestamp );
    559                     $data['historical_order_schedule']['schedule']  = $historical_order_schedule->schedule;
    560                     if ( $historical_order_schedule->timestamp && $historical_order_schedule->interval ) {
    561                         $next = $historical_order_schedule->timestamp + $historical_order_schedule->interval - time();
    562                         $data['historical_order_schedule']['next_scheduled'] = $next;
    563                     }
    564                 } else {
    565                     $data['historical_order_schedule']['error'] = true;
    566                     $logger->warning(
    567                         'Historical order sync is not scheduled.',
    568                         array(
    569                             'historical_order_schedule' => $historical_order_schedule,
    570                         )
    571                     );
    572                 }
    573             } elseif ( function_exists( 'wp_next_scheduled' ) ) {
    574                 $logger->warning( 'The wp_get_scheduled_event function may not exist. Performing wp_next_scheduled instead.' );
    575                 $abandoned_schedule                             = wp_next_scheduled( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    576                 $new_order_schedule                             = wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    577                 $historical_order_schedule                      = wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    578                 $data['abandoned_schedule']['timestamp']        = wp_date( DATE_ATOM, $abandoned_schedule );
    579                 $data['new_order_schedule']['timestamp']        = wp_date( DATE_ATOM, $new_order_schedule );
    580                 $data['historical_order_schedule']['timestamp'] = wp_date( DATE_ATOM, $historical_order_schedule );
    581                 $data['new_order_schedule']['error']            = false;
    582                 if ( ! $new_order_schedule || ! $abandoned_schedule ) {
    583                     $logger->warning(
    584                         'An order sync is not scheduled.',
    585                         array(
    586                             'new_order_schedule'        => $new_order_schedule,
    587                             'historical_order_schedule' => $historical_order_schedule,
    588                             'abandoned_cart_schedule'   => $abandoned_schedule,
    589                         )
    590                     );
    591                 }
    592             } else {
    593                 $data['new_order_schedule']['error'] = true;
    594                 $logger->warning( 'One of the cron syncs may not be scheduled.' );
    595             }
    596         } catch ( Throwable $t ) {
    597             $logger->warning(
    598                 'ActiveCampaign status page threw an error',
    599                 array(
    600                     'message' => $t->getMessage(),
    601                 )
    602             );
     541        $abandoned_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_ABANDONED_SYNC );
     542        $data['abandoned_schedule'] = $this->check_for_event_data( $abandoned_schedule );
     543        if ( ! $data['abandoned_schedule'] ) {
     544            AC_Schedule::schedule_ac_event( AC_Schedule::RECURRING_ABANDONED_SYNC, array(), true, false );
     545
     546            $abandoned_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_ABANDONED_SYNC );
     547            $data['abandoned_schedule'] = $this->check_for_event_data( $abandoned_schedule );
     548        }
     549        if ( ! $data['abandoned_schedule'] ) {
     550            $data['abandoned_schedule']['error'] = true;
     551            $logger->warning( 'Abandoned cart is not scheduled.', array( 'abandoned_cart_schedule' => $data['abandoned_schedule'] ) );
     552        }
     553
     554        $new_order_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_ORDER_SYNC );
     555        $data['new_order_schedule'] = $this->check_for_event_data( $new_order_schedule );
     556        if ( ! $data['new_order_schedule'] ) {
     557            AC_Schedule::schedule_ac_event( AC_Schedule::RECURRING_ORDER_SYNC, array(), true, false );
     558
     559            $new_order_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_ORDER_SYNC );
     560            $data['new_order_schedule'] = $this->check_for_event_data( $new_order_schedule );
     561        }
     562        if ( ! $data['new_order_schedule'] ) {
    603563            $data['new_order_schedule']['error'] = true;
     564            $logger->warning( 'New order sync is not scheduled.', array( 'new_order_schedule' => $data['new_order_schedule'] ) );
     565        }
     566
     567        $historical_order_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_HISTORICAL_SYNC );
     568        $data['historical_order_schedule'] = $this->check_for_event_data( $historical_order_schedule );
     569        if ( ! $data['historical_order_schedule'] ) {
     570            AC_Schedule::schedule_ac_event( AC_Schedule::RECURRING_HISTORICAL_SYNC, array(), true, false );
     571
     572            $historical_order_schedule         = AC_Schedule::get_schedule( AC_Schedule::RECURRING_HISTORICAL_SYNC );
     573            $data['historical_order_schedule'] = $this->check_for_event_data( $historical_order_schedule );
     574        }
     575        if ( ! $data['historical_order_schedule'] ) {
     576            $data['historical_order_schedule']['error'] = true;
     577            $logger->warning( 'Historical order sync is not scheduled.', array( 'historical_order_schedule' => $data['historical_order_schedule'] ) );
    604578        }
    605579
  • activecampaign-for-woocommerce/trunk/admin/class-activecampaign-for-woocommerce-admin.php

    r3242090 r3251904  
    2222use Activecampaign_For_Woocommerce_Ac_Tracking_Repository as AC_Tracking;
    2323use Activecampaign_For_Woocommerce_Whitelist_Repository as AC_Whitelist_Repository;
     24use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    2425
    2526/**
     
    104105    private $api_client;
    105106
     107
    106108    /**
    107109     * Initialize the class and set its properties.
     
    126128    }
    127129
     130    /**
     131     * Adds a cron task for every 10 minutes.
     132     *
     133     * @param mixed $schedules The schedules.
     134     *
     135     * @return mixed
     136     */
    128137    public function cron_add_ten_minute( $schedules ) {
    129138        // Adds once weekly to the existing schedules.
     
    779788
    780789                if ( ! isset( $storage['connection_id'] ) || empty( $storage['connection_id'] ) ) {
    781                     $this->clear_cron_syncs();
     790                    AC_Scheduler::remove_all_events();
    782791                }
    783792            }
     
    11761185     */
    11771186    public function schedule_cron_syncs() {
    1178         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    1179         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    1180         wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    1181 
    11821187        try {
    11831188            if (
     
    11861191                $this->is_configured()
    11871192            ) {
    1188                 wp_schedule_event( time() + 10, 'ten_minute', 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    1189                 wp_schedule_event( time() + 10, 'ten_minute', ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    1190                 wp_schedule_event( time() + 15, 'every_minute', ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
     1193                $ac_scheduler = new AC_Scheduler();
     1194                // clear and reschedule all of these events ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR, ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME, activecampaign_for_woocommerce_cart_updated_recurring_event
     1195                $ac_scheduler->schedule_all_recurring_events( true );
    11911196            }
    11921197        } catch ( Throwable $t ) {
     
    12021207
    12031208    /**
    1204      * Unschedules cron syncs
    1205      */
    1206     public function clear_cron_syncs() {
    1207         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    1208         wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    1209         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    1210     }
    1211 
    1212     /**
    12131209     * Callback function to validate the user can save settings
    12141210     *
     
    12511247        try {
    12521248            if ( delete_option( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_DB_SETTINGS_NAME ) && delete_option( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_DB_CONNECTION_STORAGE_NAME ) ) {
    1253                 wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    1254                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    1255                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_PRODUCT_SYNC_NAME );
    1256                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_RECUR );
    1257                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_HISTORICAL_SYNC_NAME );
    1258                 wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_HISTORICAL_SYNC_SCHEDULED_STATUS_NAME );
    1259                 wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_prep_historical_data' );
     1249                AC_Scheduler::remove_all_events();
    12601250                delete_transient( 'activecampaign_for_woocommerce_all_connections' );
    12611251                delete_transient( 'activecampaign_for_woocommerce_connection' );
  • activecampaign-for-woocommerce/trunk/admin/trait-activecampaign-for-woocommerce-admin-connections.php

    r3242090 r3251904  
    174174                do_action( 'activecampaign_for_woocommerce_run_sync_connection' );
    175175                do_action( 'activecampaign_for_woocommerce_update_connection_options', array('new_connection') );
     176                Activecampaign_For_Woocommerce_Scheduler_Handler::schedule_all_recurring_events( true );
    176177                wp_send_json_success( 'Connection saved: ' . wp_json_encode( $connection->serialize_to_array() ) );
    177178            } else {
     
    219220                $this->delete_options_from_storage();
    220221                $this->update_storage_from_connection( $connection );
     222                Activecampaign_For_Woocommerce_Scheduler_Handler::schedule_all_recurring_events( false );
    221223                do_action( 'activecampaign_for_woocommerce_retrieve_connection_options', array('select_connection') );
    222224                wp_send_json_success( 'Connection saved.' );
    223225            }
    224226        }
     227
     228        Activecampaign_For_Woocommerce_Scheduler_Handler::remove_all_events();
    225229        wp_send_json_error( 'Something went wrong with setting the connection.' );
    226230    }
  • activecampaign-for-woocommerce/trunk/admin/trait-activecampaign-for-woocommerce-admin-utilities.php

    r3220303 r3251904  
    217217        return $options_to_be_saved;
    218218    }
     219
     220    private function debug_mode() {
     221        if (defined( 'ACFWC_DEBUG' ) ) {
     222            if (
     223                ACFWC_DEBUG !== null &&
     224                in_array( ACFWC_DEBUG, array(true, 1, '1') )
     225            ) {
     226                return true;
     227            }
     228        }
     229
     230        return false;
     231    }
    219232}
  • activecampaign-for-woocommerce/trunk/admin/views/activecampaign-for-woocommerce-abandoned-cart-display.php

    r3232769 r3251904  
    3030}
    3131
     32$activecampaign_for_woocommerce_now_datetime    = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
    3233$activecampaign_for_woocommerce_expire_datetime = new DateTime( 'now -' . $activecampaign_for_woocommerce_expire_time . ' hours', new DateTimeZone( 'UTC' ) );
    3334
     
    120121                    <?php endif; ?>
    121122                </h3>
     123                <table><tr>
     124                        <td>Abandonment cutoff time UTC:</td><td><?php echo esc_html( $activecampaign_for_woocommerce_expire_datetime->format( DATE_ATOM ) ); ?></td>
     125                    </tr><tr>
     126                        <td>Current time UTC:</td><td><?php echo esc_html( $activecampaign_for_woocommerce_now_datetime->format( DATE_ATOM ) ); ?></td>
     127                    </tr></table>
    122128                <h3>
    123129                    Total Abandoned Carts
  • activecampaign-for-woocommerce/trunk/admin/views/activecampaign-for-woocommerce-admin-display.php

    r3242090 r3251904  
    765765                                > Off
    766766                            </label>
    767                             <label class="radio" style="display:none;">
     767                            <label class="radio"
     768                            <?php
     769                            if ( ! $this->debug_mode() ) :
     770                                ?>
     771                                style="display:none;"<?php endif; ?>>
    768772                                <input type="radio" id="browse_tracking3" name="browse_tracking" value="3"
    769773                                <?php
  • activecampaign-for-woocommerce/trunk/includes/abandoned_carts/class-activecampaign-for-woocommerce-run-abandonment-sync-command.php

    r3220303 r3251904  
    135135        set_transient( 'acforwc_abandoned_task_hook', wp_date( DATE_ATOM ), 604800 );
    136136
    137         $now      = date_create( 'NOW' );
    138         $last_run = get_option( 'activecampaign_for_woocommerce_abandoned_cart_last_run' );
     137        $now              = date_create( 'NOW' );
     138        $last_run         = get_option( 'activecampaign_for_woocommerce_abandoned_cart_last_run' );
     139        $interval_minutes = 0;
    139140
    140141        if ( false !== $last_run ) {
    141142            $interval         = date_diff( $now, $last_run );
    142143            $interval_minutes = $interval->format( '%i' );
    143         } else {
    144             $interval_minutes = 0;
    145144        }
    146145
    147146        if ( false === $last_run || 5 <= $interval_minutes ) {
    148147            do_action( 'activecampaign_for_woocommerce_verify_tables' );
    149 
    150148            $this->run_abandoned_carts();
    151149        }
     
    169167        }
    170168
    171         // Check for legacy abandoned carts
    172         $abandoned_carts = $this->get_all_abandoned_carts_from_table_legacy();
     169        // Process first failure records
     170        $abandoned_carts = $this->get_all_abandoned_carts_from_table( self::STATUS_ABANDONED_CART_NETWORK_FAIL_RETRY );
    173171        if ( ! empty( $abandoned_carts ) ) {
    174172            $this->process_abandoned_carts_per_record( $abandoned_carts ); // Process this group
    175173            $cart_count += count( $abandoned_carts );
    176         } else {
    177             $this->logger->debug_excess( 'Abandoned cart hourly task: No legacy abandoned carts to process...' );
    178174        }
    179175
     
    187183        }
    188184
     185        $abandoned_carts = $this->get_all_abandoned_carts_from_table_use_code_sort();
     186        if ( ! empty( $abandoned_carts ) ) {
     187            $this->process_abandoned_carts_per_record( $abandoned_carts ); // Process this group
     188            $cart_count += count( $abandoned_carts );
     189        } else {
     190            $this->logger->debug_excess( 'Abandoned cart hourly task: No code based abandoned carts to process...' );
     191        }
     192
    189193        $this->clean_old_synced_abandoned_carts();
    190194        $this->clean_all_old_abandoned_carts();
     
    262266
    263267    /**
    264      * Get all active carts.
    265      *
    266      * @return mixed Whether or not there are abandoned carts.
    267      * @throws Throwable Thrown message.
     268     * Get all abandoned carts.
     269     *
     270     * @param int $synced_to_ac Status to request.
     271     *
     272     * @return array|false|object|stdClass[]|void
    268273     */
    269274    private function get_all_abandoned_carts_from_table( $synced_to_ac = self::STATUS_ABANDONED_CART_UNSYNCED ) {
     
    298303                    )
    299304                    AND order_date IS NULL
    300                     AND synced_to_ac = ' . $synced_to_ac . ';'
     305                    AND synced_to_ac = ' . $synced_to_ac . ' LIMIT 50;'
    301306            );
    302307            // phpcs:enable
     
    314319            }
    315320
    316             $this->clean_old_synced_abandoned_carts();
    317             $this->clean_all_old_abandoned_carts();
    318 
    319321            if ( ! empty( $abandoned_carts ) ) {
    320322                return $abandoned_carts; // abandoned carts found
     
    335337
    336338    /**
    337      * Get all active carts.
    338      *
    339      * @deprecated This will need to be removed after a few versions as we moved from a common unsynced value of 0 to 20 for abandoned carts specifically.
    340      *
    341      * @return mixed Whether or not there are abandoned carts.
    342      * @throws Throwable Thrown message.
    343      */
    344     private function get_all_abandoned_carts_from_table_legacy() {
     339     * Use code to sort out if the cart is ready to sync.
     340     *
     341     * @return array|false|void
     342     */
     343    private function get_all_abandoned_carts_from_table_use_code_sort() {
    345344        global $wpdb;
    346345
    347346        // default is 1 hour abandon cart expiration
    348347        $this->expire_time = 1;
     348        $synced_to_ac      = array( self::STATUS_ABANDONED_CART_UNSYNCED, self::STATUS_ABANDONED_CART_FAILED_WAIT, self::STATUS_ABANDONED_CART_FAILED_2, self::STATUS_ABANDONED_CART_NETWORK_FAIL_RETRY );
    349349
    350350        // Get the expire time period from the db
     
    361361            // Get the expired carts from our table
    362362            // phpcs:disable
    363             $abandoned_carts = $wpdb->get_results(
    364                 'SELECT id, synced_to_ac, customer_ref_json, cart_ref_json, cart_totals_ref_json, removed_cart_contents_ref_json, activecampaignfwc_order_external_uuid, last_access_time, ADDTIME(last_access_time, "' . $this->expire_time . ':00:00") as calc_abandoned_date
    365                     FROM
    366                         `' . $wpdb->prefix . ACTIVECAMPAIGN_FOR_WOOCOMMERCE_TABLE_NAME . '`
    367                     WHERE
    368                         ( last_access_time < "' . $expire_datetime->format( 'Y-m-d H:i:s' ) . '"
    369                         OR last_access_time < str_to_date("' . $expire_datetime->format( 'Y-m-d H:i:s' ) . '", "Y-m-d H:i:s") )
    370                         AND order_date IS NULL
    371                         AND synced_to_ac = 0;'
     363            $all_carts = $wpdb->get_results( '
     364                SELECT
     365                    id, synced_to_ac, customer_ref_json, cart_ref_json, cart_totals_ref_json, removed_cart_contents_ref_json, activecampaignfwc_order_external_uuid, last_access_time, abandoned_date
     366                FROM
     367                    `' . $wpdb->prefix . ACTIVECAMPAIGN_FOR_WOOCOMMERCE_TABLE_NAME . '`
     368                WHERE
     369                    last_access_time IS NOT NULL
     370                    AND order_date IS NULL
     371                    AND synced_to_ac IN (' . implode(',', $synced_to_ac) . ') ORDER BY order_date ASC LIMIT 50;'
    372372            );
    373373            // phpcs:enable
    374374
     375            $parsed_carts = array();
     376            foreach ($all_carts as $cart ) {
     377                $last = new DateTime( $cart->last_access_time );
     378                if ($last->getTimestamp() < $expire_datetime->getTimestamp() ) {
     379                    $parsed_carts[] = $cart;
     380                }
     381            }
    375382            if ( $wpdb->last_error ) {
    376                 $this->logger->notice(
    377                     'Abandonment sync: There was an error getting results for abandoned cart records.',
    378                     array(
    379                         'wpdb_last_error' => $wpdb->last_error,
    380                     )
    381                 );
    382             }
    383 
    384             $this->clean_all_old_abandoned_carts();
    385 
    386             if ( ! empty( $abandoned_carts ) ) {
    387                 // abandoned carts found
    388                 return $abandoned_carts;
     383                $this->logger->error(
     384                    'A database error was encountered while getting results for abandoned cart records.',
     385                    array(
     386                        'wpdb_last_error'  => $wpdb->last_error,
     387                        'wpdb_last_query'  => $wpdb->last_query,
     388                        'suggested_action' => 'Please verify that the query is correct and cron process has read access to the ' . ACTIVECAMPAIGN_FOR_WOOCOMMERCE_TABLE_NAME . ' table',
     389                        'ac_code'          => 'RASC_301',
     390                    )
     391                );
     392            }
     393
     394            if ( ! empty( $parsed_carts ) ) {
     395                return $parsed_carts; // abandoned carts found
    389396            } else {
    390                 // no abandoned carts
    391                 return false;
     397                return false; // no abandoned carts to process
    392398            }
    393399        } catch ( Throwable $t ) {
    394             $this->logger->notice(
    395                 'Abandonment Sync: There was an error with preparing or getting abandoned cart results.',
     400            $this->logger->error(
     401                'An error was thrown while preparing or getting abandoned cart results.',
    396402                array(
    397403                    'message' => $t->getMessage(),
     404                    'ac_code' => 'RASC_320',
    398405                    'trace'   => $this->logger->clean_trace( $t->getTrace() ),
    399406                )
     
    10271034    private function calculate_abandoned_date( $cart ) {
    10281035        $logger = new Logger();
     1036        $now    = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
    10291037
    10301038        if ( isset( $cart->last_access_time ) && ( ! isset( $cart->abandoned_date ) || empty( $cart->abandoned_date ) ) ) {
    1031 
    1032                 $now = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
    1033 
    1034                 // 1 hour is the default
     1039            // 1 hour is the default
    10351040            if ( ! isset( $this->expire_time ) || empty( $this->expire_time ) ) {
    10361041                $this->expire_time = 1;
    10371042            }
    10381043
    1039                 $expire_datetime = new DateTime( 'now -' . $this->expire_time . ' hours', new DateTimeZone( 'UTC' ) );
    1040                 $ab_date         = new DateTime( $cart->last_access_time . ' + ' . $this->expire_time . ' hours', new DateTimeZone( 'UTC' ) );
    1041 
    1042                 $i        = 0;
    1043                 $hourdiff = 0;
     1044            // The expiration datetime limit
     1045            $expire_datetime = new DateTime( 'now -' . $this->expire_time . ' hours', new DateTimeZone( 'UTC' ) );
     1046            // The calculated abandoned date if we used the last access time with added expiration
     1047            $ab_date = new DateTime( $cart->last_access_time . ' + ' . $this->expire_time . ' hours', new DateTimeZone( 'UTC' ) );
     1048
     1049            $i        = 0;
     1050            $hourdiff = 0;
    10441051
    10451052            try {
    1046                 $diff           = $expire_datetime->diff( $ab_date, true );
     1053                $diff           = $expire_datetime->diff( $ab_date, true ); // The difference from expiration to abandonment
    10471054                $hours_in_days  = $diff->format( '%d' ) * 24; // get number of hours in days
    1048                 $hours_in_hours = $diff->format( '%h' ); // add number of hours in hours
     1055                $hours_in_hours = $diff->format( '%h' ); // add number of hours in hours for total hours
    10491056
    10501057                if ( ! empty( $hours_in_days ) ) {
     
    10701077            try {
    10711078                // secondary method to check
    1072                 $hourdiff = round( ( strtotime( $cart->last_access_time + $this->expire_time ) - strtotime( $expire_datetime->format( 'Y-m-d H:i:s' ) ) ) / 3600, 0 );
     1079                $timestamp_offset = $this->expire_time * 3600; // offset in hours (expire_time is in hours)
     1080                $hourdiff         = ( strtotime( $expire_datetime->format( 'Y-m-d H:i:s' ) ) - strtotime( $cart->last_access_time ) + $timestamp_offset ) / 3600;
    10731081            } catch ( Throwable $t ) {
    10741082                // cannot use this method
     
    10831091                );
    10841092            }
     1093
    10851094            try {
    10861095                // calc_abandoned_date is calculated by the DB
    10871096                if ( ! empty( $cart->calc_abandoned_date ) && empty( $cart->abandoned_date ) ) {
    10881097                    $c_ab_date = new DateTime( $cart->calc_abandoned_date, new DateTimeZone( 'UTC' ) );
     1098
    10891099                    return $c_ab_date->format( 'Y-m-d H:i:s e' );
    10901100                } elseif ( empty( $cart->calc_abandoned_date ) && empty( $cart->abandoned_date ) ) {
     
    10961106                }
    10971107
    1098                 // If this is manually force synced and not old enough use now as the time
     1108                // This is manually force synced and not old enough, use now as the time
    10991109                return $now->format( 'Y-m-d H:i:s e' );
    11001110            } catch ( Throwable $t ) {
     
    11091119                if ( isset( $cart->calc_abandoned_date ) && ! empty( $cart->calc_abandoned_date ) ) {
    11101120                    $ab_date = new DateTime( $cart->abandoned_date, new DateTimeZone( 'UTC' ) );
     1121
     1122                    // Return the abandoned date
    11111123                    return $ab_date->format( 'Y-m-d H:i:s e' );
    11121124                }
    11131125            }
    11141126        } elseif ( isset( $cart->abandoned_date ) && ! empty( $cart->abandoned_date ) ) {
     1127            // pass back the recorded date in UTC
    11151128            $ab_date = new DateTime( $cart->abandoned_date, new DateTimeZone( 'UTC' ) );
     1129
    11161130            return $ab_date->format( 'Y-m-d H:i:s e' );
    11171131        }
    11181132
    1119         $now = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
     1133        // Just return now
    11201134        return $now->format( 'Y-m-d H:i:s e' );
    11211135    }
  • activecampaign-for-woocommerce/trunk/includes/abandoned_carts/class-activecampaign-for-woocommerce-save-abandoned-cart-command.php

    r3232769 r3251904  
    1313use Activecampaign_For_Woocommerce_User_Meta_Service as User_Meta_Service;
    1414use Activecampaign_For_Woocommerce_Synced_Status_Interface as Synced_Status;
    15 
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1616/**
    1717 * Save the cart to a table to keep the record in case it gets abandoned
     
    7575        }
    7676        // Schedule single event for a logged in user if there's a cart
    77         $this->schedule_recurring_abandon_cart_task();
     77        // $this->schedule_recurring_abandon_cart_task(); removed
     78        $scheduler = new Activecampaign_For_Woocommerce_Scheduler_Handler();
     79
     80        try {
     81            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::RECURRING_ABANDONED_SYNC ) ) {
     82                AC_Scheduler::schedule_ac_event( AC_Scheduler::RECURRING_ABANDONED_SYNC, array(), true );
     83            }
     84        } catch ( Throwable $t ) {
     85            $this->logger->debug(
     86                'There was an issue scheduling the abandoned cart event.',
     87                array(
     88                    'message' => $t->getMessage(),
     89                )
     90            );
     91        }
    7892    }
    7993
     
    99113                $this->logger->debug( 'Could not prep abandoned cart data' );
    100114            }
    101             $this->schedule_recurring_abandon_cart_task();
     115            // removed function
     116            // $this->schedule_recurring_abandon_cart_task();
     117            $scheduler = new Activecampaign_For_Woocommerce_Scheduler_Handler();
     118
     119            try {
     120                if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::RECURRING_ABANDONED_SYNC ) ) {
     121                    AC_Scheduler::schedule_ac_event( AC_Scheduler::RECURRING_ABANDONED_SYNC, array(), true );
     122                }
     123            } catch ( Throwable $t ) {
     124                $this->logger->debug(
     125                    'There was an issue scheduling the abandoned cart event.',
     126                    array(
     127                        'message' => $t->getMessage(),
     128                    )
     129                );
     130            }
    102131
    103132            return true;
  • activecampaign-for-woocommerce/trunk/includes/abandoned_carts/trait-activecampaign-for-woocommerce-abandoned-cart-utilities.php

    r3220303 r3251904  
    1313use Activecampaign_For_Woocommerce_Customer_Utilities as Customer_Utilities;
    1414use Activecampaign_For_Woocommerce_Logger as Logger;
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1516
    1617/**
     
    4344                    WHERE
    4445                        id = %s
    45                         AND order_date IS NULL',
     46                        AND order_date IS NULL LIMIT 50',
    4647                    $id
    4748                )
     
    240241    /**
    241242     * This schedules the recurring event and verifies it's still set up
     243     *
     244     * @deprecated
    242245     */
    243246    public function schedule_recurring_abandon_cart_task() {
     
    246249
    247250        try {
    248             if ( ! wp_next_scheduled( 'activecampaign_for_woocommerce_cart_updated_recurring_event' ) ) {
    249                 wp_schedule_event( time() + 10, 'every_minute', 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
     251            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::RECURRING_ABANDONED_SYNC ) ) {
     252                AC_Scheduler::schedule_ac_event( AC_Scheduler::RECURRING_ABANDONED_SYNC, array(), true, false );
    250253            } elseif ( function_exists( 'wp_get_scheduled_event' ) ) {
    251                     $logger->debug_excess(
    252                         'Recurring cron already scheduled',
    253                         array(
    254                             'time_now' => time(),
    255                             'myevent'  => wp_get_scheduled_event( 'activecampaign_for_woocommerce_cart_updated_recurring_event' ),
    256                         )
    257                     );
     254                $logger->debug_excess(
     255                    'Recurring cron already scheduled',
     256                    array(
     257                        'time_now' => time(),
     258                        'myevent'  => AC_Scheduler::get_schedule( AC_Scheduler::RECURRING_ABANDONED_SYNC ),
     259                    )
     260                );
    258261            }
    259262        } catch ( Throwable $t ) {
  • activecampaign-for-woocommerce/trunk/includes/class-activecampaign-for-woocommerce-deactivator.php

    r3220303 r3251904  
    1212
    1313use Activecampaign_For_Woocommerce_Logger as Logger;
     14use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1415
    1516/**
     
    4142        // Should we clean the table out on deactivation?
    4243        $this->logger->info( 'Deactivation running...' );
    43         $this->clear_events();
     44        AC_Scheduler::remove_all_events();
    4445        $this->logger->info( 'ActiveCampaign for WooCommerce Deactivated.' );
    4546    }
    46 
    47     /**
    48      * Clears the events that have been created.
    49      */
    50     private function clear_events() {
    51         // clear activecampaign_for_woocommerce_cart_updated_recurring_event
    52         wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    53         wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    54 
    55         if ( wp_next_scheduled( 'activecampaign_for_woocommerce_cart_updated_recurring_event' ) ) {
    56             $this->logger->info( 'Clearing scheduled events...' );
    57 
    58             wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    59 
    60             if ( function_exists( 'wp_get_scheduled_event' ) ) {
    61                 $this->logger->info(
    62                     'Verify that the scheduled event was removed...',
    63                     array(
    64                         'activecampaign_for_woocommerce_cart_updated_recurring_event' => wp_get_scheduled_event( 'activecampaign_for_woocommerce_cart_updated_recurring_event' ),
    65                     )
    66                 );
    67             }
    68         } else {
    69             $this->logger->info( 'Abandoned cart event not scheduled. Nothing to deactivate.' );
    70         }
    71 
    72         // Clear activecampaign_for_woocommerce_run_order_sync
    73         if ( wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME ) ) {
    74             $this->logger->info( 'Clearing scheduled events...' );
    75 
    76             wp_clear_scheduled_hook( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
    77 
    78             if ( function_exists( 'wp_get_scheduled_event' ) ) {
    79                 $this->logger->info(
    80                     'Verify that the scheduled event was removed...',
    81                     array(
    82                         'activecampaign_for_woocommerce_run_order_sync_event' => wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME ),
    83                     )
    84                 );
    85             }
    86         } else {
    87             $this->logger->info( 'Order sync event not scheduled. Nothing to deactivate.' );
    88         }
    89     }
    9047}
  • activecampaign-for-woocommerce/trunk/includes/class-activecampaign-for-woocommerce-plugin-upgrade.php

    r3232769 r3251904  
    350350            wp_clear_scheduled_hook( 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    351351            // erase and reconfigure to use a faster time sequence.
    352             wp_schedule_event( time() + 10, 'every_minute', 'activecampaign_for_woocommerce_cart_updated_recurring_event' );
    353352        } catch ( Throwable $t ) {
    354353            $this->logger->error(
  • activecampaign-for-woocommerce/trunk/includes/config/activecampaign-for-woocommerce-global-constants.php

    r3242090 r3251904  
    2626 */
    2727if ( ! defined( 'ACTIVECAMPAIGN_FOR_WOOCOMMERCE_VERSION' ) ) {
    28     define( 'ACTIVECAMPAIGN_FOR_WOOCOMMERCE_VERSION', '2.8.7' );
     28    define( 'ACTIVECAMPAIGN_FOR_WOOCOMMERCE_VERSION', '2.9.0' );
    2929}
    3030
  • activecampaign-for-woocommerce/trunk/includes/orders/class-activecampaign-for-woocommerce-new-order-created-event.php

    r3239596 r3251904  
    1616use Activecampaign_For_Woocommerce_Customer_Utilities as Customer_Utilities;
    1717use Activecampaign_For_Woocommerce_Synced_Status_Interface as Synced_Status;
    18 
     18use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1919/**
    2020 * The Order_Finished Event Class.
     
    504504        try {
    505505            // wp_clear_scheduled_hook('activecampaign_for_woocommerce_cart_updated_recurring_event');
    506             if ( ! wp_next_scheduled( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME ) ) {
    507                 wp_schedule_event( time() + 10, 'ten_minute', ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME );
     506            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::RECURRING_ORDER_SYNC ) ) {
     507                AC_Scheduler::schedule_ac_event( AC_Scheduler::RECURRING_ORDER_SYNC, array(), true, false );
    508508            } elseif ( function_exists( 'wp_get_scheduled_event' ) ) {
    509509                $logger->debug_excess(
     
    511511                    array(
    512512                        'time_now' => time(),
    513                         'myevent'  => wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME ),
     513                        'myevent'  => AC_Scheduler::get_schedule( AC_Scheduler::RECURRING_ORDER_SYNC ),
    514514                    )
    515515                );
     
    533533    private function schedule_sync_job( $order_id ) {
    534534        try {
    535             if ( ! wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME, array( 'wc_order_id' => $order_id, 'event' => 'onetime' ) ) ) {
    536                 wp_schedule_single_event(
    537                     time() + 40,
    538                     'activecampaign_for_woocommerce_admin_sync_single_order_active',
     535            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::SYNC_ONE_ORDER_ACTIVE, array( 'wc_order_id' => $order_id, 'event' => 'onetime' ) ) ) {
     536                AC_Scheduler::schedule_ac_event(
     537                    AC_Scheduler::SYNC_ONE_ORDER_ACTIVE,
    539538                    array(
    540539                        'wc_order_id' => $order_id,
    541540                        'event'       => 'onetime',
    542541                    ),
    543                     true
     542                    false,
     543                    false
    544544                );
    545545            }
     
    551551                    'current_time'        => time(),
    552552                    'scheduled_time'      => time() + 40,
    553                     'schedule validation' => wp_get_scheduled_event( 'activecampaign_for_woocommerce_admin_sync_single_order_active', array( 'wc_order_id' => $order_id, 'event' => 'onetime' ) ),
     553                    'schedule validation' => AC_Scheduler::get_schedule( AC_Scheduler::SYNC_ONE_ORDER_ACTIVE, array( 'wc_order_id' => $order_id, 'event' => 'onetime' ) ),
    554554                )
    555555            );
  • activecampaign-for-woocommerce/trunk/includes/orders/class-activecampaign-for-woocommerce-new-order-sync-job.php

    r3232769 r3251904  
    152152                    'message'     => $t->getMessage(),
    153153                    'stack_trace' => $t->getTrace(),
     154                    'ac_code'     => 'NOSJ_154',
    154155                )
    155156            );
     
    277278                    'message'     => $t->getMessage(),
    278279                    'stack_trace' => $t->getTrace(),
     280                    'ac_code'     => 'NOSJ_280',
    279281                )
    280282            );
     
    603605            } catch ( Throwable $t ) {
    604606                $this->logger->warning(
    605                     'customerid not set or threw an error',
     607                    'New order sync on customerid not set or threw an error',
    606608                    array(
    607609                        'unsynced_order' => $unsynced_order,
     
    674676            if ( $wpdb->last_error ) {
    675677                $this->logger->error(
    676                     'Abandonement sync: There was an error updating an abandoned cart record as synced.',
     678                    'There was an error checking if this order record synced.',
    677679                    array(
    678680                        'wpdb_last_error' => $wpdb->last_error,
     681                        'ac_code'         => 'NOSJ_681',
    679682                    )
    680683                );
     
    793796            if ( $wpdb->last_error ) {
    794797                $this->logger->error(
    795                     'Abandonment sync: There was an error getting results for abandoned cart records.',
     798                    'There was an error getting results for unsynced records.',
    796799                    array(
    797800                        'wpdb_last_error' => $wpdb->last_error,
     801                        'ac_code'         => 'NOSJ_801',
    798802                    )
    799803                );
     
    811815                    'message' => $t->getMessage(),
    812816                    'trace'   => $this->logger->clean_trace( $t->getTrace() ),
     817                    'ac_code' => 'NOSJ_813',
    813818                )
    814819            );
  • activecampaign-for-woocommerce/trunk/includes/orders/class-activecampaign-for-woocommerce-order-action-events.php

    r3232769 r3251904  
    1313use Activecampaign_For_Woocommerce_Ecom_Order_Repository as Order_Repository;
    1414use Activecampaign_For_Woocommerce_Api_Client as Api_Client;
    15 
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1616/**
    1717 * The Order_Finished Event Class.
     
    4646
    4747            if ( isset( $order_id ) && null !== $order_id && ! empty( $order_id ) ) {
    48                 if ( ! wp_get_scheduled_event( 'activecampaign_for_woocommerce_ready_new_order', array( 'order_id' => $order_id ) ) ) {
    49                     wp_schedule_single_event(
    50                         time() + 30,
    51                         'activecampaign_for_woocommerce_ready_new_order',
    52                         array( 'order_id' => $order_id )
    53                     );
     48                $schedule_array = array( 'order_id' => $order_id );
     49
     50                if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::SYNC_ONE_NEW_ORDER, $schedule_array ) ) {
     51                    AC_Scheduler::schedule_ac_event( AC_Scheduler::SYNC_ONE_NEW_ORDER, $schedule_array, false, false );
    5452                }
    5553
     
    110108            if ( self::validate_object( $wc_order, 'get_data' ) && $this->check_update_validity( $wc_order ) ) {
    111109                set_transient( 'acforwc_order_updated_hook', wp_date( DATE_ATOM ), 604800 );
    112 
    113                 if ( ! wp_get_scheduled_event(
    114                     'activecampaign_for_woocommerce_admin_sync_single_order_active',
    115                     array(
    116                         'wc_order_id' => $order_id,
    117                         'status'      => $wc_order->get_status(),
    118                     )
    119                 ) &&
    120                     ! wp_get_scheduled_event(
    121                         'activecampaign_for_woocommerce_admin_sync_single_order_status',
    122                         array(
    123                             'wc_order_id' => $order_id,
    124                             'status'      => $wc_order->get_status(),
    125                         )
    126                     ) ) {
    127                     wp_schedule_single_event(
    128                         time() + 10,
    129                         'activecampaign_for_woocommerce_admin_sync_single_order_status',
    130                         array(
    131                             'wc_order_id' => $order_id,
    132                             'status'      => $wc_order->get_status(),
    133                         )
    134                     );
     110                $event_array = array(
     111                    'wc_order_id' => $order_id,
     112                    'status'      => $wc_order->get_status(),
     113                );
     114
     115                if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::SYNC_ONE_ORDER_ACTIVE, $event_array )
     116                    && ! AC_Scheduler::is_scheduled( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $event_array )
     117                ) {
     118                    // Schedule one time event
     119                    AC_Scheduler::schedule_ac_event( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $event_array, false, false );
    135120                }
    136121            } else {
     
    191176            if ( self::validate_object( $wc_order, 'get_data' ) ) {
    192177                set_transient( 'acforwc_order_updated_hook', wp_date( DATE_ATOM ), 604800 );
    193 
    194                 if ( ! wp_get_scheduled_event(
    195                     'activecampaign_for_woocommerce_admin_sync_single_order_status',
    196                     array(
    197                         'wc_order_id' => $order_id,
    198                         'status'      => $to_status,
    199                     )
    200                 ) ) {
    201                     wp_schedule_single_event(
    202                         time() + 10,
    203                         'activecampaign_for_woocommerce_admin_sync_single_order_status',
    204                         array(
    205                             'wc_order_id' => $order_id,
    206                             'status'      => $to_status,
    207                         )
    208                     );
     178                $event_array = array(
     179                    'wc_order_id' => $order_id,
     180                    'status'      => $to_status,
     181                );
     182                if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $event_array ) ) {
     183                    AC_Scheduler::schedule_ac_event( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $event_array, false, false );
    209184                }
    210185            }
     
    238213            }
    239214
    240             if ( ! wp_get_scheduled_event(
    241                 'activecampaign_for_woocommerce_admin_sync_single_order_status',
    242                 array(
    243                     'wc_order_id' => $order_id,
    244                     'event_type'  => 'status_' . $new_status,
    245                 )
    246             ) ) {
    247                 wp_schedule_single_event(
    248                     time() + 10,
    249                     'activecampaign_for_woocommerce_admin_sync_single_order_status',
    250                     array(
    251                         'wc_order_id' => $order_id,
    252                         'status'      => $new_status,
    253                     )
     215            $schedule_array = array(
     216                'wc_order_id' => $order_id,
     217                'status'      => $new_status,
     218            );
     219
     220            if ( ! AC_Scheduler::is_scheduled( AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER, $schedule_array ) ) {
     221                AC_Scheduler::schedule_ac_event(
     222                    AC_Scheduler::ADMIN_SYNC_SINGLE_ORDER,
     223                    $schedule_array,
     224                    false,
     225                    false
    254226                );
    255227            }
  • activecampaign-for-woocommerce/trunk/includes/orders/historical/class-activecampaign-for-woocommerce-historical-sync-contacts.php

    r3220303 r3251904  
    1717use Activecampaign_For_Woocommerce_AC_Contact_Batch as AC_Contact_Batch;
    1818use Activecampaign_For_Woocommerce_AC_Contact_Batch_Repository as AC_Contact_Batch_Repository;
     19use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Scheduler;
    1920
    2021/**
     
    194195
    195196    private function schedule_next( $start ) {
    196         wp_schedule_single_event(
    197             time() + 50,
    198             'activecampaign_for_woocommerce_run_historical_sync_contacts',
    199             array( 'start' => $start )
    200         );
     197        AC_Scheduler::schedule_ac_event( AC_Scheduler::HISTORICAL_SYNC_CONTACTS, array( 'start' => $start ), false, false );
    201198    }
    202199
  • activecampaign-for-woocommerce/trunk/includes/orders/trait-activecampaign-for-woocommerce-order-data-gathering.php

    r3220303 r3251904  
    286286                    'coupon'  => $coupon,
    287287                    'trace'   => $logger->clean_trace( $t->getTrace() ),
     288                    'ac_code' => 'ODG_288',
    288289                )
    289290            );
     
    382383            if ( $wpdb->last_error ) {
    383384                $logger->error(
    384                     'Abandonment sync: There was an error getting results for abandoned cart records.',
     385                    'There was an error getting external checkout ID for record.',
    385386                    array(
    386387                        'wpdb_last_error' => $wpdb->last_error,
     388                        'order_id'        => $order_id,
     389                        'ac_code'         => 'ODG_388',
    387390                    )
    388391                );
     
    395398        } catch ( Throwable $t ) {
    396399            $logger->error(
    397                 'Abandonment Sync: There was an error with preparing or getting abandoned cart results.',
     400                'There was an error getting external checkout ID for record.',
    398401                array(
    399402                    'message' => $t->getMessage(),
    400403                    'trace'   => $logger->clean_trace( $t->getTrace() ),
     404                    'ac_code' => 'ODG_402',
    401405                )
    402406            );
     
    431435            if ( $wpdb->last_error ) {
    432436                $logger->error(
    433                     'Abandonment sync: There was an error getting results for abandoned cart records.',
     437                    'There was an error getting AC order id from the order record',
    434438                    array(
    435439                        'wpdb_last_error' => $wpdb->last_error,
     440                        'order_id'        => $order_id,
     441                        'ac_code'         => 'ODG_438',
    436442                    )
    437443                );
     
    444450        } catch ( Throwable $t ) {
    445451            $logger->error(
    446                 'Abandonment Sync: There was an error with preparing or getting abandoned cart results.',
     452                'There was a fatal error retrieving AC order id from order record.',
    447453                array(
    448454                    'message' => $t->getMessage(),
    449455                    'trace'   => $logger->clean_trace( $t->getTrace() ),
     456                    'ac_code' => 'ODG_453',
    450457                )
    451458            );
  • activecampaign-for-woocommerce/trunk/includes/subscriptions/class-activecampaign-for-woocommerce-subscription-events.php

    r3232769 r3251904  
    1313use Activecampaign_For_Woocommerce_Logger as Logger;
    1414use Activecampaign_For_Woocommerce_Synced_Status_Interface as Synced_Status;
    15 
     15use Activecampaign_For_Woocommerce_Scheduler_Handler as AC_Schedule;
    1616/**
    1717 * The Subscription Event Class.
     
    114114
    115115            if ( isset( $subscription_id ) && null !== $subscription_id && ! empty( $subscription_id ) ) {
    116                 if ( ! wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ) ) ) {
    117                     wp_schedule_single_event(
    118                         time() + 30,
    119                         'activecampaign_for_woocommerce_update_subscription',
    120                         array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ),
    121                         true
    122                     );
    123                 }
     116                AC_Schedule::schedule_ac_event( AC_Schedule::SYNC_ONE_SUBSCRIPTION_ORDER, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ), false, false );
    124117            }
    125118        } catch ( Throwable $t ) {
     
    159152            $this->update_status( $wc_subscription, 0 );
    160153            if ( isset( $subscription_id ) && null !== $subscription_id && ! empty( $subscription_id ) ) {
    161                 if ( ! wp_get_scheduled_event( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_RUN_NEW_ORDER_SYNC_NAME, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ) ) ) {
    162                     wp_schedule_single_event(
    163                         time() + 30,
    164                         'activecampaign_for_woocommerce_update_subscription',
    165                         array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ),
    166                         true
    167                     );
     154
     155                if ( ! AC_Schedule::is_scheduled( AC_Schedule::SYNC_UPDATE_ONE_SUBSCRIPTION, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ) ) ) {
     156                    AC_Schedule::schedule_ac_event( AC_Schedule::SYNC_UPDATE_ONE_SUBSCRIPTION, array( 'wc_order_id' => $subscription_id, 'event' => 'onetime' ), false, false );
    168157                }
    169158            }
  • activecampaign-for-woocommerce/trunk/includes/subscriptions/trait-activecampaign-for-woocommerce-subscription-gathering.php

    r3220303 r3251904  
    2828    use Activecampaign_For_Woocommerce_Order_Line_Item_Gathering;
    2929
     30    /**
     31     * The connection id.
     32     *
     33     * @var string
     34     */
     35    private $connection_id;
     36
    3037    private function init() {
    3138        $admin_storage = get_option( ACTIVECAMPAIGN_FOR_WOOCOMMERCE_DB_CONNECTION_STORAGE_NAME );
Note: See TracChangeset for help on using the changeset viewer.