/** * 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; } }
/** * 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. } } } }