You are here

function acquia_lift_update_7200 in Acquia Lift Connector 7.2

Miscellaneous changes required for the new workflow, includes converting legacy campaigns to "personalizations".

File

./acquia_lift.install, line 629
Acquia Lift - Installation file.

Code

function acquia_lift_update_7200() {

  // The queue is now gone so delete the queue class variable.
  variable_del('queue_class_acquia_lift_sync');

  // Clear the ctools plugin "agent_type" cache for personalize, clear loaded
  // files cache, and rebuild the autoloader class definitions.
  cache_clear_all('plugins:personalize:agent_type', 'cache', TRUE);
  cache_clear_all('ctools_plugin_files:personalize:agent_type', 'cache', TRUE);
  registry_rebuild();

  // Convert simple A/B agents to regular Lift agents.
  db_update('personalize_agent')
    ->condition('plugin', 'acquia_lift_simple_ab')
    ->fields(array(
    'plugin' => 'acquia_lift',
  ))
    ->execute();

  // Get all old-style agents and convert them where possible.
  $result = db_query("SELECT a.machine_name, a.label, a.data, o.plugin, o.osid, o.decision_name, o.options, o.targeting FROM {personalize_agent} a INNER JOIN {personalize_option_sets} o ON o.agent = a.machine_name WHERE a.plugin = 'acquia_lift'");

  // First organize our results into arrays of agents with their option sets.
  $agents = array();
  foreach ($result as $row) {
    $options = unserialize($row->options);
    $agents[$row->machine_name][] = array(
      'agent_name' => $row->machine_name,
      'agent_label' => $row->label,
      'agent_data' => unserialize($row->data),
      'osid' => $row->osid,
      'decision_name' => empty($row->decision_name) ? 'osid-' . $row->osid : $row->decision_name,
      'option_count' => count($options),
      'options' => $options,
      'targeting' => unserialize($row->targeting),
    );
  }

  // If an agent has more than one option set or if its option set contains fixed
  // targeting rules, it cannot be converted and will be treated as a legacy agent.
  $legacy_agents = $convertibles = array();

  // If personalize module is not enabled all campaigns will be treated as legacy.
  $personalize_enabled = module_exists('personalize');
  foreach ($agents as $agent_name => $details) {
    $option_set = reset($details);
    if (!empty($option_set['targeting']) || !empty($option_set['agent_data']['visitor_context']) || !$personalize_enabled) {
      $legacy_agents[] = $agent_name;
      continue;
    }
    if (count($details) > 1) {

      // We can convert this if all option sets have the same decision name.
      $decision_name = '';
      $option_count = 0;
      $supported = TRUE;
      foreach ($details as $i => $option_set) {
        if ($i == 0) {
          $decision_name = $option_set['decision_name'];
          $option_count = $option_set['option_count'];
        }
        else {

          // If any of the option sets has a different decision name or option
          // count, then this agent cannot be converted.
          if ($option_set['decision_name'] != $decision_name || $option_set['option_count'] != $option_count) {
            $supported = FALSE;
          }
        }
      }
      if ($supported) {
        $convertibles[$agent_name] = $details;
      }
      else {
        $legacy_agents[] = $agent_name;
      }
    }
    else {
      $convertibles[$agent_name] = $details;
    }
  }

  // If personalize module is not enabled we just want to save the legacy agents
  // and be done.
  if (!$personalize_enabled && !empty($legacy_agents)) {
    drupal_set_message(t('Personalize module was disabled so existing campaigns could not be converted to the new style personalizations. They will be treated as legacy campaigns.'), 'warning');
    variable_set('acquia_lift_legacy_agents', $legacy_agents);
    return;
  }

  // Now convert anything that can be converted.
  foreach ($convertibles as $original_agent_name => $details) {

    // Create a new acquia_lift_target agent which will delegate to this one.
    $agent = new stdClass();
    $agent->label = 'Converted: ' . $details[0]['agent_label'];
    $agent->plugin = 'acquia_lift_target';
    $agent->data = $details[0]['agent_data'];

    // Preserve some data by keys, and discard others.
    $preserved_data_keys = array(
      'control_rate',
      'decision_style',
      'explore_rate',
      'cache_decisions',
    );
    foreach ($agent->data as $key => $data_entry) {
      if (in_array($key, $preserved_data_keys)) {
        continue;
      }
      unset($agent->data[$key]);
    }
    $agent->machine_name = personalize_generate_machine_name($original_agent_name . '-parent', 'personalize_agent_machine_name_exists');
    $nested_agent = personalize_agent_load($original_agent_name);
    try {
      $agent = personalize_agent_save($agent);

      // Set the status of our new agent to that of the original.
      $nested_agent_status = personalize_agent_get_status($original_agent_name);

      // Move goals over to the new agent.
      $goals = personalize_goal_load_by_conditions(array(
        'agent' => $original_agent_name,
      ));
      foreach ($goals as $goal) {
        db_update('personalize_campaign_goals')
          ->condition('id', $goal->id)
          ->fields(array(
          'agent' => $agent->machine_name,
        ))
          ->execute();
      }

      // Remove the "decisions" info from the data property of the original
      // agent as this no longer serves any function.
      unset($nested_agent->data['decisions']);
      personalize_agent_save($nested_agent);
      $nested_osid = NULL;

      // If there are mulitple option sets, they constitute one decision.
      foreach ($details as $i => $option_set_details) {
        $nested_os = personalize_option_set_load($option_set_details['osid']);
        if ($i == 0) {
          $nested_osid = $nested_os->osid;
        }
        $main_os = new stdClass();
        $main_os->agent = $agent->machine_name;
        $main_os->data = $nested_os->data;
        $main_os->label = $nested_os->label;
        $main_os->options = $nested_os->options;
        $main_os->plugin = $nested_os->plugin;
        $main_os->executor = $nested_os->executor;
        $main_os->winner = $nested_os->winner;
        $main_os->stateful = $nested_os->stateful;
        $main_os->preview_link = $nested_os->preview_link;
        $main_os->decision_name = $option_set_details['decision_name'];
        $main_os->targeting = array(
          ACQUIA_LIFT_TARGETING_EVERYONE_ELSE => array(
            'label' => t('Everyone'),
            'weight' => 1,
            'targeting_features' => array(),
            'targeting_rules' => array(),
            'targeting_strategy' => 'OR',
            'osid' => $nested_osid,
          ),
        );
        personalize_option_set_save($main_os);

        // Convert the first of the original option sets to a nested option set
        // and delete the others.
        if ($i == 0) {
          $nested_os->plugin = 'options';
          $nested_os->options = array();
          foreach ($option_set_details['options'] as $option) {
            $nested_os->options[] = array(
              'option_id' => $option['option_id'],
            );
          }
          personalize_option_set_save($nested_os);
        }
        else {
          personalize_option_set_delete($option_set_details['osid']);
        }
      }
      personalize_agent_set_status($agent->machine_name, $nested_agent_status);
      $start_date = personalize_agent_get_start_date($original_agent_name);
      personalize_agent_set_start_date($agent->machine_name, $start_date);
      $end_date = personalize_agent_get_stop_date($original_agent_name);
      personalize_agent_set_stop_date($agent->machine_name, $end_date);
      $agent->started = $nested_agent->started;
      personalize_agent_save($agent);
    } catch (PersonalizeException $e) {
      personalize_agent_delete($agent->machine_name);

      // Add this to the legacy agents, set a message to that effect and continue
      // to the next agent.
      $legacy_agents[] = $original_agent_name;
      drupal_set_message(t('There was a problem converting the campaign @agent to a new style campaign. It will be treated as a legacy agent.', array(
        '@agent' => $original_agent_name,
      )), 'error');
      continue;
    }
  }
  if (!empty($legacy_agents)) {
    drupal_set_message(t('The following campaigns could not be converted to new style personalizations and will be treated as legacy campaigns: ' . implode(', ', $legacy_agents)), 'warning');
    variable_set('acquia_lift_legacy_agents', $legacy_agents);
  }

  // Fix settings for personalized fields.
  $result = db_select('field_config', 'f')
    ->fields('f', array(
    'id',
    'field_name',
    'data',
  ))
    ->execute();
  foreach ($result as $row) {
    $data = unserialize($row->data);
    if (isset($data['settings']['personalize']) && in_array($data['settings']['personalize']['agent_type'], array(
      'acquia_lift',
      'acquia_lift_simple_ab',
    ))) {
      $data['settings']['personalize']['agent_type'] = 'acquia_lift_target';
      if (isset($data['settings']['personalize']['options']['acquia_lift'])) {
        unset($data['settings']['personalize']['options']['acquia_lift']);
      }
      if (isset($data['settings']['personalize']['options']['acquia_lift_simple_ab'])) {
        unset($data['settings']['personalize']['options']['acquia_lift_simple_ab']);
      }
      unset($data['settings']['personalize']['auto_stop']);
      unset($data['settings']['personalize']['auto_start']);
      db_update('field_config')
        ->fields(array(
        'data' => serialize($data),
      ))
        ->condition('id', $row->id)
        ->execute();
    }
  }

  // Update menu to match updated "Personalizations" terminology.
  // Remove Variations and Goals listings pages.
  menu_delete_links('acquia-lift-controls');
  _acquia_lift_build_menu('acquia-lift-controls');
}