<?php

/**
 * @file
 * Install, update and uninstall functions for the uc_order module.
 */

/**
 * Implements hook_schema().
 */
function uc_order_schema() {
  $schema = array();

  $schema['uc_orders'] = array(
    'description' => 'Stores Ubercart order information.',
    'fields' => array(
      'order_id' => array(
        'description' => 'Primary key: the order ID.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'uid' => array(
        'description' => 'The {user}.uid of the customer that placed the order.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'order_status' => array(
        'description' => 'The {uc_order_statuses}.order_status_id indicating the order status.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'order_total' => array(
        'description' => 'The total amount to be paid for the order.',
        'type' => 'numeric',
        'precision' => 16,
        'scale' => 5,
        'not null' => TRUE,
        'default' => 0.0,
      ),
      'product_count' => array(
        'description' => 'The total product quantity of the order.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'primary_email' => array(
        'description' => 'The email address of the customer.',
        'type' => 'varchar',
        'length' => 96,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_first_name' => array(
        'description' => 'The first name of the person receiving shipment.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_last_name' => array(
        'description' => 'The last name of the person receiving shipment.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_phone' => array(
        'description' => 'The phone number at the delivery location.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_company' => array(
        'description' => 'The company at the delivery location.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_street1' => array(
        'description' => 'The street address of the delivery location.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_street2' => array(
        'description' => 'The second line of the street address.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_city' => array(
        'description' => 'The city of the delivery location.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_zone' => array(
        'description' => 'The state/zone/province id of the delivery location.',
        'type' => 'int',
        'size' => 'medium',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'delivery_postal_code' => array(
        'description' => 'The postal code of the delivery location.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'delivery_country' => array(
        'description' => 'The country ID of the delivery location.',
        'type' => 'int',
        'size' => 'medium',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'billing_first_name' => array(
        'description' => 'The first name of the person paying for the order.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'billing_last_name' => array(
        'description' => 'The last name of the person paying for the order.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'billing_phone' => array(
        'description' => 'The phone number for the billing address.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'billing_company' => array(
        'description' => 'The company of the billing address.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'billing_street1' => array(
        'description' => 'The street address where the bill will be sent.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'billing_street2' => array(
        'description' => 'The second line of the street address.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'billing_city' => array(
        'description' => 'The city where the bill will be sent.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'billing_zone' => array(
        'description' => 'The state/zone/province ID where the bill will be sent.',
        'type' => 'int',
        'size' => 'medium',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'billing_postal_code' => array(
        'description' => 'The postal code where the bill will be sent.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'billing_country' => array(
        'description' => 'The country ID where the bill will be sent.',
        'type' => 'int',
        'size' => 'medium',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'payment_method' => array(
        'description' => 'The method of payment.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'data' => array(
        'description' => 'A serialized array of extra data.',
        'type' => 'text',
        'serialize' => TRUE,
      ),
      'created' => array(
        'description' => 'The Unix timestamp indicating when the order was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'modified' => array(
        'description' => 'The Unix timestamp indicating when the order was last modified.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'host' => array(
        'description' => 'Host IP address of the person paying for the order.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'currency' => array(
        'description' => 'The ISO currency code for the order.',
        'type' => 'char',
        'length' => 3,
        'not null' => TRUE,
        'default' => '',
      ),
    ),
    'indexes' => array(
      'uid' => array('uid'),
      'order_status' => array('order_status'),
    ),
    'primary key' => array('order_id'),
    'foreign keys' => array(
      'users' => array(
        'table' => 'users',
        'columns' => array('uid' => 'uid'),
      ),
      'uc_order_statuses' => array(
        'table' => 'uc_order_statuses',
        'columns' => array('order_status' => 'order_status_id'),
      ),
    ),
  );

  $schema['uc_order_admin_comments'] = array(
    'description' => 'Comments on orders that only administrators can see.',
    'fields' => array(
      'comment_id' => array(
        'description' => 'Primary key: the comment ID.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'order_id' => array(
        'description' => 'The {uc_orders}.order_id of the order.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'uid' => array(
        'description' => 'The {user}.uid of the author of the comment.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'message' => array(
        'description' => 'The comment body.',
        'type' => 'text',
      ),
      'created' => array(
        'description' => 'The Unix timestamp indicating when the comment was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'order_id' => array('order_id'),
    ),
    'primary key' => array('comment_id'),
    'foreign keys' => array(
      'uc_orders' => array(
        'table' => 'uc_orders',
        'columns' => array('order_id' => 'order_id'),
      ),
      'users' => array(
        'table' => 'users',
        'columns' => array('uid' => 'uid'),
      ),
    ),
  );

  $schema['uc_order_comments'] = array(
    'description' => 'Comments on the order that the customer can see.',
    'fields' => array(
      'comment_id' => array(
        'description' => 'Primary key: the comment ID.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'order_id' => array(
        'description' => 'The {uc_orders}.order_id of the order.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'uid' => array(
        'description' => 'The {users}.uid of the user who made the comment.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'order_status' => array(
        'description' => 'The status the order had when the comment was made, from {uc_order_statuses}.order_status_id.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'notified' => array(
        'description' => 'A flag indicating whether the comment was emailed to the customer. 1 => Yes. 0 => No.',
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 0,
      ),
      'message' => array(
        'description' => 'The comment body.',
        'type' => 'text',
      ),
      'created' => array(
        'description' => 'The Unix timestamp indicating when the comment was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'order_id' => array('order_id'),
    ),
    'primary key' => array('comment_id'),
    'foreign keys' => array(
      'uc_orders' => array(
        'table' => 'uc_orders',
        'columns' => array('order_id' => 'order_id'),
      ),
      'users' => array(
        'table' => 'users',
        'columns' => array('uid' => 'uid'),
      ),
    ),
  );

  $schema['uc_order_line_items'] = array(
    'description' => 'Order line items other than products.',
    'fields' => array(
      'line_item_id' => array(
        'description' => 'Primary key: the line item ID.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'order_id' => array(
        'description' => 'The {uc_orders}.order_id.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'type' => array(
        'description' => 'The line item type.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'title' => array(
        'description' => 'The label of the line item.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'amount' => array(
        'description' => "The amount of the line item in the store's currency.",
        'type' => 'numeric',
        'precision' => 16,
        'scale' => 5,
        'not null' => TRUE,
        'default' => 0.0,
      ),
      'weight' => array(
        'description' => 'The sort criteria of line items.',
        'type' => 'int',
        'size' => 'small',
        'not null' => TRUE,
        'default' => 0,
      ),
      'data' => array(
        'description' => 'A serialized array of extra data.',
        'type' => 'text',
        'serialize' => TRUE,
      ),
    ),
    'indexes' => array(
      'order_id' => array('order_id'),
    ),
    'primary key' => array('line_item_id'),
    'foreign keys' => array(
      'uc_orders' => array(
        'table' => 'uc_orders',
        'columns' => array('order_id' => 'order_id'),
      ),
    ),
  );

  $schema['uc_order_log'] = array(
    'description' => 'Record of changes made to an order.',
    'fields' => array(
      'order_log_id' => array(
        'description' => 'Primary key: the log entry ID.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'order_id' => array(
        'description' => 'The {uc_orders}.order_id.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'uid' => array(
        'description' => 'The {users}.uid of the user who made the changes.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'changes' => array(
        'description' => 'The description of what was changed.',
        'type' => 'text',
      ),
      'created' => array(
        'description' => 'The Unix timestamp indicating when the change was made.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'order_id' => array('order_id'),
    ),
    'primary key' => array('order_log_id'),
    'foreign keys' => array(
      'uc_orders' => array(
        'table' => 'uc_orders',
        'columns' => array('order_id' => 'order_id'),
      ),
      'users' => array(
        'table' => 'users',
        'columns' => array('uid' => 'uid'),
      ),
    ),
  );

  $schema['uc_order_products'] = array(
    'description' => 'The products that have been ordered.',
    'fields' => array(
      'order_product_id' => array(
        'description' => 'Primary key: the ordered product ID.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'order_id' => array(
        'description' => 'The {uc_orders}.order_id.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'nid' => array(
        'description' => 'The {node}.nid of the product.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'title' => array(
        'description' => 'The product title, from {node}.title.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'model' => array(
        'description' => 'The product model/SKU, from {uc_products}.model.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'qty' => array(
        'description' => 'The number of the same product ordered.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'cost' => array(
        'description' => 'The cost to the store for the product.',
        'type' => 'numeric',
        'precision' => 16,
        'scale' => 5,
        'not null' => TRUE,
        'default' => 0.0,
      ),
      'price' => array(
        'description' => 'The price paid for the ordered product.',
        'type' => 'numeric',
        'precision' => 16,
        'scale' => 5,
        'not null' => TRUE,
        'default' => 0.0,
      ),
      'weight' => array(
        'description' => 'The physical weight.',
        'type' => 'float',
        'not null' => TRUE,
        'default' => 0.0,
      ),
      'weight_units' => array(
        'description' => 'Unit of measure for the weight field.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => 'lb',
      ),
      'data' => array(
        'description' => 'A serialized array of extra data.',
        'type' => 'text',
        'serialize' => TRUE,
      ),
    ),
    'indexes' => array(
      'order_id' => array('order_id'),
      'qty' => array('qty'),
      'nid' => array('nid'),
    ),
    'primary key' => array('order_product_id'),
    'foreign keys' => array(
      'uc_orders' => array(
        'table' => 'uc_orders',
        'columns' => array('order_id' => 'order_id'),
      ),
      'node' => array(
        'table' => 'node',
        'columns' => array('nid' => 'nid'),
      ),
    ),
  );

  $schema['uc_order_statuses'] = array(
    'description' => 'Statuses the order can have during its lifecycle.',
    'fields' => array(
      'order_status_id' => array(
        'description' => 'Primary key: the order status ID.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'title' => array(
        'description' => 'The status title.',
        'type' => 'varchar',
        'length' => 48,
        'not null' => TRUE,
        'default' => '',
      ),
      'state' => array(
        'description' => 'The base order state with which the status is associated.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'weight' => array(
        'description' => 'The sort criteria for statuses.',
        'type' => 'int',
        'size' => 'small',
        'not null' => TRUE,
        'default' => 0,
      ),
      'locked' => array(
        'description' => 'A flag indicating whether users can delete the status. 0 => Yes. 1 => No.',
        'type' => 'int',
        'size' => 'tiny',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'primary key' => array('order_status_id'),
  );

  return $schema;
}

/**
 * Implements hook_install().
 */
function uc_order_install() {
  $t = get_t();

  $query = db_insert('uc_order_statuses')
    ->fields(array(
      'order_status_id',
      'title',
      'state',
      'weight',
      'locked',
    ));

  $values = array(
    array(
      'order_status_id' => 'abandoned',
      'title' => $t('Abandoned'),
      'state' => 'canceled',
      'weight' => -30,
      'locked' => 1,
    ),
    array(
      'order_status_id' => 'canceled',
      'title' => $t('Canceled'),
      'state' => 'canceled',
      'weight' => -20,
      'locked' => 1,
    ),
    array(
      'order_status_id' => 'in_checkout',
      'title' => $t('In checkout'),
      'state' => 'in_checkout',
      'weight' => -10,
      'locked' => 1,
    ),
    array(
      'order_status_id' => 'pending',
      'title' => $t('Pending'),
      'state' => 'post_checkout',
      'weight' => 0,
      'locked' => 1,
    ),
    array(
      'order_status_id' => 'processing',
      'title' => $t('Processing'),
      'state' => 'post_checkout',
      'weight' => 5,
      'locked' => 1,
    ),
    array(
      'order_status_id' => 'completed',
      'title' => $t('Completed'),
      'state' => 'completed',
      'weight' => 20,
      'locked' => 1,
    ),
  );

  foreach ($values as $record) {
    $query->values($record);
  }
  $query->execute();
}

/**
 * Implements hook_uninstall().
 */
function uc_order_uninstall() {
  db_delete('variable')
    ->condition('name', 'uc_state_%', 'LIKE')
    ->execute();

  variable_del('uc_order_capitalize_addresses');
  variable_del('uc_cust_order_invoice_template');
}

/**
 * Implements hook_update_last_removed().
 */
function uc_order_update_last_removed() {
  // 7.x-3.0-beta2 and earlier were installed with schema version 0,
  // which causes update.php to fail.
  return drupal_get_installed_schema_version('uc_order') == 0 ? 0 : 6015;
}

/**
 * Remove unused setting.
 */
function uc_order_update_6016() {
  variable_del('uc_ubrowser_product_select');
}

/**
 * Increase the maximum length of product and line item titles.
 */
function uc_order_update_7000() {
  db_change_field('uc_order_products', 'title', 'title', array(
    'description' => 'The product title, from {node}.title.',
    'type' => 'varchar',
    'length' => 255,
    'not null' => TRUE,
    'default' => '',
  ));

  db_change_field('uc_order_line_items', 'title', 'title', array(
    'description' => 'The label of the line item.',
    'type' => 'varchar',
    'length' => 255,
    'not null' => TRUE,
    'default' => '',
  ));
}

/**
 * Add currency code field.
 */
function uc_order_update_7001() {
  // Column may have been added by uc_order_update_6018() in 6.x-2.x.
  if (!db_field_exists('uc_orders', 'currency')) {
    db_add_field('uc_orders', 'currency', array(
      'type' => 'char',
      'length' => 3,
      'not null' => TRUE,
      'default' => '',
    ));
    db_update('uc_orders')
      ->fields(array('currency' => variable_get('uc_currency_code', 'USD')))
      ->execute();
  }
}


/**
 * Add indexes so product and customer reports are usable with large datasets.
 */
function uc_order_update_7002() {
  // Indexes may have been added by uc_order_update_6019() in 6.x-2.x.
  if (!db_index_exists('uc_order_products', 'qty')) {
    db_add_index('uc_order_products', 'qty', array('qty'));
  }

  if (!db_index_exists('uc_order_products', 'nid')) {
    db_add_index('uc_order_products', 'nid', array('nid'));
  }
}

/**
 * Increase maximum order item quantity.
 */
function uc_order_update_7003() {
  db_change_field('uc_order_products', 'qty', 'qty', array(
    'description' => 'The number of the same product ordered.',
    'type' => 'int',
    'unsigned' => TRUE,
    'not null' => TRUE,
    'default' => 0,
  ));
}

/**
 * Add weight units to order products.
 */
function uc_order_update_7004(&$sandbox) {
  if (!isset($sandbox['progress'])) {
    if (db_field_exists('uc_order_products', 'weight_units')) {
      return;
    }

    $sandbox['progress'] = 0;
    $sandbox['current_nid'] = 0;
    $sandbox['max'] = db_query("SELECT COUNT(DISTINCT nid) FROM {uc_products}")->fetchField();

    db_add_field('uc_order_products', 'weight_units', array(
      'description' => 'Unit of measure for the weight field.',
      'type' => 'varchar',
      'length' => 255,
      'not null' => TRUE,
      'default' => 'lb',
    ));

    db_update('uc_order_products')
      ->fields(array('weight_units' => variable_get('uc_weight_unit', 'lb')))
      ->condition('nid', 0)
      ->execute();
  }

  $t = get_t();

  $limit = 200;

  $result = db_query_range("SELECT n.nid, n.title, p.weight_units FROM {node} n JOIN {uc_products} p ON n.vid = p.vid WHERE n.nid > :current ORDER BY n.nid", 0, $limit, array(':current' => $sandbox['current_nid']));

  foreach ($result as $node) {
    db_update('uc_order_products')
      ->fields(array('weight_units' => $node->weight_units))
      ->condition('nid', $node->nid)
      ->execute();

    $sandbox['progress']++;
    $sandbox['current_nid'] = $node->nid;
    $sandbox['message'] = $t('Copied weight units from %title.', array('%title' => $node->title));
  }

  if ($sandbox['progress'] < $sandbox['max']) {
    $sandbox['#finished'] = min(0.99, $sandbox['progress'] / $sandbox['max']);
  }
  else {
    $sandbox['#finished'] = 1;
  }
}

/**
 * Remove deprecated manufacturer column.
 */
function uc_order_update_7005() {
  db_drop_field('uc_order_products', 'manufacturer');
}

/**
 * Remove unused variable.
 */
function uc_order_update_7006() {
  variable_del('uc_order_number_displayed');
}

/**
 * Add 'abandoned' order status.
 */
function uc_order_update_7007() {
  db_merge('uc_order_statuses')
    ->key(array('order_status_id' => 'abandoned'))
    ->fields(array(
      'title' => t('Abandoned'),
      'state' => 'canceled',
      'weight' => -30,
      'locked' => 1,
    ))
    ->execute();

  db_update('uc_orders')
    ->fields(array('order_status' => 'abandoned'))
    ->condition('order_status', 'in_checkout')
    ->condition('modified', REQUEST_TIME - 600, '<')
    ->execute();
}

/**
 * Delete unwanted sensitive data.
 */
function uc_order_update_7300() {
  $result = db_query("SELECT order_id, data FROM {uc_orders} WHERE data LIKE '%s:4:\"pass\"%'");
  while ($row = $result->fetchObject()) {
    $data = unserialize($row->data);
    if (isset($data['new_user']['pass'])) {
      unset($data['new_user']['pass']);
      db_update('uc_orders')
        ->fields(array('data' => serialize($data)))
        ->condition('order_id', $row->order_id)
        ->execute();
    }
  }

  variable_del('uc_order_cron_last');
}

/**
 * Convert view invoices checkbox to permission.
 */
function uc_order_update_7301() {
  if (variable_get('uc_cust_view_order_invoices', TRUE)) {
    // user_role_grant_permissions() is not allowed during upgrades from D6.
    db_merge('role_permission')
      ->key(array(
        'rid' => DRUPAL_AUTHENTICATED_RID,
        'permission' => 'view own invoices',
      ))
      ->fields(array(
        'module' => 'uc_order',
      ))
      ->execute();
  }
  variable_del('uc_cust_view_order_invoices');
}

/**
 * Remove unused order pane settings.
 */
function uc_order_update_7302() {
  db_delete('variable')
    ->condition('name', 'uc_order_pane_%', 'LIKE')
    ->execute();
}
