From 8ba593b3f3a44bc5115e26d9c8f1a7c2c6651fdf Mon Sep 17 00:00:00 2001 From: James Rhodes Date: Thu, 11 Apr 2013 11:22:06 -0700 Subject: [PATCH] Implemented support for different export formats. Summary: This adds support for different export formats to Excel via a drop-down on the Export page as per the discussion in D5443. Test Plan: Export some things from Maniphest. Do a simple implementation of ManiphestExcelFormat just for testing and make sure that it appears in the list after you run `arc liberate`. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T2575 Differential Revision: https://secure.phabricator.com/D5642 Conflicts: src/applications/maniphest/controller/ManiphestExportController.php --- src/__phutil_library_map__.php | 3 + .../controller/ManiphestExportController.php | 142 +++--------------- .../export/ManiphestExcelDefaultFormat.php | 142 ++++++++++++++++++ .../maniphest/export/ManiphestExcelFormat.php | 47 ++++++ 4 files changed, 214 insertions(+), 120 deletions(-) create mode 100644 src/applications/maniphest/export/ManiphestExcelDefaultFormat.php create mode 100644 src/applications/maniphest/export/ManiphestExcelFormat.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index aa140b1280..a0d589d85c 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -621,6 +621,8 @@ phutil_register_library_map(array( 'ManiphestDAO' => 'applications/maniphest/storage/ManiphestDAO.php', 'ManiphestDefaultTaskExtensions' => 'applications/maniphest/extensions/ManiphestDefaultTaskExtensions.php', 'ManiphestEdgeEventListener' => 'applications/maniphest/event/ManiphestEdgeEventListener.php', + 'ManiphestExcelDefaultFormat' => 'applications/maniphest/export/ManiphestExcelDefaultFormat.php', + 'ManiphestExcelFormat' => 'applications/maniphest/export/ManiphestExcelFormat.php', 'ManiphestExportController' => 'applications/maniphest/controller/ManiphestExportController.php', 'ManiphestHovercardEventListener' => 'applications/maniphest/event/ManiphestHovercardEventListener.php', 'ManiphestPeopleMenuEventListener' => 'applications/maniphest/event/ManiphestPeopleMenuEventListener.php', @@ -2302,6 +2304,7 @@ phutil_register_library_map(array( 'ManiphestDAO' => 'PhabricatorLiskDAO', 'ManiphestDefaultTaskExtensions' => 'ManiphestTaskExtensions', 'ManiphestEdgeEventListener' => 'PhutilEventListener', + 'ManiphestExcelDefaultFormat' => 'ManiphestExcelFormat', 'ManiphestExportController' => 'ManiphestController', 'ManiphestHovercardEventListener' => 'PhutilEventListener', 'ManiphestPeopleMenuEventListener' => 'PhutilEventListener', diff --git a/src/applications/maniphest/controller/ManiphestExportController.php b/src/applications/maniphest/controller/ManiphestExportController.php index 89b6ac05af..e1ea54c964 100644 --- a/src/applications/maniphest/controller/ManiphestExportController.php +++ b/src/applications/maniphest/controller/ManiphestExportController.php @@ -62,6 +62,12 @@ final class ManiphestExportController extends ManiphestController { return new Aphront404Response(); } + $formats = ManiphestExcelFormat::loadAllFormats(); + $export_formats = array(); + foreach ($formats as $format_class => $format_object) { + $export_formats[$format_class] = $format_object->getName(); + } + if (!$request->isDialogFormPost()) { $dialog = new AphrontDialogView(); $dialog->setUser($user); @@ -70,12 +76,26 @@ final class ManiphestExportController extends ManiphestController { $dialog->appendChild(phutil_tag('p', array(), pht( 'Do you want to export the query results to Excel?'))); + $form = id(new AphrontFormLayoutView()) + ->appendChild( + id(new AphrontFormSelectControl()) + ->setLabel(pht('Format:')) + ->setName("excel-format") + ->setOptions($export_formats)); + + $dialog->appendChild($form); + $dialog->addCancelButton('/maniphest/'); $dialog->addSubmitButton(pht('Export to Excel')); return id(new AphrontDialogResponse())->setDialog($dialog); } + $format = idx($formats, $request->getStr("excel-format")); + if ($format === null) { + throw new Exception('Excel format object not found.'); + } + $query->setParameter('limit', null); $query->setParameter('offset', null); $query->setParameter('order', 'p'); @@ -92,114 +112,7 @@ final class ManiphestExportController extends ManiphestController { $handles += $project_handles; $workbook = new PHPExcel(); - $sheet = $workbook->setActiveSheetIndex(0); - $sheet->setTitle(pht('Tasks')); - - $widths = array( - null, - 15, - null, - 10, - 15, - 15, - 60, - 30, - 20, - 100, - ); - - foreach ($widths as $col => $width) { - if ($width !== null) { - $sheet->getColumnDimension($this->col($col))->setWidth($width); - } - } - - $status_map = ManiphestTaskStatus::getTaskStatusMap(); - $pri_map = ManiphestTaskPriority::getTaskPriorityMap(); - - $date_format = null; - - $rows = array(); - $rows[] = array( - pht('ID'), - pht('Owner'), - pht('Status'), - pht('Priority'), - pht('Date Created'), - pht('Date Updated'), - pht('Title'), - pht('Projects'), - pht('URI'), - pht('Description'), - ); - - $is_date = array( - false, - false, - false, - false, - true, - true, - false, - false, - false, - false, - ); - - $header_format = array( - 'font' => array( - 'bold' => true, - ), - ); - - foreach ($tasks as $task) { - $task_owner = null; - if ($task->getOwnerPHID()) { - $task_owner = $handles[$task->getOwnerPHID()]->getName(); - } - - $projects = array(); - foreach ($task->getProjectPHIDs() as $phid) { - $projects[] = $handles[$phid]->getName(); - } - $projects = implode(', ', $projects); - - $rows[] = array( - 'T'.$task->getID(), - $task_owner, - idx($status_map, $task->getStatus(), '?'), - idx($pri_map, $task->getPriority(), '?'), - $this->computeExcelDate($task->getDateCreated()), - $this->computeExcelDate($task->getDateModified()), - $task->getTitle(), - $projects, - PhabricatorEnv::getProductionURI('/T'.$task->getID()), - phutil_utf8_shorten($task->getDescription(), 512), - ); - } - - foreach ($rows as $row => $cols) { - foreach ($cols as $col => $spec) { - $cell_name = $this->col($col).($row + 1); - $cell = $sheet - ->setCellValue($cell_name, $spec, $return_cell = true); - - if ($row == 0) { - $sheet->getStyle($cell_name)->applyFromArray($header_format); - } - - if ($is_date[$col]) { - $code = PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2; - $sheet - ->getStyle($cell_name) - ->getNumberFormat() - ->setFormatCode($code); - } else { - $cell->setDataType(PHPExcel_Cell_DataType::TYPE_STRING); - } - } - } - + $format->buildWorkbook($workbook, $tasks, $handles, $user); $writer = PHPExcel_IOFactory::createWriter($workbook, 'Excel2007'); ob_start(); @@ -210,19 +123,8 @@ final class ManiphestExportController extends ManiphestController { return id(new AphrontFileResponse()) ->setMimeType($mime) - ->setDownload('maniphest_tasks_'.date('Ymd').'.xlsx') + ->setDownload($format->getFileName().'.xlsx') ->setContent($data); } - private function computeExcelDate($epoch) { - $seconds_per_day = (60 * 60 * 24); - $offset = ($seconds_per_day * 25569); - - return ($epoch + $offset) / $seconds_per_day; - } - - private function col($n) { - return chr(ord('A') + $n); - } - } diff --git a/src/applications/maniphest/export/ManiphestExcelDefaultFormat.php b/src/applications/maniphest/export/ManiphestExcelDefaultFormat.php new file mode 100644 index 0000000000..a2aa6c0a9c --- /dev/null +++ b/src/applications/maniphest/export/ManiphestExcelDefaultFormat.php @@ -0,0 +1,142 @@ +setActiveSheetIndex(0); + $sheet->setTitle(pht('Tasks')); + + $widths = array( + null, + 15, + null, + 10, + 15, + 15, + 60, + 30, + 20, + 100, + ); + + foreach ($widths as $col => $width) { + if ($width !== null) { + $sheet->getColumnDimension($this->col($col))->setWidth($width); + } + } + + $status_map = ManiphestTaskStatus::getTaskStatusMap(); + $pri_map = ManiphestTaskPriority::getTaskPriorityMap(); + + $date_format = null; + + $rows = array(); + $rows[] = array( + pht('ID'), + pht('Owner'), + pht('Status'), + pht('Priority'), + pht('Date Created'), + pht('Date Updated'), + pht('Title'), + pht('Projects'), + pht('URI'), + pht('Description'), + ); + + $is_date = array( + false, + false, + false, + false, + true, + true, + false, + false, + false, + false, + ); + + $header_format = array( + 'font' => array( + 'bold' => true, + ), + ); + + foreach ($tasks as $task) { + $task_owner = null; + if ($task->getOwnerPHID()) { + $task_owner = $handles[$task->getOwnerPHID()]->getName(); + } + + $projects = array(); + foreach ($task->getProjectPHIDs() as $phid) { + $projects[] = $handles[$phid]->getName(); + } + $projects = implode(', ', $projects); + + $rows[] = array( + 'T'.$task->getID(), + $task_owner, + idx($status_map, $task->getStatus(), '?'), + idx($pri_map, $task->getPriority(), '?'), + $this->computeExcelDate($task->getDateCreated()), + $this->computeExcelDate($task->getDateModified()), + $task->getTitle(), + $projects, + PhabricatorEnv::getProductionURI('/T'.$task->getID()), + phutil_utf8_shorten($task->getDescription(), 512), + ); + } + + foreach ($rows as $row => $cols) { + foreach ($cols as $col => $spec) { + $cell_name = $this->col($col).($row + 1); + $cell = $sheet + ->setCellValue($cell_name, $spec, $return_cell = true); + + if ($row == 0) { + $sheet->getStyle($cell_name)->applyFromArray($header_format); + } + + if ($is_date[$col]) { + $code = PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2; + $sheet + ->getStyle($cell_name) + ->getNumberFormat() + ->setFormatCode($code); + } else { + $cell->setDataType(PHPExcel_Cell_DataType::TYPE_STRING); + } + } + } + } + + + private function col($n) { + return chr(ord('A') + $n); + } + +} diff --git a/src/applications/maniphest/export/ManiphestExcelFormat.php b/src/applications/maniphest/export/ManiphestExcelFormat.php new file mode 100644 index 0000000000..344c05a2d1 --- /dev/null +++ b/src/applications/maniphest/export/ManiphestExcelFormat.php @@ -0,0 +1,47 @@ +setAncestorClass(__CLASS__) + ->setConcreteOnly(true) + ->selectAndLoadSymbols(); + + $objects = array(); + foreach ($classes as $class) { + $objects[$class['name']] = newv($class['name'], array()); + } + + $objects = msort($objects, 'getOrder'); + + return $objects; + } + + public abstract function getName(); + public abstract function getFileName(); + + public function getOrder() { + return 0; + } + + protected function computeExcelDate($epoch) { + $seconds_per_day = (60 * 60 * 24); + $offset = ($seconds_per_day * 25569); + + return ($epoch + $offset) / $seconds_per_day; + } + + /** + * @phutil-external-symbol class PHPExcel + */ + public abstract function buildWorkbook( + PHPExcel $workbook, + array $tasks, + array $handles, + PhabricatorUser $user); + +}