You are here

redhen_relation.install in RedHen CRM 7

Install, update and uninstall functions for the redhen relations module.

File

modules/redhen_relation/redhen_relation.install
View source
<?php

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

/**
 * Implements hook_schema().
 */
function redhen_relation_schema() {
  $schema['redhen_relation_role'] = array(
    'description' => 'RedHen Relation Role.',
    'fields' => array(
      'redhen_relation_role_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'The redhen relation role ID.',
      ),
      'name' => array(
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'description' => 'The machine name of the redhen relation role.',
      ),
      'label' => array(
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'description' => 'The human readable name of the redhen relation role.',
      ),
      'permissions' => array(
        'type' => 'text',
        'not null' => FALSE,
        'size' => 'big',
        'serialize' => TRUE,
        'description' => 'A serialized array of permissions.',
      ),
      'status' => array(
        'type' => 'int',
        'not null' => TRUE,
        // Set the default to ENTITY_CUSTOM without using the constant as it is
        // not safe to use it at this point.
        'default' => 0x1,
        'size' => 'tiny',
        'description' => 'The exportable status of the entity.',
      ),
      'module' => array(
        'description' => 'The name of the providing module if the entity has been defined in code.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => FALSE,
      ),
    ),
    'indexes' => array(
      'redhen_relation_role_name' => array(
        'name',
      ),
    ),
    'primary key' => array(
      'redhen_relation_role_id',
    ),
    'unique keys' => array(
      'name' => array(
        'name',
      ),
    ),
  );
  return $schema;
}

/**
 * Implements hook_install().
 */
function redhen_relation_install() {

  // Create default Admin and Member roles.
  $default_roles = array(
    'admin' => array(
      'name' => 'admin',
      'label' => 'Admin',
      'permissions' => array(
        'add_relation' => 'add_relation',
        'edit_relation' => 'edit_relation',
        'delete_relation' => 'delete_relation',
      ),
      'default_role' => 0,
    ),
    'member' => array(
      'name' => 'member',
      'label' => 'Member',
      'permissions' => array(),
      'default_role' => 1,
    ),
  );
  foreach ($default_roles as $default_role) {
    $relation_role = entity_create('redhen_relation_role', $default_role);
    $relation_role
      ->save();
  }

  // Add default relationships.
  $relation_types_info = array(
    array(
      'relation_type' => REDHEN_RELATION_CONNECTION,
      'label' => t('Personal connection'),
      'source_bundles' => array(
        'redhen_contact:*',
      ),
      'r_unique' => TRUE,
    ),
    array(
      'relation_type' => REDHEN_RELATION_AFFILIATION,
      'label' => t('Organizational affiliation'),
      'reverse_label' => t('Affiliated with'),
      'directional' => TRUE,
      'r_unique' => TRUE,
      'source_bundles' => array(
        'redhen_contact:*',
      ),
      'target_bundles' => array(
        'redhen_org:*',
      ),
    ),
  );
  foreach ($relation_types_info as $relation_type_info) {
    $relation_type = relation_type_create($relation_type_info);
    relation_type_save($relation_type);
  }

  // Add relation status field.
  $status_field = array(
    'field_name' => REDHEN_RELATION_STATUS_FIELD,
    'type' => 'list_boolean',
    'locked' => TRUE,
    'cardinality' => 1,
    'settings' => array(
      'allowed_values' => array(
        'Inactive',
        'Active',
      ),
    ),
  );
  field_create_field($status_field);
  $bundles = array(
    REDHEN_RELATION_AFFILIATION => 'Active',
    REDHEN_RELATION_CONNECTION => 'Active',
  );
  foreach ($bundles as $key => $label) {
    field_create_instance(array(
      'field_name' => REDHEN_RELATION_STATUS_FIELD,
      'entity_type' => 'relation',
      'bundle' => $key,
      'label' => $label,
      'required' => 0,
      'default_value' => array(
        array(
          'value' => 1,
        ),
      ),
      'widget' => array(
        'type' => 'options_onoff',
        'settings' => array(
          'display_label' => 1,
        ),
      ),
    ));
  }

  // Add relation role field.
  $role_field = array(
    'field_name' => REDHEN_RELATION_ROLES_FIELD,
    'type' => 'entityreference',
    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
    'settings' => array(
      'target_type' => 'redhen_relation_role',
      'target_bundles' => array(
        'redhen_relation_role',
      ),
    ),
  );
  field_create_field($role_field);

  // Get default value: ID of Member role.
  $member_role_entity = entity_load('redhen_relation_role', FALSE, array(
    'name' => 'member',
  ));
  $member_role_id = (int) array_shift($member_role_entity)->redhen_relation_role_id;
  field_create_instance(array(
    'field_name' => REDHEN_RELATION_ROLES_FIELD,
    'entity_type' => 'relation',
    'bundle' => REDHEN_RELATION_AFFILIATION,
    'label' => 'Organization Role',
    'description' => 'Select the roles this contact has in this organization.',
    'required' => 0,
    'default_value' => array(
      array(
        'target_id' => $member_role_id,
      ),
    ),
    'widget' => array(
      'type' => 'options_buttons',
    ),
  ));
  entity_info_cache_clear();
}

