public function save()
 {
     // 0. WE CHECK WHETHER THE EXPERIMENT IS COMPLETELY NEW OR NOT
     // -------------------------------------------------------------------------
     $is_new = $this->get_id() < 0;
     // 1. SAVE THE EXPERIMENT AND ITS GOALS
     // -------------------------------------------------------------------------
     $exp_id = parent::save();
     // 2. UPDATE THE ALTERNATIVES
     // -------------------------------------------------------------------------
     // 2.0. FIRST OF ALL, WE CREATE A FAKE ORIGINAL FOR NEW EXPERIMENTS
     /** @var NelioABAlternative $original */
     $original = $this->get_original();
     if ($is_new && $original->get_id() < 0) {
         $body = array('name' => $original->get_name(), 'content' => '', 'kind' => NelioABExperiment::get_textual_type());
         try {
             /** @var int $result */
             $result = NelioABBackend::remote_post(sprintf(NELIOAB_BACKEND_URL . '/exp/global/%s/alternative', $exp_id), $body);
             $original->set_id($result);
         } catch (Exception $e) {
         }
     }
     // 2.1. UPDATE CHANGES ON ALREADY EXISTING APPSPOT ALTERNATIVES
     foreach ($this->get_appspot_alternatives() as $alt) {
         /** @var NelioABAlternative $alt */
         if ($alt->was_removed() || !$alt->is_dirty()) {
             continue;
         }
         $body = array('name' => $alt->get_name());
         NelioABBackend::remote_post(sprintf(NELIOAB_BACKEND_URL . '/alternative/%s/update', $alt->get_id()), $body);
     }
     // 2.2. REMOVE FROM APPSPOT THE REMOVED ALTERNATIVES
     foreach ($this->get_appspot_alternatives() as $alt) {
         /** @var NelioABAlternative $alt */
         if (!$alt->was_removed()) {
             continue;
         }
         $url = sprintf(NELIOAB_BACKEND_URL . '/alternative/%s/delete', $alt->get_id());
         try {
             NelioABBackend::remote_post($url);
         } catch (Exception $e) {
         }
     }
     // 2.3. CREATE LOCAL ALTERNATIVES IN APPSPOT
     $this->new_ids = array();
     foreach ($this->get_local_alternatives() as $alt) {
         /** @var NelioABAlternative $alt */
         if ($alt->was_removed()) {
             continue;
         }
         $body = array('name' => $alt->get_name(), 'content' => '', 'kind' => NelioABExperiment::get_textual_type());
         try {
             /** @var object|array $result */
             $result = NelioABBackend::remote_post(sprintf(NELIOAB_BACKEND_URL . '/exp/global/%s/alternative', $exp_id), $body);
             $result = json_decode($result['body']);
             $this->new_ids[$alt->get_id()] = $result->key->id;
         } catch (Exception $e) {
         }
     }
     require_once NELIOAB_MODELS_DIR . '/experiments-manager.php';
     NelioABExperimentsManager::update_experiment($this);
 }
 public function save()
 {
     // 1. UPDATE OR CREATE THE EXPERIMENT
     // -------------------------------------------------------------------------
     if ($this->get_id() < 0) {
         $url = sprintf(NELIOAB_BACKEND_URL . '/site/%s/exp/post', NelioABAccountSettings::get_site_id());
     } else {
         $url = sprintf(NELIOAB_BACKEND_URL . '/exp/post/%s/update', $this->get_id());
     }
     if ($this->get_status() != NelioABExperiment::STATUS_PAUSED && $this->get_status() != NelioABExperiment::STATUS_RUNNING && $this->get_status() != NelioABExperiment::STATUS_FINISHED && $this->get_status() != NelioABExperiment::STATUS_TRASH) {
         $this->set_status($this->determine_proper_status());
     }
     $body = array('name' => $this->get_name(), 'description' => $this->get_description(), 'originalPost' => $this->get_originals_id(), 'postType' => $this->get_post_type(), 'status' => $this->get_status(), 'kind' => $this->get_textual_type(), 'showHeatmap' => $this->are_heatmaps_tracked(), 'finalizationMode' => $this->get_finalization_mode(), 'finalizationModeValue' => $this->get_finalization_value());
     $result = NelioABBackend::remote_post($url, $body);
     $exp_id = $this->get_id();
     if ($exp_id < 0) {
         if (is_wp_error($result)) {
             return;
         }
         $json = json_decode($result['body']);
         $exp_id = $json->key->id;
         $this->id = $exp_id;
     }
     // 1.1 SAVE GOALS
     // -------------------------------------------------------------------------
     $this->make_goals_persistent();
     // 2. UPDATE THE ALTERNATIVES
     // -------------------------------------------------------------------------
     // 2.1. UPDATE CHANGES ON ALREADY EXISTING APPSPOT ALTERNATIVES
     foreach ($this->get_appspot_alternatives() as $alt) {
         /** @var NelioABAlternative $alt */
         if ($alt->was_removed() || !$alt->is_dirty()) {
             continue;
         }
         $body = array('name' => $alt->get_name(), 'value' => $alt->get_value());
         NelioABBackend::remote_post(sprintf(NELIOAB_BACKEND_URL . '/alternative/%s/update', $alt->get_id()), $body);
     }
     // 2.2. REMOVE FROM APPSPOT THE REMOVED ALTERNATIVES
     foreach ($this->get_appspot_alternatives() as $alt) {
         if (!$alt->was_removed()) {
             continue;
         }
         $url = sprintf(NELIOAB_BACKEND_URL . '/alternative/%s/delete', $alt->get_id());
         NelioABBackend::remote_post($url);
     }
     // 2.3. CREATE LOCAL ALTERNATIVES IN APPSPOT
     /** @var array $ori_post */
     $ori_post = get_post($this->get_originals_id(), ARRAY_A);
     foreach ($this->get_local_alternatives() as $alt) {
         if ($alt->was_removed()) {
             continue;
         }
         if ($this->get_type() != NelioABExperiment::HEADLINE_ALT_EXP) {
             if ($alt->is_based_on_another_element()) {
                 $new_id = $this->create_alternative_copying_content($alt->get_name(), $alt->get_base_element(), $ori_post);
                 if ($new_id) {
                     $alt->set_value($new_id);
                 } else {
                     continue;
                 }
             } else {
                 $new_id = $this->create_empty_alternative($alt->get_name(), $this->get_type(), $this->get_post_type());
                 if ($new_id) {
                     $alt->set_value($new_id);
                 } else {
                     continue;
                 }
             }
         }
         $body = array('name' => $alt->get_name(), 'value' => $alt->get_value(), 'kind' => NelioABExperiment::get_textual_type());
         try {
             /** @var int $result */
             $result = NelioABBackend::remote_post(sprintf(NELIOAB_BACKEND_URL . '/exp/post/%s/alternative', $exp_id), $body);
             $alt->set_id($result);
         } catch (Exception $e) {
             // If I could not add an alternative... remove the associated page
             wp_delete_post($alt->get_value());
         }
     }
     // 2.3 REMOVE THE PAGES THAT BELONGED TO AN ALTERNATIVE THAT HAS BEEN DELETED
     $all_alternatives = array_merge($this->get_appspot_alternatives(), $this->get_local_alternatives());
     foreach ($all_alternatives as $alt) {
         if ($alt->was_removed()) {
             // Delete permanently (skipping Trash)
             if ($alt->get_value()) {
                 wp_delete_post($alt->get_value(), true);
             }
         }
     }
     // 2.4 SET META "_is_nelioab_alternative" WITH THE ID OF THE EXPERIMENT
     foreach ($this->get_alternatives() as $alt) {
         $pid = $alt->get_value();
         if (is_int($pid) && $pid > 0) {
             $value = $this->get_id() . ',' . $this->get_status();
             update_post_meta($pid, "_is_nelioab_alternative", $value);
         }
     }
     require_once NELIOAB_MODELS_DIR . '/experiments-manager.php';
     NelioABExperimentsManager::update_experiment($this);
 }