Skip to content

Instantly share code, notes, and snippets.

@GregPK
Forked from AWeg/CopyAsanaTasks.php
Last active December 22, 2015 08:49
Show Gist options
  • Save GregPK/6447781 to your computer and use it in GitHub Desktop.
Save GregPK/6447781 to your computer and use it in GitHub Desktop.
This utility class allows you to copy projects from one workspace in Asana to another. Shortcomings: * any tasks that have been set up as recurring will not preserve that setting (a limitation of the Asana API)
<?php
class CopyAsanaWorkspace
{
public $apiKey; /// Get it from http://app.asana.com/-/account_api
public $indentationLevel = 0;
public $verbose = true;
private $projectFields = array('name','color','notes');
public function __construct($apiKey) {
$this->apiKey = $apiKey;
}
function copyProjects($srcWorkspaceID,$targetWorkspaceID) {
$projectsResponse = $this->asanaRequest("workspaces/$srcWorkspaceID/projects",'GET',null,$this->projectFields);
$projects = $projectsResponse['data'];
$this->debug("Found ".count($projects)." projects in source workspace");
foreach ($projects as $project) {
$this->levelDown();
$newProj = $this->createProject($targetWorkspaceID,$project);
if ($newProj) {
$this->debug("Created new project with id=[{$newProj['id']}], starting to copy tasks...");
$this->copyTasks($project['id'],$newProj['id']);
}
else {
$this->debug("Failed to create project");
}
$this->levelUp();
}
}
public function createProject($targetWorkspaceID, $data) {
$this->debug("Creating new project with name: {$data['name']}");
unset($data['id']);
$data = array("data"=>$data);
$projectsResponse = $this->asanaRequest("workspaces/$targetWorkspaceID/projects",'POST',$data);
return $projectsResponse['data'];
}
public function asanaRequest($methodPath, $httpMethod = 'GET', $body = null, $fields = null)
{
$url = "https://app.asana.com/api/1.0/$methodPath";
if (is_array($fields)) {
$url .= "?opt_fields=".implode(',',$fields);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ;
curl_setopt($ch, CURLOPT_USERPWD, $this->apiKey);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $httpMethod);
// SSL cert of Asana is selfmade
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
if ($body)
{
if (!is_string($body))
{
$body = json_encode($body);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$data = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
$result = json_decode($data, true);
return $result;
}
function createTask($workspaceId, $projectId, $task)
{
$this->levelDown();
$this->debug("Creating new task");
$data = array('data' => $task);
$result = $this->asanaRequest("workspaces/$workspaceId/tasks", 'POST', $data);
if ($result['data'])
{
$newTask = $result['data'];
$newTaskId = $newTask['id'];
$data = array('data' => array('project' => $projectId));
$result = $this->asanaRequest("tasks/$newTaskId/addProject", 'POST', $data);
$this->levelUp();
return $newTask;
}
$this->levelUp();
return $result;
}
function copySubtasks($taskId, $newTaskId, $failsafe) {
$this->levelDown();
$this->debug("Copying subtasks from $taskId to $newTaskId");
$failsafe++;
if ($failsafe > 10) {
$this->error("Copy aborting because of exceeding 10 levels of nesting");
return FALSE;
}
// GET subtasks of task
$result = $this->asanaRequest("tasks/$taskId/subtasks");
$subtasks = $result["data"];
if ($subtasks){ // does subtask exist?
for ($i= count($subtasks) - 1; $i >= 0; $i--) {
$subtask = $subtasks[$i];
$subtaskId = $subtask['id'];
// get data for subtask
$result = $this->asanaRequest("tasks/$subtaskId?opt_fields=name,due_on,assignee_status,notes,assignee");
$newSubtask = $result['data'];
unset($newSubtask["id"]);
$newSubtask["assignee"] = $newSubtask["assignee"]["id"];
// create Subtask
$data = array('data' => $newSubtask );
$result = $this->asanaRequest("tasks/$newTaskId/subtasks", 'POST', $data);
// add History
$newSubId = $result["data"]["id"];
$this->copyHistory($subtaskId, $newSubId);
// subtask of subtask?
$this->copySubtasks($subtaskId, $result["data"]["id"], $failsafe);
}
}
$this->levelUp();
}
function copyHistory($taskId, $newTaskId) {
$this->levelDown();
$this->debug("Copying task history");
$result = $this->asanaRequest("tasks/$taskId/stories");
$comments = array();
foreach ($result['data'] as $story){
$date = date('l M d, Y h:i A', strtotime($story['created_at']));
$comment = " ­\n" . $story['created_by']['name'] . ' on ' . $date . ":\n" . $story['text'];
$comments[] = $comment;
}
$comment = implode("\n----------------------", $comments);
$data = array('data' => array('text' => $comment));
$result = $this->asanaRequest("tasks/$newTaskId/stories", 'POST', $data);
$this->levelUp();
}
function copyTags($taskId, $newTaskId, $newworkspaceId) {
$this->levelDown();
$this->debug("Copying tags");
// GET Tags
$result = $this->asanaRequest("tasks/$taskId/tags");
if($result["data"]){ // are there any tags?
$tags = $result["data"];
for ($i = count ($tags) - 1; $i >= 0; $i--) {
$tag = $tags[$i];
$tagName = $tag["name"];
// does tag exist?
$result = $this->asanaRequest("workspaces/$newworkspaceId/tags");
$tagisset = false;
$existingtags = $result["data"];
for($j = count($existingtags) - 1; $j >= 0; $j--) {
$existingtag = $existingtags[$j];
if ($tagName == $existingtag["name"]) {
$tagisset = true;
$tagId = $existingtag["id"];
break;
}
}
if (!$tagisset) {
$this->debug("tag does not exist in workspace");
$data = array('data' => array('name' => $tagName));
$result = $this->asanaRequest("workspaces/$newworkspaceId/tags", "POST", $data);
$tagId = $result["data"]["id"];
}
$data = array("data" => array("tag" => $tagId));
$result = $this->asanaRequest("tasks/$newTaskId/addTag", "POST", $data);
}
}
$this->levelUp();
}
function createTag($tagName, $workspaceId, $newTaskId) {
$data = array('data' => array('name' => $tagName));
$result = $this->asanaRequest("workspaces/$workspaceId/tags", "POST", $data);
$data = array("data" => array("tag" => $result["data"]["id"]));
$result = $this->asanaRequest("tasks/$newTaskId/addTag", "POST", $data);
}
function copyTasks($fromProjectId, $toProjectId)
{
$this->levelDown();
$result = $this->asanaRequest("projects/$toProjectId");
if (!$result['data'])
{
$this->error("Error Loading Project!");
return;
}
$workspaceId = $result['data']['workspace']['id'];
// GET Project tasks
$result = $this->asanaRequest("projects/$fromProjectId/tasks?opt_fields=name,due_on,assignee_status,notes,assignee");
$tasks = $result['data'];
// copy Tasks
for ($i = count($tasks) - 1; $i >= 0; $i--)
{
$task = $tasks[$i];
$newTask = $task;
unset($newTask['id']);
$newTask['assignee'] = $newTask['assignee']['id'];
foreach ($newTask as $key => $value)
{
if (empty($value))
{
unset($newTask[$key]);
}
}
$this->debug("Copying task [{$task['name']}");
$newTask = $this->createTask($workspaceId, $toProjectId, $newTask);
if ($newTask['id'])
{
//copy history
$taskId = $task['id'];
$newTaskId = $newTask['id'];
$this->copyHistory($taskId, $newTaskId);
//copy tags
$this->copyTags($taskId, $newTaskId, $workspaceId);
//implement copying of subtasks
$failsafe = 0;
$this->copySubtasks($taskId, $newTaskId, $failsafe);
}
}
$this->levelUp();
}
protected function levelUp() {
$this->indentationLevel--;
}
protected function levelDown() {
$this->indentationLevel++;
}
protected function debug($msg) {
if ($this->verbose) $this->msg($msg);
}
protected function error($msg) {
$this->msg($msg);
}
protected function msg($msg) {
echo str_repeat(" ",$this->indentationLevel). "$msg\n";
}
}
@libswan
Copy link

libswan commented Dec 26, 2013

How does one implement this exactly? I tried running it on a local server using WAMP. I'm guessing I need to upload it to a web server and run it there...right? #Learning

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment