Last active
April 2, 2024 19:23
-
-
Save helmo/e066bb696359311bf8b041b0db07b645 to your computer and use it in GitHub Desktop.
Convert Taiga json export to HTML and CSV
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env php | |
<?php | |
/** | |
* Taiga export processor - Covert json to csv. | |
* | |
* For each project you have to go to Settings -> Export and request an export in the Taiga web interface. | |
* Once you have the exported json-file this script can convert it to a simplified version. | |
* | |
* Usage: taiga-export.php <input json filename> <output csv filename> | |
*/ | |
$json_export = $argv[1] ?? ''; | |
$output_dir = $argv[2] ?? 'export'; | |
$attachment_dir = $argv[3] ?? 'attachments'; | |
$html_dir = 'html'; | |
if (empty($json_export)) { | |
echo "taiga-export.php <input json filename> <output dir> [attachment dir]" . PHP_EOL; | |
exit; | |
} | |
@mkdir($output_dir, 0755, $recursive = true); | |
@mkdir($output_dir . DIRECTORY_SEPARATOR . $attachment_dir, 0755, $recursive = true); | |
@mkdir($output_dir . DIRECTORY_SEPARATOR . $html_dir, 0755, $recursive = true); | |
$data = json_decode(file_get_contents($json_export)); | |
$i=1; | |
$limit = 999999999; | |
$index_html = '<html><body>'; | |
// Header | |
$index_html .= '<h1>User stories</h1>'; | |
$user_stories_list[] = ['id', 'subject', 'created_date', 'modified_date', 'status', 'swimlane', 'owner', 'attachments', 'is_closed', 'description', 'tags' ]; | |
foreach ($data->user_stories as $story) { | |
if ($i++ > $limit) { | |
break; | |
} | |
$text = ''; | |
$attachments = []; | |
if (!empty($story->attachments)) { | |
foreach ($story->attachments as $a) { | |
$attachments[$a->attached_file->name] = $attachment_dir . DIRECTORY_SEPARATOR . 'user_story-' . $story->ref . DIRECTORY_SEPARATOR . $a->attached_file->name; | |
@mkdir($output_dir . DIRECTORY_SEPARATOR . $attachment_dir . DIRECTORY_SEPARATOR . 'user_story-' . $story->ref); | |
file_put_contents($output_dir . DIRECTORY_SEPARATOR . $attachment_dir . DIRECTORY_SEPARATOR . 'user_story-' . $story->ref . DIRECTORY_SEPARATOR . $a->attached_file->name, base64_decode($a->attached_file->data)); | |
} | |
} | |
$user_stories_list[] = [ | |
$story->ref, | |
$story->subject, | |
$story->created_date, | |
$story->modified_date, | |
$story->status, | |
$story->swimlane, | |
$story->owner, | |
join("\n", $attachments), | |
$story->is_closed, | |
$story->description, | |
join("|",$story->tags), | |
]; | |
$text .= " | |
Reference: " . $story->ref . " | |
Subject: " . $story->subject . " | |
Create date: ". $story->created_date . " | |
Modify date: " . $story->modified_date . " | |
Status: " . $story->status . " | |
Swim lane: " . $story->swimlane . " | |
Owner: " . $story->owner . "\n"; | |
if ($story->is_closed) { | |
$text .= "is closed: Yes\n"; | |
} | |
$text .= "Description: " . $story->description . "\n"; | |
$text .= "Tags: " . join("|", $story->tags) . "\n"; | |
$text .= "Linked tasks:\n"; | |
foreach ($data->tasks as $id => $task) { | |
if ($task->user_story == $story->ref) { | |
$text .= "<li><a href='task-{$task->ref}.html'>{$task->ref}: {$task->subject}</a></li>\n"; | |
} | |
} | |
$text .= "\n"; | |
if (!empty($attachments)) { | |
$text .= "\nAttachments:\n "; | |
foreach($attachments as $name => $file) { | |
$text .= "<a href=\"../$file\">$name</a>\n"; | |
if (preg_match('/\.(jpg|png|gif)/', $name)) { | |
$text .= "<img src='../$file' />\n"; | |
} | |
} | |
} | |
$text .= "\n\n\n"; | |
$html = '<html> | |
<head> | |
<title>Taiga ID ' . $story->ref . '</title> | |
</head> | |
<body>' . nl2br($text) . '</body></html>'; | |
$html_filename = $html_dir . DIRECTORY_SEPARATOR . 'user_story-' . $story->ref . '.html'; | |
file_put_contents($output_dir . DIRECTORY_SEPARATOR . $html_filename, $html); | |
$index_html .= "<li><a href='$html_filename'>" . $story->ref . ': ' . $story->subject . '</a></li>'; | |
} | |
// Store user_stories CSV | |
$fp = fopen($output_dir . DIRECTORY_SEPARATOR . 'export-user_stories.csv', 'w'); | |
foreach ($user_stories_list as $fields) { | |
fputcsv($fp, $fields); | |
} | |
fclose($fp); | |
// Header | |
$index_html .= '<h1>Tasks</h1>'; | |
$task_list[] = ['id', 'subject', 'created_date', 'modified_date', 'status', 'owner', 'attachments', 'description', 'tags', 'user_story' ]; | |
foreach ($data->tasks as $id => $task) { | |
if ($i++ > $limit) { | |
break; | |
} | |
$text = ''; | |
$attachments = []; | |
if (!empty($task->attachments)) { | |
foreach ($task->attachments as $a) { | |
$attachments[$a->attached_file->name] = $attachment_dir . DIRECTORY_SEPARATOR . 'task-' . $task->ref . DIRECTORY_SEPARATOR . $a->attached_file->name; | |
@mkdir($output_dir . DIRECTORY_SEPARATOR . $attachment_dir . DIRECTORY_SEPARATOR . 'task-' . $task->ref); | |
file_put_contents($output_dir . DIRECTORY_SEPARATOR . $attachment_dir . DIRECTORY_SEPARATOR . 'task-' . $task->ref . DIRECTORY_SEPARATOR . $a->attached_file->name, base64_decode($a->attached_file->data)); | |
} | |
} | |
$task_list[] = [ | |
$task->ref, | |
$task->subject, | |
$task->created_date, | |
$task->modified_date, | |
$task->status, | |
$task->owner, | |
join("\n", $attachments), | |
$task->description, | |
join("|",$task->tags), | |
$task->user_story, | |
]; | |
$text .= " | |
Reference: " . $task->ref . " | |
Subject: " . $task->subject . " | |
Create date: ". $task->created_date . " | |
Modify date: " . $task->modified_date . " | |
Status: " . $task->status . " | |
Owner: " . $task->owner . "\n"; | |
$text .= "Description: " . $task->description . " | |
Tags: " . join("|", $task->tags) . "\n"; | |
$text .= "User story: <a href='user_story-{$task->user_story}.html'>{$task->user_story}</a>\n"; | |
$text .= "\n"; | |
if (!empty($attachments)) { | |
$text .= "\nAttachments:\n "; | |
foreach($attachments as $name => $file) { | |
$text .= "<a href=\"../$file\">$name</a>\n"; | |
if (preg_match('/\.(jpg|png|gif)/', $name)) { | |
$text .= "<img src='../$file' />\n"; | |
} | |
} | |
} | |
$text .= "\n\n\n"; | |
$html = '<html> | |
<head> | |
<title>Taiga ID ' . $task->ref . '</title> | |
</head> | |
<body>' . nl2br($text) . '</body></html>'; | |
$html_filename = $html_dir . DIRECTORY_SEPARATOR . 'task-' . $task->ref . '.html'; | |
file_put_contents($output_dir . DIRECTORY_SEPARATOR . $html_filename, $html); | |
$index_html .= "<li><a href='$html_filename'>" . $task->ref . ': ' . $task->subject . '</a></li>'; | |
} | |
$index_html .= '</body></html>'; | |
file_put_contents($output_dir . DIRECTORY_SEPARATOR . 'index.html', $index_html); | |
// Store task CSV | |
$fp = fopen($output_dir . DIRECTORY_SEPARATOR . 'export-tasks.csv', 'w'); | |
foreach ($task_list as $fields) { | |
fputcsv($fp, $fields); | |
} | |
fclose($fp); | |
echo "Export complete, stored in: $output_dir, attachments in $attachment_dir" . PHP_EOL; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment