Skip to content

Instantly share code, notes, and snippets.

@helmo
Last active April 2, 2024 19:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save helmo/e066bb696359311bf8b041b0db07b645 to your computer and use it in GitHub Desktop.
Save helmo/e066bb696359311bf8b041b0db07b645 to your computer and use it in GitHub Desktop.
Convert Taiga json export to HTML and CSV
#!/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