<?php

/**
 * @file
 * Contains install, update, and uninstall functions for Skinr.
 */

/**
 * Implements hook_schema().
 */
function skinr_schema() {
  $schema['skinr_skins'] = array(
    'description' => 'Stores skinr data.',
    'fields' => array(
      'sid' => array(
        'description' => 'The primary identifier for a skin configuration.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'theme' => array(
        'description' => 'The theme this configuration applies to.',
        'type' => 'varchar',
        'length' => 64,
        'not null' => TRUE,
        'default' => '',
      ),
      'module' => array(
        'description' => 'The module this configuration applies to.',
        'type' => 'varchar',
        'length' => 64,
        'not null' => TRUE,
        'default' => '',
      ),
      'element' => array(
        'description' => 'The element this configutation applies to.',
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'default' => '',
      ),
      'skin' => array(
        'description' => 'The skin that has been applied.',
        'type' => 'varchar',
        'length' => 64,
        'not null' => TRUE,
        'default' => '',
      ),
      'options' => array(
        'description' => 'A serialized array containing the skin options that have been applied.',
        'type' => 'text',
        'size' => 'big',
        'not null' => TRUE,
        'serialize' => TRUE,
      ),
      'status' => array(
        'description' => 'Boolean indicating whether or not this item is enabled.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
        'size' => 'tiny',
      ),
    ),
    'primary key' => array('sid'),
    'indexes' => array(
      'theme' => array('theme'),
      'module' => array('theme', 'module'),
      'element' => array('theme', 'module', 'element'),
      'skin' => array('skin'),
    ),
  );

  return $schema;
}

/**
 * Implements hook_uninstall().
 */
function skinr_uninstall() {
  // Remove all skinr variables.
  db_delete('variable')
    ->condition('name', 'skinr_%', 'LIKE')
    ->execute();
}

/**
 * Implements hook_update_last_removed().
 *
 * Make sure any previous updates aren't skipped.
 */
function skinr_update_last_removed() {
  // Determine version 6.x-1.x or 6.x-2.x.
  $version = drupal_get_installed_schema_version('skinr');
  if ($version >= 7000) {
    // 7.x-2.x.
    return 7003;
  }
  if ($version == 6100) {
    // 6.x-1.x.
    return 6100;
  }
  elseif ($version >= 6000) {
    // 6.x-2.x.
    return 6004;
  }
}

/**
 * Upgrade from Skinr 6.x-1.x or 6.x-2.x.
 */
