/**
  * This function checks whether there are any Theme experiments running or
  * not. If there are, it will add some hooks to WordPress, just to make sure
  * that the framework used to create the active (original or alternative)
  * theme is recovering the appropriate information.
  */
 public static function make_compat()
 {
     // Let's check if there's a theme experiment running
     require_once NELIOAB_MODELS_DIR . '/experiments-manager.php';
     $running_exps = NelioABExperimentsManager::get_running_experiments_from_cache();
     $found = false;
     foreach ($running_exps as $exp) {
         /** @var NelioABExperiment $exp */
         if ($exp->get_type() == NelioABExperiment::THEME_ALT_EXP) {
             $found = true;
         }
     }
     if (!$found) {
         return;
     }
     // If there's some exp running, let's make sure we're compatible with the framework
     // used to create it.
     add_filter('option_optionsframework', array('NelioABThemeCompatibilityLayer', 'fix_optionsframework_compatibility'));
 }
 public function start()
 {
     // If the experiment is already running, quit
     if ($this->get_status() == NelioABExperiment::STATUS_RUNNING) {
         return;
     }
     // Checking whether the experiment can be started or not...
     require_once NELIOAB_UTILS_DIR . '/backend.php';
     require_once NELIOAB_MODELS_DIR . '/experiments-manager.php';
     $running_exps = NelioABExperimentsManager::get_running_experiments_from_cache();
     foreach ($running_exps as $running_exp) {
         /** @var NelioABExperiment $running_exp */
         if ($running_exp->get_type() != NelioABExperiment::PAGE_ALT_EXP && $running_exp->get_type() != NelioABExperiment::POST_ALT_EXP && $running_exp->get_type() != NelioABExperiment::CPT_ALT_EXP && $running_exp->get_type() != NelioABExperiment::HEADLINE_ALT_EXP) {
             continue;
         }
         if ($running_exp->get_originals_id() == $this->get_originals_id()) {
             if ($running_exp->get_type() == NelioABExperiment::PAGE_ALT_EXP) {
                 $err_str = sprintf(__('The experiment cannot be started, because there is another experiment running that is testing the same page. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
             } else {
                 if ($running_exp->get_type() == NelioABExperiment::POST_ALT_EXP) {
                     $err_str = sprintf(__('The experiment cannot be started, because there is another experiment running that is testing the same post. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                 } else {
                     if ($running_exp->get_type() == NelioABExperiment::CPT_ALT_EXP) {
                         $err_str = sprintf(__('The experiment cannot be started, because there is another experiment running that is testing the same custom post. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                     } else {
                         $err_str = sprintf(__('The experiment cannot be started, because there is another experiment that is testing the title of the same page. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                     }
                 }
             }
             throw new Exception($err_str, NelioABErrCodes::EXPERIMENT_CANNOT_BE_STARTED);
         }
     }
     // If everything is OK, we can start it!
     // (keep in mind that, if it is a title experiment, we'll create the goal in AE
     // And there we go!
     $ori_post = get_post($this->get_originals_id());
     if ($ori_post && $this->get_type() != NelioABExperiment::HEADLINE_ALT_EXP) {
         foreach ($this->get_alternatives() as $alt) {
             /** @var NelioABAlternative $alt */
             $alt_post = get_post($alt->get_value());
             if ($alt_post) {
                 $alt_post->comment_status = $ori_post->comment_status;
                 wp_update_post($alt_post);
             }
         }
     }
     $url = sprintf(NELIOAB_BACKEND_URL . '/exp/post/%s/start', $this->get_id());
     try {
         NelioABBackend::remote_post($url);
         $this->set_status(NelioABExperiment::STATUS_RUNNING);
     } catch (Exception $e) {
         throw $e;
     }
 }
 public function start()
 {
     // If the experiment is already running, quit
     if ($this->get_status() == NelioABExperiment::STATUS_RUNNING) {
         return;
     }
     // Checking whether the experiment can be started or not...
     require_once NELIOAB_UTILS_DIR . '/backend.php';
     require_once NELIOAB_MODELS_DIR . '/experiments-manager.php';
     $running_exps = NelioABExperimentsManager::get_running_experiments_from_cache();
     $this_exp_origins = $this->get_origins();
     array_push($this_exp_origins, -1);
     foreach ($running_exps as $running_exp) {
         /** @var NelioABExperiment $running_exp */
         switch ($running_exp->get_type()) {
             case NelioABExperiment::THEME_ALT_EXP:
                 $err_str = sprintf(__('The experiment cannot be started, because there is a theme experiment running. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                 throw new Exception($err_str, NelioABErrCodes::EXPERIMENT_CANNOT_BE_STARTED);
             case NelioABExperiment::CSS_ALT_EXP:
                 /** @var NelioABGlobalAlternativeExperiment $running_exp */
                 foreach ($this_exp_origins as $origin_id) {
                     if (in_array($origin_id, $running_exp->get_origins())) {
                         $err_str = sprintf(__('The experiment cannot be started, because there is a CSS experiment running. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                         throw new Exception($err_str, NelioABErrCodes::EXPERIMENT_CANNOT_BE_STARTED);
                     }
                 }
                 break;
             case NelioABExperiment::WIDGET_ALT_EXP:
                 /** @var NelioABGlobalAlternativeExperiment $running_exp */
                 foreach ($this_exp_origins as $origin_id) {
                     if (in_array($origin_id, $running_exp->get_origins())) {
                         $err_str = sprintf(__('The experiment cannot be started, because there is a Widget experiment running. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                         throw new Exception($err_str, NelioABErrCodes::EXPERIMENT_CANNOT_BE_STARTED);
                     }
                 }
                 break;
             case NelioABExperiment::MENU_ALT_EXP:
                 /** @var NelioABGlobalAlternativeExperiment $running_exp */
                 foreach ($this_exp_origins as $origin_id) {
                     if (in_array($origin_id, $running_exp->get_origins())) {
                         $err_str = sprintf(__('The experiment cannot be started, because there is a Menu experiment running. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                         throw new Exception($err_str, NelioABErrCodes::EXPERIMENT_CANNOT_BE_STARTED);
                     }
                 }
                 break;
             case NelioABExperiment::HEATMAP_EXP:
                 if ($this->get_type() != NelioABExperiment::WIDGET_ALT_EXP) {
                     $err_str = __('The experiment cannot be started, because there is one (or more) heatmap experiments running. Please make sure to stop any running heatmap experiment before starting the new one.', 'nelioab');
                     throw new Exception($err_str, NelioABErrCodes::EXPERIMENT_CANNOT_BE_STARTED);
                 }
                 break;
         }
     }
     // If everything is OK, we can start it!
     $url = sprintf(NELIOAB_BACKEND_URL . '/exp/global/%s/start', $this->get_id());
     try {
         NelioABBackend::remote_post($url);
         $this->set_status(NelioABExperiment::STATUS_RUNNING);
     } catch (Exception $e) {
         throw $e;
     }
 }
Beispiel #4
0
 /**
  * Initializes the properties of this class.
  *
  * This function iterates over all the experiment and assigned alternative
  * in which this visitor participates and initializes the relevant
  * properties of the class. In particular, it sets the properties
  * `$css_info`, `$menu_info,` `$theme_info`, and `$widget_info` for global
  * experiments and the arrays `$exps` and `$headline_exps`.
  *
  *
  * @param array $env a hashmap of experiments (key) and the alternatives (value) this visitor is supposed to see.
  *
  * @since 4.0.0
  */
 private static function prepareEnvironment($env)
 {
     require_once NELIOAB_MODELS_DIR . '/experiments-manager.php';
     $running_exps = NelioABExperimentsManager::get_running_experiments_from_cache();
     self::$ids = array();
     self::$css_info = false;
     self::$menu_info = false;
     self::$theme_info = false;
     self::$widget_info = false;
     self::$exps = array();
     self::$headline_exps = array();
     self::$wc_product_summary_exps = array();
     foreach ($env as $exp_id => $alt) {
         /** @var NelioABExperiment $aux */
         $exp = NULL;
         foreach ($running_exps as $aux) {
             if ($aux->get_id() == $exp_id) {
                 $exp = $aux;
             }
         }
         if ($exp) {
             switch ($exp->get_type()) {
                 case NelioABExperiment::PAGE_ALT_EXP:
                 case NelioABExperiment::POST_ALT_EXP:
                 case NelioABExperiment::CPT_ALT_EXP:
                     /** @var NelioABPostAlternativeExperiment $exp */
                     self::add_regular_exp($exp, $alt);
                     array_push(self::$ids, $exp->get_id());
                     break;
                 case NelioABExperiment::HEADLINE_ALT_EXP:
                     /** @var NelioABHeadlineAlternativeExperiment $exp */
                     self::add_headline_exp($exp, $alt);
                     array_push(self::$ids, $exp->get_id());
                     break;
                 case NelioABExperiment::WC_PRODUCT_SUMMARY_ALT_EXP:
                     /** @var NelioABHeadlineAlternativeExperiment $exp */
                     self::add_wc_product_summary_exp($exp, $alt);
                     array_push(self::$ids, $exp->get_id());
                     break;
                 case NelioABExperiment::CSS_ALT_EXP:
                 case NelioABExperiment::MENU_ALT_EXP:
                 case NelioABExperiment::THEME_ALT_EXP:
                 case NelioABExperiment::WIDGET_ALT_EXP:
                     /** @var NelioABGlobalAlternativeExperiment $exp */
                     self::add_global_exp($exp, $alt);
                     array_push(self::$ids, $exp->get_id());
                     break;
             }
         }
     }
 }
 public function start()
 {
     // Checking whether the experiment can be started or not...
     require_once NELIOAB_UTILS_DIR . '/backend.php';
     require_once NELIOAB_MODELS_DIR . '/experiments-manager.php';
     $running_exps = NelioABExperimentsManager::get_running_experiments_from_cache();
     foreach ($running_exps as $running_exp) {
         /** @var NelioABGlobalAlternativeExperiment $running_exp */
         // $running_exp can actually be anything, but we're focusing
         // on Global Alternative Experiments only.
         switch ($running_exp->get_type()) {
             case NelioABExperiment::THEME_ALT_EXP:
                 $err_str = sprintf(__('The experiment cannot be started, because there is a theme experiment running. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                 throw new Exception($err_str, NelioABErrCodes::EXPERIMENT_CANNOT_BE_STARTED);
             case NelioABExperiment::CSS_ALT_EXP:
                 if (in_array($this->get_post_id(), $running_exp->get_origins()) || in_array(-1, $running_exp->get_origins())) {
                     $err_str = sprintf(__('The experiment cannot be started, because there is a running CSS experiment that may be changing the appearence of the tested page. Please, stop the experiment named «%s» before starting the new one.', 'nelioab'), $running_exp->get_name());
                     throw new Exception($err_str, NelioABErrCodes::EXPERIMENT_CANNOT_BE_STARTED);
                 }
         }
     }
     // If everything is OK, we can start it!
     // If the experiment is already running, quit
     if ($this->get_status() == NelioABExperiment::STATUS_RUNNING) {
         return;
     }
     require_once NELIOAB_UTILS_DIR . '/backend.php';
     $url = sprintf(NELIOAB_BACKEND_URL . '/exp/hm/%s/start', $this->get_id());
     NelioABBackend::remote_post($url);
     $this->set_status(NelioABExperiment::STATUS_RUNNING);
 }
 /**
  * PHPDOC
  *
  * @param int $order_id PHPDOC
  *
  * @return void
  *
  * @since PHPDOC
  */
 public function sync_order_completed($order_id)
 {
     $order = wc_get_order($order_id);
     $items = $order->get_items();
     $user = get_post_meta($order_id, '_nelioab_userid', true);
     $env = get_post_meta($order_id, '_nelioab_form_env', true);
     if (!$user) {
         return;
     }
     require_once NELIOAB_MODELS_DIR . '/experiments-manager.php';
     $running_experiments = NelioABExperimentsManager::get_running_experiments_from_cache();
     // Let's start by selecting the relevant experiments.
     // A relevant experiment is a running experiment that was in the environment
     // that was active during the purchase AND that has at least one conversion
     // action in its goals that tracks an "Order Completed" event.
     $relevant_experiments = array();
     $relevant_conversion_actions = array();
     foreach ($env as $id => $alt) {
         foreach ($running_experiments as $exp) {
             if ($exp->get_id() != $id) {
                 continue;
             }
             foreach ($exp->get_goals() as $goal) {
                 if ($goal->get_kind() != NelioABGoal::ALTERNATIVE_EXPERIMENT_GOAL) {
                     continue;
                 }
                 foreach ($goal->get_actions() as $action) {
                     echo "Considering {$action->get_id()}... ";
                     if ($action->get_type() != NelioABAction::WC_ORDER_COMPLETED) {
                         echo "NO<br>";
                         continue;
                     }
                     echo "YES<br>";
                     // Once we've found a Order Complete conversion action, we save:
                     //  a) the experiment
                     //  b) the product controlled by that conversion action
                     if (!in_array($exp, $relevant_experiments)) {
                         array_push($relevant_experiments, $exp);
                     }
                     array_push($relevant_conversion_actions, $action);
                 }
             }
         }
     }
     // Now we need to see if products are being tested and, if they are,
     // the IDs of the concrete alternatives the visitor saw.
     $relevant_products = array();
     foreach ($relevant_experiments as $exp) {
         if ($exp->get_type() != NelioABExperiment::WC_PRODUCT_SUMMARY_ALT_EXP) {
             continue;
         }
         $alt_num = false;
         foreach ($env as $id => $alt) {
             if ($exp->get_id() == $id) {
                 $alt_num = $alt;
                 break;
             }
         }
         if ($alt_num !== false) {
             if (0 == $alt_num) {
                 // We use "-1" because it's the ID we use for the "original alternative" object
                 // (which doesn't exist in AE).
                 $alt = -1;
             } else {
                 $alts = $exp->get_alternatives();
                 if ($alt_num > count($alts)) {
                     continue;
                 }
                 $alt = $alts[$alt_num - 1];
                 $alt = $alt->get_id();
             }
             $relevant_products[$exp->get_originals_id()] = $alt;
             break;
         }
     }
     // Once we have the list of PRODUCT_ID => ACTUAL_PRODUCT_ID, we need to
     // include all the other relevant product IDs:
     foreach ($relevant_conversion_actions as $action) {
         $product_id = $action->get_product_id();
         if (!isset($relevant_products[$product_id])) {
             $relevant_products[$product_id] = $product_id;
         }
     }
     // Now we need to get information about the global experiments:
     $css_alt = false;
     $menu_alt = false;
     $theme_alt = false;
     $widget_alt = false;
     foreach ($relevant_experiments as $exp) {
         foreach ($env as $id => $alt_num) {
             if ($exp->get_id() != $id) {
                 continue;
             }
             $alt = false;
             switch ($exp->get_type()) {
                 case NelioABExperiment::CSS_ALT_EXP:
                 case NelioABExperiment::MENU_ALT_EXP:
                 case NelioABExperiment::THEME_ALT_EXP:
                 case NelioABExperiment::WIDGET_ALT_EXP:
                     if (0 == $alt_num) {
                         $alt = $exp->get_original();
                     } else {
                         $alts = $exp->get_alternatives();
                         if ($alt_num > count($alts)) {
                             continue;
                         }
                         $alt = $alts[$alt_num - 1];
                     }
                     $alt = $alt->get_id();
                     break;
             }
             if ($alt) {
                 switch ($exp->get_type()) {
                     case NelioABExperiment::CSS_ALT_EXP:
                         $css_alt = $alt;
                         break;
                     case NelioABExperiment::MENU_ALT_EXP:
                         $menu_alt = $alt;
                         break;
                     case NelioABExperiment::THEME_ALT_EXP:
                         $theme_alt = $alt;
                         break;
                     case NelioABExperiment::WIDGET_ALT_EXP:
                         $widget_alt = $alt;
                         break;
                 }
             }
         }
     }
     // Finally, we can create the result object
     $result = array('products' => array());
     foreach ($relevant_products as $product_id => $actual_product_id) {
         $product_found = false;
         foreach ($items as $item) {
             if (isset($item['product_id']) && $item['product_id'] == $product_id) {
                 $product_found = true;
                 break;
             }
         }
         if ($product_found) {
             array_push($result['products'], $product_id . ':' . $actual_product_id);
         }
     }
     if (count($result['products']) > 0) {
         $result['kind'] = 'OrderComplete';
         $result['products'] = implode(',', $result['products']);
         $result['user'] = $user;
         if ($css_alt) {
             $result['activeCSS'] = $css_alt;
         }
         if ($menu_alt) {
             $result['activeMenu'] = $menu_alt;
         }
         if ($theme_alt) {
             $result['activeTheme'] = $theme_alt;
         }
         if ($widget_alt) {
             $result['activeWidget'] = $widget_alt;
         }
         $url = sprintf(NELIOAB_BACKEND_URL . '/site/%s/productevent', NelioABAccountSettings::get_site_id());
         $data = NelioABBackend::build_json_object_with_credentials($result);
         $data['timeout'] = 50;
         for ($attemp = 0; $attemp < 5; ++$attemp) {
             try {
                 NelioABBackend::remote_post_raw($url, $data);
                 break;
             } catch (Exception $e) {
                 // If the form submission event could not be sent, it may be that's
                 // because there is no more quota available
                 if ($e->getCode() == NelioABErrCodes::NO_MORE_QUOTA) {
                     // If that was the case, simply leave
                     break;
                 }
                 // If there was another error... we just keep trying (attemp) up to 5
                 // times.
             }
         }
     }
 }