/**
 * Implements hook_uninstall().
 */
function redhen_relation_uninstall() {

  // Get all the relationship_types (bundles), find all fields
  // delete them.
  $query = db_select('relation_bundles', 'rb')
    ->fields('rb', array(
    'relation_type',
  ))
    ->condition('rb.entity_type', 'redhen_contact')
    ->distinct()
    ->execute();
  $relationship_type = array();
  while ($record = $query
    ->fetchAssoc()) {
    $relationship_type[] = $record['relation_type'];
  }
  foreach ($relationship_type as $type) {

    // Look into the database for each type.
    $relationship_query = db_select('relation', 'r')
      ->fields('r', array(
      'rid',
    ))
      ->condition('r.relation_type', $type)
      ->execute();
    while ($result = $relationship_query
      ->fetchAssoc()) {

      // Delete all the relationships of that type.
      relation_delete($result['rid']);
    }

    // Finally delete the relationshp_type.
    relation_type_delete($type);
  }

  // Delete status field.
  field_delete_field('redhen_relation_status');

  // Delete Roles field:
  field_delete_field('redhen_relation_roles');

  // Delete relation role field.
  field_delete_field(REDHEN_RELATION_ROLES_FIELD);
  entity_info_cache_clear();
}

/**
 * Remove old relation role field and add new, converting existing data.
 */