function skinr_update_7200() {
  $t = get_t();

  if (!db_table_exists('skinr_skins')) {
    // The skinr_skins table exists for both 7.x-1.x and 6.x-2.x, so we're only
    // targeting 6.x-1.x.

    // Create skinr_skins table.
    $schema = drupal_get_schema_unprocessed('skinr');
    db_create_table('skinr_skins', $schema['skinr_skins']);

    // Exclude variables that aren't theme settings.
    $exclude = array('skinr_settings_page', 'skinr_overlay_width', 'skinr_overlay_height', 'skinr_overlay_autofit', 'skinr_overlay_draggable');

    $result = db_query("SELECT name FROM {variable} WHERE name LIKE 'skinr_%'");
    foreach ($result as $variable) {
      if (in_array($variable->name, $exclude)) {
        continue;
      }

      // Convert from variable to db.
      $theme = substr($variable->name, 6);
      $theme_skins = variable_get($variable->name, array());
      if (is_array($theme_skins)) {
        foreach ($theme_skins as $module => $elements) {
          foreach ($elements as $element => $skins) {
            foreach ($skins as $skin => $options) {
              if (!is_array($options)) {
                $options = array($options);
              }

              db_insert('skinr_skins')
                ->fields(array(
                  'theme' => $theme,
                  'module' => $module,
                  'element' => _skinr_element_name($module, $element),
                  'skin' => $skin,
                  'options' => serialize($options),
                  'status' => 1,
                ))
                ->execute();
            }
          }
        }

        // Delete the old variable.
        variable_del($variable->name);
      }
    }
  }
  else {
    if (db_table_exists('skinr_skinsets')) {
      // The info files are now stored in code.
      db_drop_table('skinr_skinsets');
    }

    if (db_field_exists('skinr_skins', 'type')) {
      // The name field only appeared in the 6.x-2.x version of this table. This
      // table briefly existed in 7.x-2.x as well in the same incarnation.

      // Move data from old table to variables.
      $result = db_query("SELECT * FROM {skinr_skins}");
      foreach ($result as $skin_info) {
        $skin_info->status = unserialize($skin_info->status);
        $variable = 'skinr_skin_' . $skin_info->name . '_status';
        if (!variable_get($variable, FALSE)) {
          $status = array();
          foreach ($skin_info->status as $key => $theme) {
            if ($theme) {
              $status[$theme] = 1;
            }
          }
          variable_set($variable, $status);
        }
      }

      // Delete the table.
      db_drop_table('skinr_skins');
    }

    if (!db_table_exists('skinr_skins')) {
      // Create the new skinr_skins table.
      $schema = drupal_get_schema_unprocessed('skinr');
      db_create_table('skinr_skins', $schema['skinr_skins']);
    }
    else {
      // Delete unique key.
      db_drop_unique_key('skinr_skins', 'theme_module_element_skin');
    }

    // We require skinr_context to be enabled to ensure our tables exist.
    module_enable(array('ctools', 'context', 'skinr_context'));

    $groups = array();
    if (db_table_exists('skinr_rules')) {
      // Skinr Context replaces Rules.

      // The rule_type field started appearing in the 7.x-2.x version of this
      // table. Module/type changed from 'page' to 'rules'.
      $has_rule_type = db_field_exists('skinr_rules', 'rule_type');

      // Add rules to its tables.
      $result = db_query("SELECT * FROM {skinr_rules}");
      foreach ($result as $rule) {
        $rule->roles = unserialize($rule->roles);

        // Element.
        $element = 'html';
        if (isset($rule->rule_type) && strpos($rule->rule_type, 'region__') === 0) {
          // Element is a region.
          $element = $rule->rule_type;
        }

        // Conditions.
        $conditions = array();
        // Paths.
        if (!empty($rule->pages) && $rule->visibility != 2) {
          // @todo See if we want to process paths with PHP.
          $paths = array();
          $pages = explode("\n", str_replace("\r\n", "\n", $rule->pages));
          $prefix = ($rule->visibility == 1 ? '-' : '');
          foreach ($pages as $page) {
            $paths[$prefix . $page] = $prefix . $page;
          }
          $conditions['path'] = array('values' => $pages);
        }

        // User roles.
        $roles = array();
        foreach ($rule->roles as $rid) {
          if ($rid > 0) {
            if ($role = user_role_load($rid)) {
              $roles[$role->name] = $role->name;
            }
          }
        }
        if ($roles) {
          $conditions['user'] = array('values' => $roles);
        }

        // Node types.
        if (isset($rule->node_types)) {
          $types = array();
          foreach ($rule->node_types as $type => $value) {
            if ($value) {
              $types[$type] = $type;
            }
          }
          if ($types) {
            $conditions['node'] = array('values' => $types, 'options' => array('node_form' => '1'));
          }
        }

        // Set default.
        if (!$conditions) {
          $conditions = array('sitewide' => array('values' => array(1 => 1)));
        }

        // Save our new group.
        $groups[$rule->rid] = $rule;
        $groups[$rule->rid]->gid = db_insert('skinr_groups')
          ->fields(array(
            'module' => 'system',
            'element' => $element,
            'title' => $rule->title,
            'description' => '',
            'conditions' => serialize($conditions),
            'condition_mode' => 0,
            'weight' => 0,
            'status' => 1,
          ))
          ->execute();
      }

      // Delete the table.
      db_drop_table('skinr_rules');
    }

    // Process rule related skin settings.
    if ($groups) {
      $result = db_query("SELECT * FROM {skinr_skins} WHERE module = 'rules'");
      foreach ($result as $skin) {
        $element = 'html';
        if (isset($groups[$skin->element])) {
          $rule = $groups[$skin->element];
          if (isset($rule->rule_type) && strpos($rule->rule_type, 'region__') === 0) {
            // Element is a region.
            $element = $rule->rule_type;
          }

          // Link skin setting to group.
          db_insert('skinr_group_skins')
            ->fields(array(
              'gid' => $rule->gid,
              'sid' => $skin->sid,
            ))
            ->execute();
        }

        // Update module and element fields.
        db_update('skinr_skins')
          ->fields(array(
            'module' => 'system',
            'element' => $element,
          ))
          ->condition('sid', $skin->sid)
          ->execute();
      }
    }

    if (db_table_exists('skinr')) {
      $result = db_query("SELECT * FROM {skinr}");
      foreach ($result as $skins) {
        $skins->skins = unserialize($skins->skins);
        foreach ($skins->skins as $skin => $options) {
          $module = $skins->module;
          $element = _skinr_element_name($module, $skins->sid);
          $gid = NULL;

          if ($skins->module == 'rules' || $skins->module == 'page') {
            $module = 'system';
            $element = 'html';
            if (isset($groups[$skins->sid])) {
              $rule = $groups[$skins->sid];
              $gid = $rule->gid;
              if (isset($rule->rule_type) && strpos($rule->rule_type, 'region__') === 0) {
                // Element is a region.
                $element = $rule->rule_type;
              }
            }
          }
          else {
            // Create default group.
            if (isset($groups[$module . '__' . $element])) {
              $gid = $groups[$module . '__' . $element];
            }
            else {
              $gid = db_insert('skinr_groups')
                ->fields(array(
                  'module' => $module,
                  'element' => $element,
                  'title' => $t('Default'),
                  'description' => '',
                  'conditions' => serialize(array('sitewide' => array('values' => array(1 => 1)))),
                  'condition_mode' => 0,
                  'weight' => 0,
                  'status' => 1,
                ))
                ->execute();
              $groups[$module . '__' . $element] = $gid;
            }
          }
          if (!is_array($options)) {
            $options = array($options);
          }

          $sid = db_insert('skinr_skins')
            ->fields(array(
              'theme' => $skins->theme,
              'module' => $module,
              'element' => $element,
              'skin' => $skin,
              'options' => serialize($options),
              'status' => 1,
            ))
            ->execute();

          if ($gid) {
            // Link skin setting to group.
            db_insert('skinr_group_skins')
              ->fields(array(
                'gid' => $gid,
                'sid' => $sid,
              ))
              ->execute();
          }
        }
      }

      // Delete the table.
      db_drop_table('skinr');
    }
  }
}

