From e952740429a842aa2666d9519d0d1d76fdad3a55 Mon Sep 17 00:00:00 2001
From: Marco Villegas <marvil07@gmail.com>
Date: Wed, 14 Nov 2012 00:54:22 -0500
Subject: [PATCH] Issue #1020220 by marvil07, cvangysel: Reintroduced token
 integration.

Original code from cvangysel gsoc-activity D6 topic branch, then
rewriten(ported and extended token integration and its tests) by
marvil07 for D7 port.

This now includes chained tokens for relevant token types.
---
 tests/VersioncontrolTokenTests.test |  142 ++++++++++++
 versioncontrol.info                 |    1 +
 versioncontrol.tokens.inc           |  405 +++++++++++++++++++++++++++++++++++
 3 files changed, 548 insertions(+)
 create mode 100644 tests/VersioncontrolTokenTests.test
 create mode 100644 versioncontrol.tokens.inc

diff --git a/tests/VersioncontrolTokenTests.test b/tests/VersioncontrolTokenTests.test
new file mode 100644
index 0000000..66bfe2b
--- /dev/null
+++ b/tests/VersioncontrolTokenTests.test
@@ -0,0 +1,142 @@
+<?php
+/**
+ * @file
+ *   Tests ensuring proper behavior of the integration with Token.
+ *
+ *   @todo test when sanitized option is passed
+ *   @todo test chained tokens
+ */
+require_once drupal_get_path('module', 'versioncontrol') . '/tests/VersioncontrolTestCase.test';
+
+class VersioncontrolTokenTests extends VersioncontrolTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => t('Token integration tests'),
+      'description' => t('Tests on Token integration.'),
+      'group' => t('Version Control API'),
+    );
+  }
+
+  function setUp() {
+    $this->useBackends = self::BACKENDS_ALL;
+    parent::setUp();
+  }
+
+  function testVersioncontrolBackendTokens() {
+    $object = $this->testBackend;
+    $tokens = array(
+      '[VersioncontrolBackend:name]' => $object->name,
+      '[VersioncontrolBackend:type]' => $object->type,
+      '[VersioncontrolBackend:description]' => $object->description,
+    );
+    // Test to make sure that we generated something for each token.
+    $this->assertFalse(in_array(0, array_map('strlen', $tokens)), t('No empty tokens generated.'));
+    foreach ($tokens as $name => $value) {
+      $render = token_replace($name, array('VersioncontrolBackend' => $object));
+      $this->assertEqual($render, $value, t('Token %name generated correctly.', array('%name' => $name)));
+    }
+  }
+
+  function testVersioncontrolRepositoryTokens() {
+    $object = $this->versioncontrolCreateRepository();
+    $viewer_url = l($object->name, $object->getUrlHandler()->getRepositoryViewUrl());
+    $tokens = array(
+      '[VersioncontrolRepository:id]' => $object->repo_id,
+      '[VersioncontrolRepository:name]' => $object->name,
+      '[VersioncontrolRepository:backend]' => $object->vcs,
+      '[VersioncontrolRepository:viewer]' => $viewer_url,
+    );
+    // Test to make sure that we generated something for each token.
+    $this->assertFalse(in_array(0, array_map('strlen', $tokens)), t('No empty tokens generated.'));
+    foreach ($tokens as $name => $value) {
+      $render = token_replace($name, array('VersioncontrolRepository' => $object));
+      $this->assertEqual($render, $value, t('Token %name generated correctly.', array('%name' => $name)));
+    }
+  }
+
+  function testVersioncontrolOperationTokens() {
+    $object = $this->versioncontrolCreateOperation();
+    $tokens = array(
+      '[VersioncontrolOperation:id]' => $object->vc_op_id,
+      '[VersioncontrolOperation:revision]' => $object->revision,
+      '[VersioncontrolOperation:author_date]' => format_date($object->author_date, 'medium'),
+      '[VersioncontrolOperation:committer_date]' => format_date($object->committer_date, 'medium'),
+      '[VersioncontrolOperation:author]' => $object->author,
+      '[VersioncontrolOperation:committer]' => $object->committer,
+      '[VersioncontrolOperation:message]' => check_plain($object->message),
+    );
+    // Test to make sure that we generated something for each token.
+    $this->assertFalse(in_array(0, array_map('strlen', $tokens)), t('No empty tokens generated.'));
+    foreach ($tokens as $name => $value) {
+      $render = token_replace($name, array('VersioncontrolOperation' => $object));
+      $this->assertEqual($render, $value, t('Token %name generated correctly.', array('%name' => $name)));
+    }
+  }
+
+  function testVersioncontrolBranchTokens() {
+    $object = $this->versioncontrolCreateBranch();
+    $tokens = array(
+      '[VersioncontrolBranch:id]' => $object->label_id,
+      '[VersioncontrolBranch:name]' => $object->name,
+    );
+    // Test to make sure that we generated something for each token.
+    $this->assertFalse(in_array(0, array_map('strlen', $tokens)), t('No empty tokens generated.'));
+    foreach ($tokens as $name => $value) {
+      $render = token_replace($name, array('VersioncontrolBranch' => $object));
+      $this->assertEqual($render, $value, t('Token %name generated correctly.', array('%name' => $name)));
+    }
+  }
+
+  function testVersioncontrolTagTokens() {
+    $object = $this->versioncontrolCreateTag();
+    $tokens = array(
+      '[VersioncontrolTag:id]' => $object->label_id,
+      '[VersioncontrolTag:name]' => $object->name,
+    );
+    // Test to make sure that we generated something for each token.
+    $this->assertFalse(in_array(0, array_map('strlen', $tokens)), t('No empty tokens generated.'));
+    foreach ($tokens as $name => $value) {
+      $render = token_replace($name, array('VersioncontrolTag' => $object));
+      $this->assertEqual($render, $value, t('Token %name generated correctly.', array('%name' => $name)));
+    }
+  }
+
+  function testVersioncontrolItemTokens() {
+    $object = $this->versioncontrolCreateItem();
+    $action_strings = versioncontrol_revision_actions();
+    $tokens = array(
+      '[VersioncontrolItem:id]' => $object->item_revision_id,
+      '[VersioncontrolItem:operation]' => $object->vc_op_id,
+      '[VersioncontrolItem:repository]' => $object->repo_id,
+      '[VersioncontrolItem:path]' => $object->path,
+      '[VersioncontrolItem:revision]' => $object->revision,
+      '[VersioncontrolItem:source_item]' => $object->source_item_revision_id,
+      '[VersioncontrolItem:action]' => $action_strings[$object->action],
+      '[VersioncontrolItem:line_changes_added]' => $object->line_changes_added,
+      '[VersioncontrolItem:line_changes_removed]' => $object->line_changes_removed,
+    );
+    // Test to make sure that we generated something for each token.
+    $this->assertFalse(in_array(0, array_map('strlen', $tokens)), t('No empty tokens generated.'));
+    foreach ($tokens as $name => $value) {
+      $render = token_replace($name, array('VersioncontrolItem' => $object));
+      $this->assertEqual($render, $value, t('Token %name generated correctly.', array('%name' => $name)));
+    }
+  }
+
+  function testVersioncontrolEventTokens() {
+    $object = $this->versioncontrolCreateEvent();
+    $tokens = array(
+      '[VersioncontrolEvent:id]' => $object->elid,
+      '[VersioncontrolEvent:repository]' => $object->repo_id,
+      '[VersioncontrolEvent:date]' => format_date($object->timestamp, 'medium'),
+      '[VersioncontrolEvent:actor]' => $object->uid,
+    );
+    // Test to make sure that we generated something for each token.
+    $this->assertFalse(in_array(0, array_map('strlen', $tokens)), t('No empty tokens generated.'));
+    foreach ($tokens as $name => $value) {
+      $render = token_replace($name, array('VersioncontrolEvent' => $object));
+      $this->assertEqual($render, $value, t('Token %name generated correctly.', array('%name' => $name)));
+    }
+  }
+}
diff --git a/versioncontrol.info b/versioncontrol.info
index 204150c..cce963f 100644
--- a/versioncontrol.info
+++ b/versioncontrol.info
@@ -52,3 +52,4 @@ files[] = tests/VersioncontrolRepositoryManagementTestCase.test
 files[] = tests/VersioncontrolRepositoryUnitTestingTestCase.test
 files[] = tests/VersioncontrolTagUnitTestingTestCase.test
 files[] = tests/VersioncontrolTestCase.test
