From e1a9ad161248356283ded68747ffb0284e1ac4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 11 Jan 2016 21:45:20 +0100 Subject: [PATCH] [wip] add different steps to handle request --- Controller/ExportController.php | 186 ++++++++++++- .../CompilerPass/ExportsCompilerPass.php | 31 +++ Export/ExportManager.php | 97 +++++-- Export/Formatter/CSVFormatter.php | 247 ++++++++++++++++++ Export/FormatterInterface.php | 2 +- .../AliasToFormatterTransformer.php | 86 ++++++ Form/Type/Export/AggregatorType.php | 20 +- Form/Type/Export/ExportType.php | 4 + Form/Type/Export/FormatterType.php | 59 +++++ Form/Type/Export/PickFormatterType.php | 69 +++++ Resources/config/services.yml | 27 ++ Resources/views/Export/new.html.twig | 11 +- .../views/Export/new_formatter_step.html.twig | 38 +++ 13 files changed, 829 insertions(+), 48 deletions(-) create mode 100644 Export/Formatter/CSVFormatter.php create mode 100644 Form/Type/DataTransformer/AliasToFormatterTransformer.php create mode 100644 Form/Type/Export/FormatterType.php create mode 100644 Form/Type/Export/PickFormatterType.php create mode 100644 Resources/views/Export/new_formatter_step.html.twig diff --git a/Controller/ExportController.php b/Controller/ExportController.php index 392340eab..0ea0a0b3a 100644 --- a/Controller/ExportController.php +++ b/Controller/ExportController.php @@ -25,6 +25,11 @@ namespace Chill\MainBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Chill\MainBundle\Form\Type\Export\ExportType; +use Chill\MainBundle\Form\Type\Export\PickFormatterType; +use Chill\MainBundle\Form\Type\Export\FormatterType; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\Extension\Core\Type\HiddenType; /** @@ -44,20 +49,53 @@ class ExportController extends Controller )); } - public function newAction($alias) + /** + * Render the form required to generate data for the export. + * + * This action has two steps : + * + * - 'export', for the export form + * - 'formatter', for the formatter form + * + * @param string $alias + * @param Request $request + * @return \Symfony\Component\HttpFoundation\Response + */ + public function newAction(Request $request, $alias) + { + $step = $request->query->getAlpha('step', 'export'); + + switch ($step) { + case 'export': + return $this->renderExportForm($alias); + break; + case 'formatter': + return $this->renderFormatterStep($request, $alias); + break; + default: + throw $this->createNotFoundException("The given step '$step' is invalid"); + } + } + + /** + * Render the export form + * + * @param string $alias + * @return \Symfony\Component\HttpFoundation\Response + */ + protected function renderExportForm($alias) { $exportManager = $this->get('chill.main.export_manager'); $export = $exportManager->getExport($alias); - - $form = $this->createCreateForm($alias); + + $form = $this->createCreateFormExport($alias); return $this->render('ChillMainBundle:Export:new.html.twig', array( 'form' => $form->createView(), 'export_alias' => $alias, 'export' => $export )); - } /** @@ -65,30 +103,150 @@ class ExportController extends Controller * @param string $alias * @return \Symfony\Component\Form\Form */ - protected function createCreateForm($alias) + protected function createCreateFormExport($alias) { - $form = $this->createForm(ExportType::class, array(), array( + $builder = $this->get('form.factory') + ->createNamedBuilder(null, FormType::class, array(), array( + 'method' => 'GET', + 'csrf_protection' => false, + 'action' => $this->generateUrl('chill_main_export_new', array( + 'alias' => $alias + )) + )); + + $builder->add('export', ExportType::class, array( 'export_alias' => $alias, - 'method' => 'GET', - 'action' => $this->generateUrl('chill_main_export_generate', array( - 'alias' => $alias - )) + )); - $form->add('submit', 'submit', array( + $builder->add('submit', 'submit', array( + 'label' => 'Generate' + )); + $builder->add('step', 'hidden', array( + 'data' => 'formatter' + )); + + return $builder->getForm(); + } + + protected function renderFormatterStep(Request $request, $alias) + { + $export = $this->get('chill.main.export_manager')->getExport($alias); + + $exportForm = $this->createCreateFormExport($alias); + $exportForm->handleRequest($request); + $data = $exportForm->getData(); + + $form = $this->createCreateFormFormatter($request, + $alias, array(), $data['export']['formatter']['alias']); + + return $this->render('ChillMainBundle:Export:new_formatter_step.html.twig', + array( + 'form' => $form->createView(), + 'export' => $export + )); + } + + /** + * + * @param Request $request + * @param type $formatterAlias + * @return \Symfony\Component\Form\Form + */ + protected function createCreateFormFormatter(Request $request, + $exportAlias, $aggregatorAliases, $formatterAlias = null) + { + var_dump($request->query->all()); + $builder = $this->get('form.factory') + ->createNamedBuilder(null, FormType::class, array(), array( + 'method' => 'GET', + 'csrf_protection' => false, + 'action' => $this->generateUrl('chill_main_export_generate', array( + 'alias' => $exportAlias + )) + )); + + $builder->add('formatter', FormatterType::class, array( + 'formatter_alias' => $formatterAlias, + 'export_alias' => $exportAlias, + 'aggregator_aliases' => $aggregatorAliases + )); + + // re-add the export type under hidden fields + $builderExport = $builder->create('export', FormType::class, array()); + $data = $request->query->all(); + foreach($data['export'] as $key => $value) { + $this->recursiveAddHiddenFieldsToForm($builderExport, $key, $value); + } + $builder->add($builderExport); + + //add the formatter alias + $builder->add('formatter', HiddenType::class, array( + 'data' => $formatterAlias + )); + + $builder->add('submit', 'submit', array( 'label' => 'Generate' )); - return $form; + return $builder->getForm(); + } public function generateAction(Request $request, $alias) { $exportManager = $this->get('chill.main.export_manager'); - $form = $this->createCreateForm($alias); + $form = $this->createCreateFormGenerate($request, $alias); $form->handleRequest($request); + $data = $form->getData(); - return $exportManager->generate($alias, $form->getData()); + return $exportManager->generate($alias, $data['export']); + } + + /** + * + * @param Request $request + * @param string $alias + * @return \Symfony\Component\Form\Form + */ + public function createCreateFormGenerate(Request $request, $alias, + $aggregatorAliases, $formatterAlias) + { + $builder = $this->get('form.factory') + ->createNamedBuilder(null, FormType::class, array(), array( + 'method' => 'GET', + 'csrf_protection' => false, + 'action' => $this->generateUrl('chill_main_export_generate', array( + 'alias' => $alias + )) + )); + + $builder->add('formatter', FormatterType::class, array( + 'formatter_alias' => $formatterAlias, + 'export_alias' => $exportAlias, + 'aggregator_aliases' => $aggregatorAliases + )); + + $builder->add('export', ExportType::class, array( + 'export_alias' => $alias, + )); + + return $builder->getForm(); + } + + protected function recursiveAddHiddenFieldsToForm(FormBuilderInterface $builder, $key, $data) + { + if (is_array($data)) { + foreach($data as $subKey => $value) { + $subBuilder = $builder->create($subKey, FormType::class); + $this->recursiveAddHiddenFieldsToForm($subBuilder, $subKey, $value); + $builder->add($subBuilder); + } + } else { + $builder->add($key, 'hidden', array( + 'data' => $data + )); + } } } diff --git a/DependencyInjection/CompilerPass/ExportsCompilerPass.php b/DependencyInjection/CompilerPass/ExportsCompilerPass.php index 39045495f..dc4d1805d 100644 --- a/DependencyInjection/CompilerPass/ExportsCompilerPass.php +++ b/DependencyInjection/CompilerPass/ExportsCompilerPass.php @@ -52,6 +52,7 @@ class ExportsCompilerPass implements CompilerPassInterface $this->compileExports($chillManagerDefinition, $container); $this->compileFilters($chillManagerDefinition, $container); $this->compileAggregators($chillManagerDefinition, $container); + $this->compileFormatters($chillManagerDefinition, $container); } private function compileExports(Definition $chillManagerDefinition, @@ -143,5 +144,35 @@ class ExportsCompilerPass implements CompilerPassInterface } } } + + private function compileFormatters(Definition $chillManagerDefinition, + ContainerBuilder $container) + { + $taggedServices = $container->findTaggedServiceIds( + 'chill.export_formatter' + ); + + $knownAliases = array(); + + foreach ($taggedServices as $id => $tagAttributes) { + foreach ($tagAttributes as $attributes) { + if (!isset($attributes["alias"])) { + throw new \LogicException("the 'alias' attribute is missing in your ". + "service '$id' definition"); + } + + if (array_search($attributes["alias"], $knownAliases)) { + throw new \LogicException("There is already a chill.export_formatter service with alias " + .$attributes["alias"].". Choose another alias."); + } + $knownAliases[] = $attributes["alias"]; + + $chillManagerDefinition->addMethodCall( + 'addFormatter', + array(new Reference($id), $attributes["alias"]) + ); + } + } + } } diff --git a/Export/ExportManager.php b/Export/ExportManager.php index f243f8492..adc4fea25 100644 --- a/Export/ExportManager.php +++ b/Export/ExportManager.php @@ -94,9 +94,9 @@ class ExportManager $this->exports[$alias] = $export; } - public function addFormatter(FormatterInterface $formatter) + public function addFormatter(FormatterInterface $formatter, $alias) { - array_push($this->formatters, $formatter); + $this->formatters[$alias] = $formatter; } /** @@ -157,6 +157,13 @@ class ExportManager return $this->filters[$alias]; } + public function getFilters(array $aliases) + { + foreach($aliases as $alias) { + yield $alias => $this->getFilter($alias); + } + } + /** * * @param string $alias @@ -172,6 +179,31 @@ class ExportManager return $this->aggregators[$alias]; } + public function getAggregators(array $aliases) + { + foreach ($aliases as $alias) { + yield $alias => $this->getAggregator($alias); + } + } + + public function getFormatter($alias) + { + if (!array_key_exists($alias, $this->formatters)) { + throw new \RuntimeException("The formatter with alias $alias is not known."); + } + + return $this->formatters[$alias]; + } + + public function getFormattersByTypes(array $types) + { + foreach ($this->formatters as $alias => $formatter) { + if (in_array($formatter->getType(), $types)) { + yield $alias => $formatter; + } + } + } + /** * Return a \Generator containing filter which support type @@ -242,11 +274,18 @@ class ExportManager 'class' => self::class, 'function' => __FUNCTION__ )); - $results = $qb->getQuery()->getResult(\Doctrine\ORM\Query::HYDRATE_SCALAR); + $result = $export->getResult($qb, array()); - var_dump($results); + /* @var $formatter Formatter\CSVFormatter */ + $formatter = $this->getFormatter('csv'); + $filters = array(); + $aggregators = iterator_to_array($this->retrieveUsedAggregators($data['aggregators'])); + $aggregatorsData = array_combine(array_keys($data['aggregators']), + array_map(function($data) { return $data['form']; }, $data['aggregators']) + ); - return new Response('everything is fine !'); + return $formatter->getResponse($result, array(), $export, + $filters, $aggregators, array(), $data['filters'], $aggregatorsData); } /** @@ -257,12 +296,10 @@ class ExportManager */ private function retrieveUsedModifiers($data) { - $usedTypes = array(); - - // used filters - $this->retrieveUsedFilters($data, $usedTypes); - // used aggregators - $this->retrieveUsedAggregators($data, $usedTypes); + $usedTypes = array_merge( + $this->retrieveUsedFiltersType($data['filters']), + $this->retrieveUsedAggregatorsType($data['aggregators']) + ); $this->logger->debug('Required types are '.implode(', ', $usedTypes), array('class' => self::class, 'function' => __FUNCTION__)); @@ -270,9 +307,10 @@ class ExportManager return $usedTypes; } - private function retrieveUsedFilters($data, &$usedTypes) + private function retrieveUsedFiltersType($data) { - foreach($data['filters'] as $alias => $filterData) { + $usedTypes = array(); + foreach($data as $alias => $filterData) { if ($filterData['enabled'] == true){ $filter = $this->getFilter($alias); if (!in_array($filter->applyOn(), $usedTypes)) { @@ -280,16 +318,37 @@ class ExportManager } } } + + return $usedTypes; } - private function retrieveUsedAggregators($data, &$usedTypes) + /** + * + * @param mixed $data + * @return string[] + */ + private function retrieveUsedAggregatorsType($data) { - foreach($data['aggregators'] as $alias => $aggregatorData) { + $usedTypes = array(); + foreach($this->retrieveUsedAggregators($data) as $alias => $aggregator) { + if (!in_array($aggregator->applyOn(), $usedTypes)) { + array_push($usedTypes, $aggregator->applyOn()); + } + } + + return $usedTypes; + } + + /** + * + * @param mixed $data + * @return AggregatorInterface[] + */ + private function retrieveUsedAggregators($data) + { + foreach($data as $alias => $aggregatorData) { if ($aggregatorData['order']> 0){ - $aggregator = $this->getAggregator($alias); - if (!in_array($aggregator->applyOn(), $usedTypes)) { - array_push($usedTypes, $aggregator->applyOn()); - } + yield $alias => $this->getAggregator($alias); } } } diff --git a/Export/Formatter/CSVFormatter.php b/Export/Formatter/CSVFormatter.php new file mode 100644 index 000000000..3cd9d4cd1 --- /dev/null +++ b/Export/Formatter/CSVFormatter.php @@ -0,0 +1,247 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\MainBundle\Export\Formatter; + +use Chill\MainBundle\Export\ExportInterface; +use Symfony\Component\HttpFoundation\Response; +use Chill\MainBundle\Export\FormatterInterface; +use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Form\FormBuilderInterface; + +// command to get the report with curl : curl --user "center a_social:password" "http://localhost:8000/fr/exports/generate/count_person?export[filters][person_gender_filter][enabled]=&export[filters][person_nationality_filter][enabled]=&export[filters][person_nationality_filter][form][nationalities]=&export[aggregators][person_nationality_aggregator][order]=1&export[aggregators][person_nationality_aggregator][form][group_by_level]=country&export[submit]=&export[_token]=RHpjHl389GrK-bd6iY5NsEqrD5UKOTHH40QKE9J1edU" --globoff + +/** + * + * + * @author Julien Fastré + */ +class CSVFormatter implements FormatterInterface +{ + /** + * + * @var TranslatorInterface + */ + protected $translator; + + protected $result; + + protected $formatterData; + + protected $export; + + protected $filters; + + protected $aggregators; + + protected $exportData; + + protected $filterData; + + protected $aggregatorsData; + + + public function __construct(TranslatorInterface $translator) + { + $this->translator = $translator; + } + + public function getType() + { + return 'tabular'; + } + + public function getName() + { + return 'CSV'; + } + + public function buildForm(FormBuilderInterface $builder, $exportAlias, array $aggregatorAliases) + { + + } + + /** + * + * @param mixed $result + * @param mixed $data + * @param \Chill\MainBundle\Export\ExportInterface $export + * @param \Chill\MainBundle\Export\FilterInterface[] $filters + * @param \Chill\MainBundle\Export\AggregatorInterface[] $aggregators + */ + public function getResponse($result, $formatterData, ExportInterface $export, $filters, + $aggregators, $exportData, $filterData, $aggregatorsData) + { + $this->result = $result; + $this->formatterData = $formatterData; + $this->export = $export; + $this->filters = $filters; + $this->aggregators = $aggregators; + $this->exportData = $exportData; + $this->filterData = $filterData; + $this->aggregatorsData = $aggregatorsData; + + $response = new Response(); + $response->setStatusCode(200); + $response->headers->set('Content-Type', 'text/csv; charset=utf-8'); + //$response->headers->set('Content-Disposition','attachment; filename="export.csv"'); + + $response->setContent($this->generateContent()); + + return $response; + } + + protected function generateContent() + { + $labels = $this->gatherLabels(); + $horizontalHeadersKeys = $this->getHorizontalHeaders(); + $resultsKeys = $this->export->getQueryKeys($this->exportData); + + + // create a file pointer connected to the output stream + $output = fopen('php://output', 'w'); + + //title + fputcsv($output, array($this->translator->trans($this->export->getTitle()))); + //blank line + fputcsv($output, array("")); + + //headers + $headerLine = array(); + foreach($horizontalHeadersKeys as $headerKey) { + $headerLine[] = array_key_exists('_header', $labels[$headerKey]) ? + $labels[$headerKey]['_header'] : ''; + } + foreach($resultsKeys as $key) { + $headerLine[] = array_key_exists('_header', $labels[$key]) ? + $labels[$key]['_header'] : ''; + } + fputcsv($output, $headerLine); + unset($headerLine); //free memory + + $content = array(); + foreach($this->result as $row) { + $line = array(); + //set horizontal headers + foreach($horizontalHeadersKeys as $headerKey) { + + if (!array_key_exists($row[$headerKey], $labels[$headerKey])) { + throw new \LogicException("The value '".$row[$headerKey]."' " + . "is not available from the labels defined by aggregators. " + . "The key name was $headerKey"); + } + + $line[] = $labels[$headerKey][$row[$headerKey]]; + } + //append result + foreach($resultsKeys as $key) { + $line[] = $labels[$key][$row[$key]]; + } + // append to content + $content[] = $line; + } + + //ordering content + array_multisort($content); + + //generate CSV + foreach($content as $line) { + fputcsv($output, $line); + } + + $text = stream_get_contents($output); + fclose($output); + + return $text; + } + + + protected function getHorizontalHeaders() + { + $headers = array(); + /* @var $aggregator AggregatorInterface */ + foreach($this->aggregators as $alias => $aggregator) { + $headers = array_merge($headers, $aggregator->getQueryKeys($this->aggregatorsData[$alias])); + } + return $headers; + } + + /** + * + * @param mixed $result + * @param \Chill\MainBundle\Export\AggregatorInterface[] $aggregators + */ + protected function gatherLabels() + { + return array_merge( + $this->gatherLabelsFromAggregators(), + $this->gatherLabelsFromExport() + ); + } + + protected function gatherLabelsFromAggregators() + { + $labels = array(); + /* @var $aggretator \Chill\MainBundle\Export\AggregatorInterface */ + foreach ($this->aggregators as $alias => $aggregator) { + $keys = $aggregator->getQueryKeys($this->aggregatorsData[$alias]); + + // gather data in an array + foreach($keys as $key) { + $values = array_map(function($row) use ($key, $alias) { + if (!array_key_exists($key, $row)) { + throw new \LogicException("the key '".$key."' is declared by " + . "the aggregator with alias '".$alias."' but is not " + . "present in results"); + } + + return $row[$key]; + }, $this->result); + $labels[$key] = $aggregator->getLabels($key, array_unique($values), + $this->aggregatorsData[$alias]); + } + } + + return $labels; + } + + protected function gatherLabelsFromExport() + { + $labels = array(); + $export = $this->export; + $keys = $this->export->getQueryKeys($this->exportData); + + foreach($keys as $key) { + $values = array_map(function($row) use ($key, $export) { + if (!array_key_exists($key, $row)) { + throw new \LogicException("the key '".$key."' is declared by " + . "the export with title '".$export->getTitle()."' but is not " + . "present in results"); + } + + return $row[$key]; + }, $this->result); + $labels[$key] = $this->export->getLabels($key, array_unique($values), + $this->exportData); + } + + return $labels; + } + +} diff --git a/Export/FormatterInterface.php b/Export/FormatterInterface.php index e980af624..9fdf9d8ba 100644 --- a/Export/FormatterInterface.php +++ b/Export/FormatterInterface.php @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -namespace Chill\Mainbundle\Export; +namespace Chill\MainBundle\Export; /** * diff --git a/Form/Type/DataTransformer/AliasToFormatterTransformer.php b/Form/Type/DataTransformer/AliasToFormatterTransformer.php new file mode 100644 index 000000000..598ee615d --- /dev/null +++ b/Form/Type/DataTransformer/AliasToFormatterTransformer.php @@ -0,0 +1,86 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\MainBundle\Form\Type\DataTransformer; + +use Symfony\Component\Form\DataTransformerInterface; +use Chill\MainBundle\Export\ExportManager; +use Symfony\Component\Form\Exception\TransformationFailedException; + +/** + * Transform a formatter alias to an FormatterInterface class + * + * @author Julien Fastré + */ +class AliasToFormatterTransformer implements DataTransformerInterface +{ + /** + * + * @var ExportManager + */ + protected $exportManager; + + public function __construct(ExportManager $exportManager) + { + $this->exportManager = $exportManager; + } + + public function reverseTransform($value) + { + if ($value === NULL) { + return NULL; + } + + if (!value instanceof \Chill\MainBundle\Export\FormatterInterface) { + throw new TransformationFailedException("The given value is not a " + . "Chill\MainBundle\Export\FormatterInterface"); + } + + // we do not have the alias, which is only known by the container. + // we try to check the formatter by the php internal object id. + $formatters = $this->exportManager + ->getFormattersByTypes(array($value->getType())); + foreach($formatters as $alias => $formatter) { + if (spl_object_hash($formatter) === spl_object_hash($value)) { + return $alias; + } + } + + throw new TransformationFailedException("The formatter could not be found " + . "by his object_hash. Maybe you created a formatter manually ? " + . "Use the export manager to get your formatter."); + } + + /** + * + * @param type $value + * @return \Chill\MainBundle\Export\FormatterInterface + * @throws TransformationFailedException + */ + public function transform($value) + { + if (empty($value)) { + throw new TransformationFailedException("The formatter with empty " + . "alias is not allowed. Given value is ".$value); + } + + return $this->exportManager->getFormatter($value); + } + +} diff --git a/Form/Type/Export/AggregatorType.php b/Form/Type/Export/AggregatorType.php index 7c96e612c..bcbe48ec7 100644 --- a/Form/Type/Export/AggregatorType.php +++ b/Form/Type/Export/AggregatorType.php @@ -23,8 +23,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\FormBuilderInterface; use Chill\MainBundle\Export\ExportManager; -use Symfony\Component\Validator\Constraints as Assert; -use Symfony\Component\Form\Extension\Core\Type\IntegerType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; /** * @@ -49,15 +48,14 @@ class AggregatorType extends AbstractType $aggregator = $this->exportManager->getAggregator($options['aggregator_alias']); $builder - ->add('order', IntegerType::class, array( - 'constraints' => array( - new Assert\GreaterThanOrEqual(array( - 'value' => -1 - )), - new Assert\LessThanOrEqual(array( - 'value' => $options['aggregators_length'] - )) - ) + ->add('enabled', ChoiceType::class, array( + 'choices' => array( + 'enabled' => true, + 'disabled' => false + ), + 'multiple' => false, + 'expanded' => true, + 'choices_as_values' => true )); $filterFormBuilder = $builder->create('form', 'form', array( diff --git a/Form/Type/Export/ExportType.php b/Form/Type/Export/ExportType.php index 6c6b06584..d195ebbc0 100644 --- a/Form/Type/Export/ExportType.php +++ b/Form/Type/Export/ExportType.php @@ -88,6 +88,10 @@ class ExportType extends AbstractType $builder->add($aggregatorBuilder); + $builder->add('formatter', PickFormatterType::class, array( + 'export_alias' => $options['export_alias'] + )); + } diff --git a/Form/Type/Export/FormatterType.php b/Form/Type/Export/FormatterType.php new file mode 100644 index 000000000..023822d12 --- /dev/null +++ b/Form/Type/Export/FormatterType.php @@ -0,0 +1,59 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\MainBundle\Form\Type\Export; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Form\FormBuilderInterface; +use Chill\MainBundle\Export\ExportManager; + +/** + * + * + * @author Julien Fastré + */ +class FormatterType extends AbstractType +{ + /** + * + * @var ExportManager + */ + protected $exportManager; + + public function __construct(ExportManager $manager) + { + $this->exportManager = $manager; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setRequired(array('formatter_alias', 'export_alias', + 'aggregator_aliases')); + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $formatter = $this->exportManager->getFormatter($options['formatter_alias']); + + $formatter->buildForm($builder, $options['export_alias'], + $options['aggregator_aliases']); + } + +} diff --git a/Form/Type/Export/PickFormatterType.php b/Form/Type/Export/PickFormatterType.php new file mode 100644 index 000000000..0f18cf3df --- /dev/null +++ b/Form/Type/Export/PickFormatterType.php @@ -0,0 +1,69 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\MainBundle\Form\Type\Export; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Chill\MainBundle\Export\ExportManager; +use Chill\MainBundle\Form\Type\DataTransformer\AliasToFormatterTransformer; + +/** + * + * + * @author Julien Fastré + */ +class PickFormatterType extends AbstractType +{ + protected $exportManager; + + public function __construct(ExportManager $exportManager) + { + $this->exportManager = $exportManager; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $export = $this->exportManager->getExport($options['export_alias']); + $allowedFormatters = $this->exportManager + ->getFormattersByTypes($export->getAllowedFormattersTypes()); + //$transformer = new AliasToFormatterTransformer($this->exportManager); + + //build choices + $choices = array(); + foreach($allowedFormatters as $alias => $formatter) { + $choices[$formatter->getName()] = $alias; + } + + $builder->add('alias', 'choice', array( + 'choices' => $choices, + 'choices_as_values' => true, + 'multiple' => false + )); + + //$builder->get('type')->addModelTransformer($transformer); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setRequired(array('export_alias')); + } + +} diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 2d8b5b0e3..ee660e734 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -161,3 +161,30 @@ services: - "@chill.main.export_manager" tags: - { name: form.type } + + chill.main.form.pick_formatter_type: + class: Chill\MainBundle\Form\Type\Export\PickFormatterType + arguments: + - "@chill.main.export_manager" + tags: + - { name: form.type } + + chill.main.form.formatter_type: + class: Chill\MainBundle\Form\Type\Export\FormatterType + arguments: + - "@chill.main.export_manager" + tags: + - { name: form.type } + + chill.main.countries_repository: + class: Doctrine\ORM\EntityRepository + factory: ["@doctrine.orm.entity_manager", getRepository] + arguments: + - "Chill\\MainBundle\\Entity\\Country" + + chill.main.export.csv_formatter: + class: Chill\MainBundle\Export\Formatter\CSVFormatter + arguments: + - "@translator" + tags: + - { name: chill.export_formatter, alias: 'csv' } diff --git a/Resources/views/Export/new.html.twig b/Resources/views/Export/new.html.twig index 637b16694..985521f33 100644 --- a/Resources/views/Export/new.html.twig +++ b/Resources/views/Export/new.html.twig @@ -29,7 +29,7 @@ {{ form_start(form) }}

{{ 'Filters'| trans }}

- {% for filter_form in form.children.filters %} + {% for filter_form in form.children.export.children.filters %} {{ form_label(filter_form) }} {{ form_row(filter_form.enabled) }} {{ form_widget(filter_form.form) }} @@ -38,13 +38,18 @@

{{ 'Aggregators'| trans }}

- {% for aggregator_form in form.children.aggregators %} + {% for aggregator_form in form.children.export.children.aggregators %} {{ form_label(aggregator_form) }} - {{ form_row(aggregator_form.order) }} + {{ form_row(aggregator_form.enabled) }} {{ form_widget(aggregator_form.form) }} {% endfor %}
+
+

{{ 'Formatter'| trans }}

+ {{ form_row(form.children.export.children.formatter.children.alias) }} +
+

{{ form_widget(form.submit, { 'attr' : { 'class' : 'sc-button btn-action' } } ) }}

{{ form_end(form) }} diff --git a/Resources/views/Export/new_formatter_step.html.twig b/Resources/views/Export/new_formatter_step.html.twig new file mode 100644 index 000000000..8949d7beb --- /dev/null +++ b/Resources/views/Export/new_formatter_step.html.twig @@ -0,0 +1,38 @@ +{# + * Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, + / + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +#} + +{% extends "ChillMainBundle::layoutWithVerticalMenu.html.twig" %} + +{% block title %}{{ export.title|trans }}{% endblock %} + +{% block layout_wvm_content %} + +

{{ export.title|trans }}

+ +

{{ export.description|trans }}

+ + {{ form_start(form) }} +
+

{{ 'Formatter'| trans }}

+ {{ form_row(form.children.formatter) }} +
+ +

{{ form_widget(form.submit, { 'attr' : { 'class' : 'sc-button btn-action' } } ) }}

+ {{ form_end(form) }} + +{% endblock layout_wvm_content %}