Commit f9eed82e authored by Marco Villegas's avatar Marco Villegas
Browse files

Issue #443000: Added a new module to store the relation between versioncontrol...

Issue #443000: Added a new module to store the relation between versioncontrol operations and project issues.

- Maintains the table with the relations.
- Implements hook_node_{update,delete}().
  hook_versioncontrol_entity_commit_delete() and
  hook_versioncontrol_repository_bypassing_purge() trying to keep data
  consistent.
- Adds the versioncontrol operation objects on the project issue nodes
  via hook_node_load().
parent b7679763
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
name = "Version Control / Project issue integration"
description = "Expose some functionality that integrates project_issue and Version Control API."
package = Version Control
dependencies[] = versioncontrol_project
dependencies[] = project_issue
core = 7.x
+32 −0
Original line number Diff line number Diff line
<?php
/**
 * @file
 * Version Control / Project issue integration
 */

/**
 * Implements hook_schema().
 */
function versioncontrol_project_issue_schema() {
  $schema['versioncontrol_project_issue_operations'] = array(
    'description' => 'This table associates project issue nodes with versioncontrol operations.',
    'fields' => array(
      'nid' => array(
        'description' => 'Foreign key for the project issue nid.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'vc_op_id' => array(
        'description' => 'Foreign key for the operation({versioncontrol_operations}.vc_op_id).',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'primary key' => array('nid', 'vc_op_id'),
  );
  return $schema;
}
+132 −0
Original line number Diff line number Diff line
<?php
/**
 * @file
 * Version Control / Project issue integration.
 */

/**
 * Implements hook_node_load().
 */
function versioncontrol_project_issue_node_load($nodes, $types) {
  $issue_node_types = project_issue_issue_node_types();
  $intersection = array_intersect($issue_node_types, $types);
  if (empty($intersection)) {
    // Nothing to do.
    return;
  }
  $vc_op_ids_by_nid = versioncontrol_project_issue_get_issue_operation_ids(array_keys($nodes));
  if (empty($vc_op_ids_by_nid)) {
    // Nothing to load.
    return;
  }
  foreach ($vc_op_ids_by_nid as $nid => $vc_op_ids) {
    $repository = versioncontrol_project_repository_load($nodes[$nid]->field_project[LANGUAGE_NONE][0]['target_id']);
    $nodes[$nid]->versioncontrol_project_issue['operations'] = $repository->loadCommits($vc_op_ids);
  }
}

/**
 * Implements hook_node_update().
 *
 * Change the mappings when a project issue is changed of project.
 */
function versioncontrol_project_issue_node_update($node) {
  if (!project_issue_node_type_is_issue($node->type)) {
    return;
  }
  $project_id = $node->field_project[LANGUAGE_NONE][0]['target_id'];
  $original_project_id = $node->original->field_project[LANGUAGE_NONE][0]['target_id'];
  if ($original_project_id == $project_id) {
    // Nothing to do.
    return;
  }
  // Project was changed, remove operation associations with the issue.
  db_delete('versioncontrol_project_issue_operations')->condition('nid', $node->nid)->execute();
  // @todo Search all operations associated with the new project? (if decided,
  // use a queue, since it can be time consuming).
}

/**
 * Implements hook_node_delete().
 */
function versioncontrol_project_issue_node_delete($node) {
  if (!project_issue_node_is_issue($node)) {
    // Nothing to do.
    return;
  }
  // Remove mappings on delete.
  db_delete('versioncontrol_project_issue_operations')->condition('nid', $node->nid)->execute();
}

/**
 * Implements hook_versioncontrol_entity_commit_delete().
 *
 * Repository synchronization removes commits, event processor plugins are
 * executed later, so we cannot react at that time. So we use this hook to
 * remove relations from our table.
 */
function versioncontrol_project_issue_versioncontrol_entity_commit_delete(VersioncontrolOperation $operation) {
  db_delete('versioncontrol_project_issue_operations')->condition('vc_op_id', $operation->vc_op_id)->execute();
}

/**
 * Implements hook_versioncontrol_repository_bypassing_purge().
 *
 * @todo db_delete seems to not support joins, is that possible to use for the
 * generic case? i.e. no mysql(should be more efficient, in case a lot of
 * issues are associated).
 */
function versioncontrol_project_issue_versioncontrol_repository_bypassing_purge(VersioncontrolRepository $repository) {
  versioncontrol_project_issue_delete_issue_operation_maps($repository);
}

/**
 * Deletes all relared issue/operation associations.
 *
 * @param int|VersioncontrolRepository $repository
 *   Repository object or its repo_id.
 */
function versioncontrol_project_issue_delete_issue_operation_maps($repository) {
  if (!$repository instanceof VersioncontrolRepository) {
    // Should be a repo_id.
    $repository = versioncontrol_repository_load($repository);
  }
  if (empty($repository->project_nid)) {
    // No project associated.
    return;
  }
  // Load all associated project issue nids.
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', project_issue_issue_node_types())
    ->fieldCondition('field_project', 'target_id', $repository->project_nid);
  $result = $query->execute();
  if (empty($result['node'])) {
    // No issues associated.
    return;
  }
  // Remove related rows from versioncontrol_project_issue_operations table.
  $issue_nids = array_keys($result['node']);
  // Do it in chunks of 500 items.
  foreach (array_chunk($issue_nids, 500) as $chunk) {
    db_delete('versioncontrol_project_issue_operations')->condition('nid', array_values($chunk), 'IN')->execute();
  }
}

/**
 * Helper to get the operation IDs.
 *
 * @param array $project_issue_nids
 *   List of project issue nids.
 *
 * @return array
 *   List of operation ids keyed by project issue node id.
 */
function versioncontrol_project_issue_get_issue_operation_ids($project_issue_nids) {
  $vc_op_ids = array();
  $result = db_query('SELECT nid, vc_op_id FROM {versioncontrol_project_issue_operations} WHERE nid IN (:nids)', array(':nids' => $project_issue_nids));
  foreach ($result as $row) {
    $vc_op_ids[$row->nid][] = $row->vc_op_id;
  }
  return $vc_op_ids;
}