/**
 * Returns the renamed system element.
 *
 * @see system_update_7004()
 */
function _skinr_element_name($module, $element) {
  if ($module == 'block') {
    list($block_module, $delta) = explode('-', $element, 2);
    // Get an array of the renamed block deltas, organized by module.
    $renamed_deltas = array(
      'blog' => array('0' => 'recent'),
      'book' => array('0' => 'navigation'),
      'comment' => array('0' => 'recent'),
      'forum' => array(
        '0' => 'active',
        '1' => 'new',
      ),
      'locale' => array('0' => LANGUAGE_TYPE_INTERFACE),
      'node' => array('0' => 'syndicate'),
      'poll' => array('0' => 'recent'),
      'profile' => array('0' => 'author-information'),
      'search' => array('0' => 'form'),
      'statistics' => array('0' => 'popular'),
      'system' => array('0' => 'powered-by'),
      'user' => array(
        '0' => 'login',
        '1' => 'navigation',
        '2' => 'new',
        '3' => 'online',
      ),
    );

    $moved_deltas = array(
      'user' => array('navigation' => 'system'),
    );

    if (isset($renamed_deltas[$block_module][$delta])) {
      $delta = $renamed_deltas[$block_module][$delta];
    }
    if (isset($moved_deltas[$block_module][$delta])) {
      $block_module = $moved_deltas[$block_module][$delta];
    }
    $element = $block_module . '__' . $delta;
  }
  elseif ($module == 'panels') {
    // Strip 'panel-'.
    $element = substr($element, 8);
    // Extract did and pid.
    if (strpos($element, '-region-') !== FALSE) {
      list($did, $pid) = explode('-region-', $element, 2);
      $element = 'region__' . $did . '__' . $pid;
    }
    elseif (strpos($element, '-pane-') !== FALSE) {
      list($did, $pid) = explode('-pane-', $element, 2);
      $element = 'pane__' . $did . '__' . $pid;
    }
    else {
      list($did, $pid) = explode('-pane-', $element, 2);
      $element = 'panel__' . $did;
    }
  }
  elseif ($module == 'views') {
    list($view, $display) = explode('-display-', $element, 2);
    $view = substr($view, 5);
    $element = $view . '__' . $display;
  }

  return $element;
}