function redhen_relation_update_7101(&$sandbox) {

  // Save old field values for the Relation Roles field in the Sandbox.
  $limit = 20;
  if (!isset($sandbox['instances'])) {

    // Assemble all entities that have values for the relation roles field.
    $all_fields = field_info_field_map();
    if (isset($all_fields[REDHEN_RELATION_ROLES_FIELD])) {
      $sandbox['old_instances'] = $all_fields[REDHEN_RELATION_ROLES_FIELD]['bundles'];
      $sandbox['instances'] = $all_fields[REDHEN_RELATION_ROLES_FIELD]['bundles'];
      $sandbox['entities'] = array();
      $sandbox['count'] = 0;
      $sandbox['save_progress'] = 0;
      $sandbox['transfer_progress'] = 0;
      $sandbox['fields_processed'] = FALSE;
      foreach ($sandbox['instances'] as $entity_type => $bundles) {
        $query = new EntityFieldQuery();
        $query
          ->entityCondition('entity_type', $entity_type, '=')
          ->fieldCondition(REDHEN_RELATION_ROLES_FIELD);
        $result = $query
          ->execute();
        if (isset($result[$entity_type])) {
          $sandbox['entities'][$entity_type] = array_keys($result[$entity_type]);
          $sandbox['count'] += count($result[$entity_type]);
        }
      }
    }
    else {
      $sandbox['instances'] = FALSE;
    }
  }
  if (!empty($sandbox['entities'])) {
    $allowance = $limit;

    // Loop through existing values and save them in the Sandbox for later use.
    foreach ($sandbox['entities'] as $entity_type => &$entity_ids) {
      while (!empty($entity_ids)) {
        if ($allowance < 1) {
          $sandbox['#finished'] = $sandbox['count'] ? ($sandbox['save_progress'] + $sandbox['transfer_progress']) / (2 * $sandbox['count']) : 0;
          return t('Saving old field values: !progress% complete.', array(
            '!progress' => $sandbox['#finished'] * 100,
          ));
        }
        else {
          $allowance--;
          $id = array_pop($entity_ids);
          $sandbox['save_progress']++;
          $entity = entity_load_single($entity_type, $id);
          if ($entity) {
            $wrapper = entity_metadata_wrapper($entity_type, $entity);
            $sandbox['old_values'][] = array(
              'entity_type' => $entity_type,
              'id' => $id,
              'value' => $wrapper->{REDHEN_RELATION_ROLES_FIELD}
                ->value(),
            );
          }
        }
      }
    }
    if (empty($sandbox['entities'][$entity_type])) {
      unset($sandbox['entities'][$entity_type]);
    }
    $sandbox['#finished'] = $sandbox['count'] ? ($sandbox['save_progress'] + $sandbox['transfer_progress']) / (2 * $sandbox['count']) : 0;
    return t('Saving old field values: !progress% complete.', array(
      '!progress' => $sandbox['#finished'] * 100,
    ));
  }
  if (empty($sandbox['fields_processed']) || !$sandbox['fields_processed']) {

    // All old field values should now be preserved in $sandbox['old_values'].
    // Proceed with replacing field.
    // Make sure that new new entity classes are available.
    registry_rebuild();

    // Install redhen_relation_role schema.
    $relation_role_schema = array(
      'description' => 'RedHen Relation Role.',
      'fields' => array(
        'redhen_relation_role_id' => array(
          'type' => 'serial',
          'unsigned' => TRUE,
          'not null' => TRUE,
          'description' => 'The redhen relation role ID.',
        ),
        'name' => array(
          'type' => 'varchar',
          'length' => 128,
          'not null' => TRUE,
          'description' => 'The machine name of the redhen relation role.',
        ),
        'label' => array(
          'type' => 'varchar',
          'length' => 128,
          'not null' => TRUE,
          'description' => 'The human readable name of the redhen relation role.',
        ),
        'permissions' => array(
          'type' => 'text',
          'not null' => FALSE,
          'size' => 'big',
          'serialize' => TRUE,
          'description' => 'A serialized array of permissions.',
        ),
        'status' => array(
          'type' => 'int',
          'not null' => TRUE,
          // Set the default to ENTITY_CUSTOM without using the constant as it
          // is not safe to use it at this point.
          'default' => 0x1,
          'size' => 'tiny',
          'description' => 'The exportable status of the entity.',
        ),
        'module' => array(
          'description' => 'The name of the providing module if the entity has been defined in code.',
          'type' => 'varchar',
          'length' => 255,
          'not null' => FALSE,
        ),
      ),
      'indexes' => array(
        'redhen_relation_role_name' => array(
          'name',
        ),
      ),
      'primary key' => array(
        'redhen_relation_role_id',
      ),
      'unique keys' => array(
        'name' => array(
          'name',
        ),
      ),
    );

    // Ensure aren't trying to re-create an existing table.
    if (!db_table_exists('redhen_relation_role')) {
      db_create_table('redhen_relation_role', $relation_role_schema);
    }

    // Remove old relation role field.
    $purge_batch = 4;
    foreach ($sandbox['old_instances'] as $type => $bundles) {
      foreach ($bundles as $bundle) {
        $instance = field_info_instance($type, REDHEN_RELATION_ROLES_FIELD, $bundle);
        field_delete_instance($instance, $field_cleanup = TRUE);
        $purge_batch++;
      }
    }
    field_delete_field(REDHEN_RELATION_ROLES_FIELD);
    field_purge_batch($purge_batch);

    // Create default Admin and Member roles.
    $default_roles = array(
      'admin' => array(
        'name' => 'admin',
        'label' => 'Admin',
        'permissions' => array(
          'add_relation' => 'add_relation',
          'edit_relation' => 'edit_relation',
          'delete_relation' => 'delete_relation',
        ),
        'default_role' => 0,
      ),
      'member' => array(
        'name' => 'member',
        'label' => 'Member',
        'permissions' => array(),
        'default_role' => 1,
      ),
    );
    foreach ($default_roles as $rolename => $default_role) {
      $relation_role = entity_create('redhen_relation_role', $default_role);
      $relation_role
        ->save();
    }

    // Add new relation role field.
    $field = array(
      'field_name' => REDHEN_RELATION_ROLES_FIELD,
      'type' => 'entityreference',
      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
      'settings' => array(
        'target_type' => 'redhen_relation_role',
        'target_bundles' => array(
          'redhen_relation_role',
        ),
      ),
    );
    field_create_field($field);

    // Load up the new roles to use in other settings.
    $admin_role_entity = entity_load('redhen_relation_role', FALSE, array(
      'name' => 'admin',
    ));
    $member_role_entity = entity_load('redhen_relation_role', FALSE, array(
      'name' => 'member',
    ));
    $sandbox['replacement_values'] = array(
      0 => array_values($admin_role_entity),
      1 => array_values($member_role_entity),
    );
    $member_role_id = (int) array_shift($member_role_entity)->redhen_relation_role_id;
    foreach ($sandbox['old_instances'] as $entity_type => $bundles) {
      foreach ($bundles as $bundle) {
        $instance = array(
          'field_name' => REDHEN_RELATION_ROLES_FIELD,
          'entity_type' => $entity_type,
          'bundle' => $bundle,
          'label' => 'Organization Role',
          'description' => 'Select the roles this contact has in this organization.',
          'required' => 0,
          'default_value' => array(
            array(
              'target_id' => $member_role_id,
            ),
          ),
          'widget' => array(
            'type' => 'options_buttons',
          ),
        );
        field_create_instance($instance);
      }
    }
    entity_info_cache_clear();
    $sandbox['fields_processed'] = TRUE;
    $sandbox['#finished'] = $sandbox['count'] ? ($sandbox['save_progress'] + $sandbox['transfer_progress']) / (2 * $sandbox['count']) : 0;
    return t('Fields altered, resetting DB transaction: !progress% complete.', array(
      '!progress' => $sandbox['#finished'] * 100,
    ));
  }

  // Now that we have our new field definition, restore the old values:
  if (!empty($sandbox['old_values'])) {
    $allowance = $limit;
    while (!empty($sandbox['old_values'])) {
      if ($allowance < 1) {
        $sandbox['#finished'] = $sandbox['count'] ? ($sandbox['save_progress'] + $sandbox['transfer_progress']) / (2 * $sandbox['count']) : 0;
        return t('Moving old field values to new field definition: !progress% complete.', array(
          '!progress' => $sandbox['#finished'] * 100,
        ));
      }
      else {
        $allowance--;
        $sandbox['transfer_progress']++;
        $val = array_pop($sandbox['old_values']);
        $entity = entity_load_single($val['entity_type'], $val['id']);
        if ($entity) {
          $wrapper = entity_metadata_wrapper($val['entity_type'], $entity);
          if (isset($sandbox['replacement_values'][$val['value']])) {
            $wrapper->{REDHEN_RELATION_ROLES_FIELD} = $sandbox['replacement_values'][$val['value']];
            $wrapper
              ->save();
          }
        }
      }
    }
  }
  $sandbox['#finished'] = 1;
  return t('Relation update complete');
}

/**
 * Update affiliation and connection status field labels to Active.
 */
function redhen_relation_update_7102(&$sandbox) {
  $bundles = array(
    REDHEN_RELATION_AFFILIATION,
    REDHEN_RELATION_CONNECTION,
  );
  foreach ($bundles as $bundle) {
    $instance = field_info_instance('relation', REDHEN_RELATION_STATUS_FIELD, $bundle);
    $instance['label'] = 'Active';
    field_update_instance($instance);
  }
}

Functions

Namesort descending Description
redhen_relation_install Implements hook_install().
redhen_relation_schema Implements hook_schema().
redhen_relation_uninstall Implements hook_uninstall().
redhen_relation_update_7101 Remove old relation role field and add new, converting existing data.
redhen_relation_update_7102 Update affiliation and connection status field labels to Active.