+files[] = tests/VersioncontrolTokenTests.test
diff --git a/versioncontrol.tokens.inc b/versioncontrol.tokens.inc
new file mode 100644
index 0000000..a12e3cb
--- /dev/null
+++ b/versioncontrol.tokens.inc
@@ -0,0 +1,405 @@
+<?php
+/**
+ * @file
+ *   Token integration.
+ */
+
+/**
+ * Implements hook_token_info().
+ */
+function versioncontrol_token_info() {
+  $info = array();
+
+  // Backend.
+  $info['types']['VersioncontrolBackend'] = array(
+    'name' => t('Version Control Backend'),
+    'description' => t('Tokens related to backends.'),
+    'needs-data' => 'VersioncontrolBackend',
+  );
+  $info['tokens']['VersioncontrolBackend'] = array(
+    'name' => array(
+      'name'=> t('Backend name'),
+      'description' => t('The name of the backend'),
+    ),
+    'type' => array(
+      'name'=> t('Backend machine name'),
+      'description' => t('The type of the backend'),
+    ),
+    'description' => array(
+      'name'=> t('Backend description'),
+      'description' => t('The description of the backend'),
+    ),
+  );
+
+  // Repository.
+  $info['types']['VersioncontrolRepository'] = array(
+    'name' => t('Version Control Repository'),
+    'description' => t('Tokens related to repositories.'),
+    'needs-data' => 'VersioncontrolRepository',
+  );
+  $info['tokens']['VersioncontrolRepository'] = array(
+    'id' => array(
+      'name'=> t('Repository ID'),
+      'description' => t('The unique identifier for the repository.'),
+    ),
+    'name' => array(
+      'name'=> t('Repository name'),
+      'description' => t('User visible name of the repository.'),
+    ),
+    'backend' => array(
+      'name'=> t('Repository backend machine name'),
+      'description' => t('The backend machine name this repository uses.'),
+      'type' => 'VersioncontrolBackend',
+    ),
+    'viewer' => array(
+      'name'=> t('Repository viewer url.'),
+      'description' => t('A link to the web viewer associated with this repository.'),
+    ),
+  );
+
+  // Operation.
+  $info['types']['VersioncontrolOperation'] = array(
+    'name' => t('Version Control Operation'),
+    'description' => t('Tokens related to operations.'),
+    'needs-data' => 'VersioncontrolOperation',
+  );
+  $info['tokens']['VersioncontrolOperation'] = array(
+    'id' => array(
+      'name' => t('Operation ID'),
+      'description' => t('The unique identifier for the operation.'),
+    ),
+    'repository' => array(
+      'name' => t('Operation repository ID'),
+      'description' => t('The unique identifier for the repository this operation belongs to.'),
+      'type' => 'VersioncontrolRepository',
+    ),
+    'revision' => array(
+      'name' => t('Operation revision'),
+      'description' => t('Backend internal identifier for the operation.'),
+    ),
+    'author_date' => array(
+      'name' => t('Authored date'),
+      'description' => 'Date/time when the operation was created.',
+      'type' => 'date',
+    ),
+    'committer_date' => array(
+      'name' => t('Committed date'),
+      'description' => 'Date/time when the operation was added to the repository.',
+      'type' => 'date',
+    ),
+    'author' => array(
+      'name' => t('Author'),
+      'description' => 'VCS specific username of the user who is the original author of this operation.',
+      'type' => 'user',
+    ),
+    'committer' => array(
+      'name' => t('Committer'),
+      'description' => 'VCS specific username of the user who is the original committer of this operation.',
+      'type' => 'user',
+    ),
+    'message' => array(
+      'name' => t('Commit message'),
+      'description' => 'Log message from VCS for this operation.',
+    ),
+  );
+
+  // Branch.
+  $info['types']['VersioncontrolBranch'] = array(
+    'name' => t('Version Control Branch'),
+    'description' => t('Tokens related to branches.'),
+    'needs-data' => 'VersioncontrolBranch',
+  );
+  $info['tokens']['VersioncontrolBranch'] = array(
+    'id' => array(
+      'name' => t('Branch ID'),
+      'description' => t('The unique identifier for the branch.'),
+    ),
+    'name' => array(
+      'name' => t('Branch name'),
+      'description' => t('The name of the branch.'),
+    ),
+    'repository' => array(
+      'name' => t('Branch repository ID'),
+      'description' => t('The unique identifier for the repository this branch belongs to.'),
+      'type' => 'VersioncontrolRepository',
+    ),
+  );
+
+  // Tag.
+  $info['types']['VersioncontrolTag'] = array(
+    'name' => t('Version Control Tag'),
+    'description' => t('Tokens related to tags.'),
+    'needs-data' => 'VersioncontrolTag',
+  );
+  $info['tokens']['VersioncontrolTag'] = array(
+    'id' => array(
+      'name' => t('Tag ID'),
+      'description' => t('The unique identifier for the tag.'),
+    ),
+    'name' => array(
+      'name' => t('Tag name'),
+      'description' => t('The name of the tag.'),
+    ),
+    'repository' => array(
+      'name' => t('Tag repository ID'),
+      'description' => t('The unique identifier for the repository this tag belongs to.'),
+      'type' => 'VersioncontrolRepository',
+    ),
+  );
+
+  // Item revision.
+  $info['types']['VersioncontrolItem'] = array(
+    'name' => t('Version Control Item'),
+    'description' => t('Tokens related to item revisions.'),
+    'needs-data' => 'VersioncontrolItem',
+  );
+  $info['tokens']['VersioncontrolItem'] = array(
+    'id' => array(
+      'name' => t('Item revision ID'),
+      'description' => t('The unique identifier for the item revision.'),
+    ),
+    'operation' => array(
+      'name' => t('Item revision operation ID'),
+      'description' => t('The unique identifier for the operation this item revision belongs to.'),
+      'type' => 'VersioncontrolOperation',
+    ),
+    'repository' => array(
+      'name' => t('Item revision repository ID'),
+      'description' => t('The unique identifier for the repository this item revision belongs to.'),
+      'type' => 'VersioncontrolRepository',
+    ),
+    'path' => array(
+      'name' => t('Item revision path'),
+      'description' => t('Path of the item revision, relative to the repository root.'),
+    ),
+    'revision' => array(
+      'name' => t('Item revision revision'),
+      'description' => t('File-level revision of the item.'),
+    ),
+    // @todo type
+    'source_item' => array(
+      'name' => t('Item revision type'),
+      'description' => t('File-level revision of the item.'),
+      'type' => 'VersioncontrolItem',
+    ),
+    'action' => array(
+      'name' => t('Item revision action'),
+      'description' => t('Action that was performed while transforming the source item into the successor item.'),
+    ),
+    'line_changes_added' => array(
+      'name' => t('Item revision added lines count'),
+      'description' => t('Number of lines added with this item.'),
+    ),
+    'line_changes_removed' => array(
+      'name' => t('Item revision removed lines count'),
+      'description' => t('Number of lines removed with this item.'),
+    ),
+  );
+
+  // Event.
+  $info['types']['VersioncontrolEvent'] = array(
+    'name' => t('Version Control Event'),
+    'description' => t('Tokens related to events.'),
+    'needs-data' => 'VersioncontrolEvent',
+  );
+  $info['tokens']['VersioncontrolEvent'] = array(
+    'id' => array(
+      'name' => t('Event ID'),
+      'description' => t('The unique identifier for the event.'),
+    ),
+    'repository' => array(
+      'name' => t('Event repository ID'),
+      'description' => t('The unique identifier for the repository this event belongs to.'),
+      'type' => 'VersioncontrolRepository',
+    ),
+    'actor' => array(
+      'name' => t('Event actor user ID'),
+      'description' => t('The unique identifier for the user who performed this event.'),
+      'type' => 'user',
+    ),
+    'date' => array(
+      'name' => t('Event date'),
+      'description' => 'Date/time when the event happened.',
+      'type' => 'date',
+    ),
+  );
+
+  return $info;
+}
+
+/**
+ * Implements hook_tokens().
+ */
+function versioncontrol_tokens($type, $tokens, array $data = array(), array $options = array()) {
+  $replacements = array();
+  $sanitize = !empty($options['sanitize']);
+  $language_code = isset($options['language']) ? $options['language']->language : NULL;
+
+  if (empty($data[$type])) {
+    return $replacements;
+  }
+  $object = $data[$type];
+
+  foreach ($tokens as $name => $original) {
+    switch ($type) {
+      case 'VersioncontrolBackend':
+        switch ($name) {
+          case 'name':
+          case 'type':
+          case 'description':
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+        }
+        break;
+      case 'VersioncontrolRepository':
+        switch ($name) {
+          case 'viewer':
+            $replacements[$original] = l($object->name, $object->getUrlHandler()->getRepositoryViewUrl());
+            break;
+          case 'backend':
+            $name = 'vcs';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+          case 'id':
+            $name = 'repo_id';
+          case 'name':
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+        }
+        if ($backend_tokens = token_find_with_prefix($tokens, 'backend')) {
+          $backend = $object->getBackend();
+          $replacements += token_generate('VersioncontrolBackend', $backend_tokens, array('VersioncontrolBackend' => $backend), $options);
+        }
+        break;
+      case 'VersioncontrolOperation':
+        switch ($name) {
+          case 'type':
+            $operation_types = versioncontrol_operation_types();
+            $replacements[$original] = $operation_types[$object->type];
+            break;
+          case 'author_date':
+          case 'committer_date':
+            $replacements[$original] = format_date($object->$name, 'medium', '', NULL, $language_code);
+            break;
+          case 'repository':
+            $name = 'repo_id';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+          case 'id':
+            $name = 'vc_op_id';
+          case 'revision':
+          case 'author':
+          case 'committer':
+          case 'message':
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+        }
+        if ($author_date_tokens = token_find_with_prefix($tokens, 'author_date')) {
+          $replacements += token_generate('date', $author_date_tokens, array('date' => $object->author_date), $options);
+        }
+        if ($committer_date_tokens = token_find_with_prefix($tokens, 'committer_date')) {
+          $replacements += token_generate('date', $committer_date_tokens, array('date' => $object->committer_date), $options);
+        }
+        if ($author_tokens = token_find_with_prefix($tokens, 'author')) {
+          $author = user_load($object->author_uid);
+          $replacements += token_generate('user', $author_tokens, array('user' => $author), $options);
+        }
+        if ($committer_tokens = token_find_with_prefix($tokens, 'committer')) {
+          $committer = user_load($object->committer_uid);
+          $replacements += token_generate('user', $author_tokens, array('user' => $committer), $options);
+        }
+        if ($repository_tokens = token_find_with_prefix($tokens, 'repository')) {
+          //$repository = $object->getRepository();
+          $repository = versioncontrol_repository_load($object->repo_id);
+          $replacements += token_generate('VersioncontrolRepository', $repository_tokens, array('VersioncontrolRepository' => $repository), $options);
+        }
+        break;
+      case 'VersioncontrolBranch':
+      case 'VersioncontrolTag':
+        switch ($name) {
+          case 'repository':
+            $name = 'repo_id';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+          case 'id':
+            $name = 'label_id';
+          case 'name':
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+        }
+        if ($repository_tokens = token_find_with_prefix($tokens, 'repository')) {
+          $repository = $object->getRepository();
+          $replacements += token_generate('VersioncontrolRepository', $repository_tokens, array('VersioncontrolRepository' => $repository), $options);
+        }
+        break;
+      case 'VersioncontrolItem':
+        switch ($name) {
+          case 'repository':
+            $name = 'repo_id';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+          case 'operation':
+            $name = 'vc_op_id';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+          case 'action':
+            $item_revision_actions = versioncontrol_revision_actions();
+            $replacements[$original] = $item_revision_actions[$object->action];
+            break;
+          case 'source_item':
+            $name = 'source_item_revision_id';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+          //@todo add a successor_item if possible
+          case 'id':
+            $name = 'item_revision_id';
+          case 'path':
+          case 'revision':
+          case 'line_changes_added':
+          case 'line_changes_removed':
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+        }
+        if ($repository_tokens = token_find_with_prefix($tokens, 'repository')) {
+          $repository = $object->getRepository();
+          $replacements += token_generate('VersioncontrolRepository', $repository_tokens, array('VersioncontrolRepository' => $repository), $options);
+        }
+        if ($operation_tokens = token_find_with_prefix($tokens, 'operation')) {
+          $operation = $object->getBackend()->loadEntity('operation', array($object->vc_op_id));
+          $replacements += token_generate('VersioncontrolOperation', $operation_tokens, array('VersioncontrolOperation' => $operation), $options);
+        }
+        if ($source_item_tokens = token_find_with_prefix($tokens, 'source_item')) {
+          $source_item = $object->getSourceItem();
+          $replacements += token_generate('VersioncontrolItem', $source_item_tokens, array('VersioncontrolItem' => $source_item), $options);
+        }
+        break;
+      case 'VersioncontrolEvent':
+        switch ($name) {
+          case 'repository':
+            $name = 'repo_id';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+          case 'date':
+            $replacements[$original] = format_date($object->timestamp, 'medium', '', NULL, $language_code);
+            break;
+          case 'id':
+            $name = 'elid';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+          case 'actor':
+            $name = 'uid';
+            $replacements[$original] = $sanitize ? check_plain($object->$name) : $object->$name;
+            break;
+        }
+        if ($repository_tokens = token_find_with_prefix($tokens, 'repository')) {
+          $repository = $object->getRepository();
+          $replacements += token_generate('VersioncontrolRepository', $repository_tokens, array('VersioncontrolRepository' => $repository), $options);
+        }
+        if ($date_tokens = token_find_with_prefix($tokens, 'date')) {
+          $replacements += token_generate('date', $date_tokens, array('date' => $object->timestamp), $options);
+        }
+        if ($actor_tokens = token_find_with_prefix($tokens, 'actor')) {
+          $actor = user_load($object->uid);
+          $replacements += token_generate('user', $actor_tokens, array('user' => $actor), $options);
+        }
+        break;
+    }
+  }
+
+  return $replacements;
+}
-- 
1.7.10.4

