diff --git a/Controller/ExportController.php b/Controller/ExportController.php index 4c777db08..5f1341480 100644 --- a/Controller/ExportController.php +++ b/Controller/ExportController.php @@ -117,7 +117,7 @@ class ExportController extends Controller $data = $form->getData(); // check ACL - if ($exportManager->isGrantedForElement($export, + if ($exportManager->isGrantedForElement($export, NULL, $exportManager->getPickedCenters($data['centers'])) === FALSE) { throw $this->createAccessDeniedException('you do not have ' . 'access to this export for those centers'); diff --git a/Export/AggregatorInterface.php b/Export/AggregatorInterface.php index d2f3fa34a..ec3fba739 100644 --- a/Export/AggregatorInterface.php +++ b/Export/AggregatorInterface.php @@ -19,18 +19,34 @@ namespace Chill\MainBundle\Export; -use Symfony\Component\Form\FormBuilderInterface; -use Doctrine\ORM\QueryBuilder; - /** + * Interface for Aggregators. + * + * Aggregators gather result of a query. Most of the time, it will add + * a GROUP BY clause. * * @author Julien Fastré */ -interface AggregatorInterface extends ExportElementInterface -{ - public function applyOn(); +interface AggregatorInterface extends ModifierInterface +{ + /** + * give the list of keys the current export added to the queryBuilder in + * self::initiateQuery + * + * Example: if your query builder will contains `SELECT count(id) AS count_id ...`, + * this function will return `array('count_id')`. + * + * @param mixed[] $data the data from the export's form (added by self::buildForm) + */ + public function getQueryKeys($data); - public function buildForm(FormBuilderInterface $builder); - - public function alterQuery(QueryBuilder $qb, $data); + /** + * transform the results to viewable and understable string. + * + * @param string $key The column key, as added in the query + * @param mixed[] $values The values from the result. Each value is unique + * @param mixed $data The data from the form + */ + public function getLabels($key, array $values, $data); + } diff --git a/Export/ExportElementInterface.php b/Export/ExportElementInterface.php index 0ea32f22f..d1498be31 100644 --- a/Export/ExportElementInterface.php +++ b/Export/ExportElementInterface.php @@ -19,15 +19,29 @@ namespace Chill\MainBundle\Export; +use Symfony\Component\Form\FormBuilderInterface; + /** * The common methods between different object used to build export (i.e. : ExportInterface, - * FilterInterface, AggregatorInterface + * FilterInterface, AggregatorInterface) * * @author Julien Fastré */ interface ExportElementInterface { - public function requiredRole(); - + /** + * get a title, which will be used in UI (and translated) + * + * @return string + */ public function getTitle(); + + + /** + * Add a form to collect data from the user. + * + * @param FormBuilderInterface $builder + */ + public function buildForm(FormBuilderInterface $builder); + } diff --git a/Export/ExportInterface.php b/Export/ExportInterface.php index fd0126c8b..3a0fba63e 100644 --- a/Export/ExportInterface.php +++ b/Export/ExportInterface.php @@ -20,22 +20,42 @@ namespace Chill\MainBundle\Export; use Doctrine\ORM\QueryBuilder; -use Symfony\Component\Form\FormBuilderInterface; /** + * Interface for Export. + * + * An export is a class which will initiate a query for an export. * + * @example Chill\PersonBundle\Export\CountPerson an example of implementation * @author Julien Fastré */ interface ExportInterface extends ExportElementInterface { - + /** + * Return the Export's type. This will inform _on what_ export will apply. + * Most of the type, it will be a string which references an entity. + * + * Example of types : Chill\PersonBundle\Export\Declarations::PERSON_TYPE + * + * @return string + */ public function getType(); + /** + * A description, which will be used in the UI to explain what the export does. + * This description will be translated. + * + * @return string + */ public function getDescription(); - public function getTitle(); - /** + * The initial query, which will be modified by ModifiersInterface + * (i.e. AggregatorInterface, FilterInterface). + * + * This query should take into account the `$acl` and restrict result only to + * what the user is allowed to see. (Do not show personal data the user + * is not allowed to see). * * @param QueryBuilder $qb * @param array $requiredModifiers @@ -43,14 +63,67 @@ interface ExportInterface extends ExportElementInterface * TODO : we should add ability to receive data from a form */ public function initiateQuery(QueryBuilder $qb, array $requiredModifiers, $acl); - - public function buildForm(FormBuilderInterface $builder); + /** + * Return wether this export has a form. + * * @return bool */ public function hasForm(); + /** + * Inform which ModifiersInterface (i.e. AggregatorInterface, FilterInterface) + * are allowed. The modifiers should be an array of types the _modifier_ apply on + * (@see ModifiersInterface::applyOn()). + * + * @return string[] + */ public function supportsModifiers(); + + /** + * Return the required Role to execute the Export. + * + * @return \Symfony\Component\Security\Core\Role\Role + * + */ + public function requiredRole(); + + /** + * Return which formatter type is allowed for this report. + * + * @return string[] + */ + public function getAllowedFormattersTypes(); + + /** + * give the list of keys the current export added to the queryBuilder in + * self::initiateQuery + * + * Example: if your query builder will contains `SELECT count(id) AS count_id ...`, + * this function will return `array('count_id')`. + * + * @param mixed[] $data the data from the export's form (added by self::buildForm) + */ + public function getQueryKeys($data); + + /** + * Return the results of the query builder. + * + * @param QueryBuilder $qb + * @param mixed[] $data the data from the export's fomr (added by self::buildForm) + * @return mixed[] an array of results + */ + public function getResult(QueryBuilder $qb, $data); + + + /** + * transform the results to viewable and understable string. + * + * @param string $key The column key, as added in the query + * @param mixed[] $values The values from the result. Each value is unique + * @param mixed $data The data from the form + */ + public function getLabels($key, array $values, $data); } diff --git a/Export/ExportManager.php b/Export/ExportManager.php index 0ef3e1272..5f2d0009f 100644 --- a/Export/ExportManager.php +++ b/Export/ExportManager.php @@ -31,10 +31,11 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Chill\MainBundle\Form\Type\Export\PickCenterType; +use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; /** * Collects all agregators, filters and export from - * the installed bundle. + * the installed bundle, and performs the export logic. * * * @author Julien Fastré @@ -42,30 +43,35 @@ use Chill\MainBundle\Form\Type\Export\PickCenterType; class ExportManager { /** + * The collected filters, injected by DI * * @var FilterInterface[] */ private $filters = array(); /** + * The collected aggregators, injected by DI * * @var AggregatorInterface[] */ private $aggregators = array(); /** + * Collected Exports, injected by DI * * @var ExportInterface[] */ private $exports = array(); /** + * Collected Formatters, injected by DI * * @var FormatterInterface[] */ private $formatters = array(); /** + * a logger * * @var LoggerInterface */ @@ -109,21 +115,53 @@ class ExportManager $this->user = $tokenStorage->getToken()->getUser(); } + /** + * add a Filter + * + * @internal Normally used by the dependency injection + * + * @param FilterInterface $filter + * @param string $alias + */ public function addFilter(FilterInterface $filter, $alias) { $this->filters[$alias] = $filter; } + /** + * add an aggregator + * + * @internal used by DI + * + * @param AggregatorInterface $aggregator + * @param string $alias + */ public function addAggregator(AggregatorInterface $aggregator, $alias) { $this->aggregators[$alias] = $aggregator; } + /** + * add an export + * + * @internal used by DI + * + * @param ExportInterface $export + * @param type $alias + */ public function addExport(ExportInterface $export, $alias) { $this->exports[$alias] = $export; } + /** + * add a formatter + * + * @internal used by DI + * + * @param FormatterInterface $formatter + * @param type $alias + */ public function addFormatter(FormatterInterface $formatter, $alias) { $this->formatters[$alias] = $formatter; @@ -156,7 +194,7 @@ class ExportManager { foreach ($this->exports as $alias => $export) { if ($whereUserIsGranted) { - if ($this->isGrantedForElement($export, null)) { + if ($this->isGrantedForElement($export, null, null)) { yield $alias => $export; } } else { @@ -252,15 +290,14 @@ class ExportManager * has access in every centers he can reach (if the user can use the filter F in * center A, but not in center B, the filter F will not be returned) * - * @param string[] $types * @param \Chill\MainBundle\Entity\Center[] $centers the centers where the user have access to * @return FilterInterface[] a \Generator that contains filters. The key is the filter's alias */ - public function &getFiltersApplyingOn(array $types, array $centers = null) + public function &getFiltersApplyingOn(ExportInterface $export, array $centers = null) { foreach ($this->filters as $alias => $filter) { - if (in_array($filter->applyOn(), $types) - && $this->isGrantedForElement($filter, $centers)) { + if (in_array($filter->applyOn(), $export->supportsModifiers()) + && $this->isGrantedForElement($filter, $export, $centers)) { yield $alias => $filter; } } @@ -274,11 +311,28 @@ class ExportManager * @param array|null $centers, if null, the function take into account all the reachables centers for the current user and the role given by element::requiredRole * @return boolean */ - public function isGrantedForElement(ExportElementInterface $element, array $centers = null) + public function isGrantedForElement(ExportElementInterface $element, ExportInterface $export = NULL, array $centers = null) { - if($centers === null) { + if ($element instanceof ExportInterface) { + $role = $element->requiredRole(); + } elseif ($element instanceof ModifierInterface ) { + if (is_null($element->addRole())) { + if (is_null($export)) { + throw new \LogicException("The export should not be null: as the " + . "ModifierInstance element is not an export, we should " + . "be aware of the export to determine which role is required"); + } else { + $role = $export->requiredRole(); + } + } + } else { + throw new \LogicException("The element is not an ModifiersInterface or " + . "an ExportInterface."); + } + + if ($centers === null) { $centers = $this->authorizationHelper->getReachableCenters($this->user, - $element->requiredRole()); + $role); } if (count($centers) === 0) { @@ -286,8 +340,7 @@ class ExportManager } foreach($centers as $center) { - if ($this->authorizationChecker->isGranted( - $element->requiredRole()->getRole(), $center) === false) { + if ($this->authorizationChecker->isGranted($role->getRole(), $center) === false) { //debugging $this->logger->debug('user has no access to element', array( 'method' => __METHOD__, @@ -301,32 +354,16 @@ class ExportManager return true; } - /** - * Return a \Generator containing filter which support type - * - * @param string $types - * @return FilterInterface[] a \Generator that contains filters. The key is the filter's alias - */ - public function &getFiltersSupportingType($type) - { - foreach ($this->filters as $alias => $filter) { - if ($filter->supportsType($type)) { - yield $alias => $filter; - } - } - } - /** * Return a \Generator containing aggregators which support type * - * @param string[] $types * @return AggregatorInterface[] a \Generator that contains aggretagors. The key is the filter's alias */ - public function &getAggregatorsApplyingOn(array $types, array $centers = null) + public function &getAggregatorsApplyingOn(ExportInterface $export, array $centers = null) { foreach ($this->aggregators as $alias => $aggregator) { - if (in_array($aggregator->applyOn(), $types) && - $this->isGrantedForElement($aggregator, $centers)) { + if (in_array($aggregator->applyOn(), $export->supportsModifiers()) && + $this->isGrantedForElement($aggregator, $export, $centers)) { yield $alias => $aggregator; } } @@ -349,10 +386,10 @@ class ExportManager $this->buildCenterReachableScopes($centers, $export)); //handle filters - $this->handleFilters($export, $qb, $data['filters']); + $this->handleFilters($export, $qb, $data['filters'], $centers); //handle aggregators - $this->handleAggregators($export, $qb, $data['aggregators']); + $this->handleAggregators($export, $qb, $data['aggregators'], $centers); $this->logger->debug('current query is '.$qb->getDQL(), array( 'class' => self::class, 'function' => __FUNCTION__ @@ -418,6 +455,13 @@ class ExportManager return $data['pick_formatter']['alias']; } + /** + * Get the Center picked by the user for this export. The data are + * extracted from the PickCenterType data + * + * @param array $data the data from a PickCenterType + * @return \Chill\MainBundle\Entity\Center[] the picked center + */ public function getPickedCenters(array $data) { return $data[PickCenterType::CENTERS_IDENTIFIERS]; @@ -442,6 +486,12 @@ class ExportManager return $usedTypes; } + /** + * Retrieve the filter used in this export. + * + * @param mixed $data the data from the `filters` key of the ExportType + * @return array an array with types + */ private function retrieveUsedFiltersType($data) { $usedTypes = array(); @@ -481,7 +531,7 @@ class ExportManager */ private function retrieveUsedAggregators($data) { - foreach($data as $alias => $aggregatorData) { + foreach ($data as $alias => $aggregatorData) { if ($aggregatorData['enabled'] === true){ yield $alias => $this->getAggregator($alias); } @@ -490,43 +540,75 @@ class ExportManager /** * - * @param ExportInterface $export - * @param QueryBuilder $qb - * @param mixed $data the data under the initial 'filters' data + * @param type $data the data from the filter key of the ExportType */ - private function handleFilters(ExportInterface $export, QueryBuilder $qb, $data) + private function retrieveUsedFilters($data) { - $filters = $this->getFiltersApplyingOn($export->supportsModifiers()); - - foreach($filters as $alias => $filter) { - $this->logger->debug('handling filter '.$alias, array( - 'class' => self::class, 'function' => __FUNCTION__ - )); - - $formData = $data[$alias]; - - if ($formData['enabled'] == true) { - $this->logger->debug('alter query by filter '.$alias, array( - 'class' => self::class, 'function' => __FUNCTION__ - )); - $filter->alterQuery($qb, $formData['form']); - } else { - $this->logger->debug('skipping filter '.$alias.' because not enabled', - array('class' => self::class, 'function' => __FUNCTION__)); + foreach ($data as $alias => $filterData) { + if ($filterData['enabled'] === true) { + yield $alias => $this->getFilter($alias); } } } - private function handleAggregators(ExportInterface $export, QueryBuilder $qb, $data) + /** + * alter the query with selected filters. + * + * This function check the acl. + * + * @param ExportInterface $export + * @param QueryBuilder $qb + * @param mixed $data the data under the initial 'filters' data + * @param \Chill\MainBundle\Entity\Center[] $centers the picked centers + * @throw UnauthorizedHttpException if the user is not authorized + */ + private function handleFilters( + ExportInterface $export, + QueryBuilder $qb, + $data, + array $centers) + { + $filters = $this->retrieveUsedFilters($data); + + foreach($filters as $alias => $filter) { + if ($this->isGrantedForElement($filter, $export, $centers) === false) { + throw new UnauthorizedHttpException("You are not authorized to " + . "use the filter ".$filter->getTitle()); + } + + $formData = $data[$alias]; + + $this->logger->debug('alter query by filter '.$alias, array( + 'class' => self::class, 'function' => __FUNCTION__ + )); + $filter->alterQuery($qb, $formData['form']); + + } + } + + /** + * Alter the query with selected aggregators + * + * Check for acl. If an user is not authorized to see an aggregator, throw an + * UnauthorizedException. + * + * @param ExportInterface $export + * @param QueryBuilder $qb + * @param type $data + * @param \Chill\MainBundle\Entity\Center[] $centers the picked centers + * @throw UnauthorizedHttpException if the user is not authorized + */ + private function handleAggregators( + ExportInterface $export, + QueryBuilder $qb, + $data, + array $center) { - //$aggregators = $this->getAggregatorsApplyingOn($export->supportsModifiers()); $aggregators = $this->retrieveUsedAggregators($data); foreach ($aggregators as $alias => $aggregator) { $formData = $data[$alias]; - //if ($formData['order'] >= 0) { - $aggregator->alterQuery($qb, $formData['form']); - //} + $aggregator->alterQuery($qb, $formData['form']); } } diff --git a/Export/FilterInterface.php b/Export/FilterInterface.php index 0011376a5..249be24d4 100644 --- a/Export/FilterInterface.php +++ b/Export/FilterInterface.php @@ -19,19 +19,19 @@ namespace Chill\MainBundle\Export; -use Doctrine\ORM\QueryBuilder; -use Symfony\Component\Form\FormBuilderInterface; /** + * Interface for filters. + * + * Filter will filter result on the query initiated by Export. Most of the time, + * it will add a `WHERE` clause on this query. + * + * Filters should not add column in `SELECT` clause. * * * @author Julien Fastré */ -interface FilterInterface extends ExportElementInterface +interface FilterInterface extends ModifierInterface { - public function applyOn(); - - public function buildForm(FormBuilderInterface $builder); - - public function alterQuery(QueryBuilder $qb, $data); + } diff --git a/Export/FormatterInterface.php b/Export/FormatterInterface.php index 9fdf9d8ba..2f84793fc 100644 --- a/Export/FormatterInterface.php +++ b/Export/FormatterInterface.php @@ -19,11 +19,41 @@ namespace Chill\MainBundle\Export; +use Symfony\Component\Form\FormBuilderInterface; + /** * * @author Julien Fastré */ interface FormatterInterface { - //put your code here + const TYPE_TABULAR = 'tabular'; + + public function getType(); + + public function getName(); + + /** + * build a form, which will be used to collect data required for the execution + * of this formatter. + * + * @uses appendAggregatorForm + * @param FormBuilderInterface $builder + * @param type $exportAlias + * @param array $aggregatorAliases + */ + public function buildForm(FormBuilderInterface $builder, $exportAlias, array $aggregatorAliases); + + /** + * Generate a response from the data collected on differents ExportElementInterface + * + * @param mixed[] $result The result, as given by the ExportInterface + * @param mixed[] $data collected from the current form + * @param \Chill\MainBundle\Export\ExportInterface $export the export which is executing + * @param \Chill\MainBundle\Export\FilterInterface[] $filters the filters applying on the export. The key will be filters aliases, and the values will be filter's data (from their own form) + * @param \Chill\MainBundle\Export\AggregatorInterface[] $aggregators the aggregators applying on the export. The key will be aggregators aliases, and the values will be aggregator's data (from their own form) + */ + public function getResponse($result, $formatterData, $exportAlias, array $exportData, array $filtersData, + array $aggregatorsData); + } diff --git a/Export/ModifierInterface.php b/Export/ModifierInterface.php new file mode 100644 index 000000000..e0633a1f1 --- /dev/null +++ b/Export/ModifierInterface.php @@ -0,0 +1,58 @@ + + * + * 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; + +use Doctrine\ORM\QueryBuilder; + +/** + * Modifiers modify the export's query. + * + * Known subclasses : AggregatorInterface and FilterInterface + * + * @author Julien Fastré + */ +interface ModifierInterface extends ExportElementInterface +{ + /** + * The role required for executing this Modifier + * + * If null, will used the ExportInterface::requiredRole role from + * the current executing export. + * + * @return NULL|\Symfony\Component\Security\Core\Role\Role A role required to execute this ModifiersInterface + */ + public function addRole(); + + /** + * On which type of Export this ModifiersInterface may apply. + * + * @return string the type on which the Modifiers apply + */ + public function applyOn(); + + /** + * Alter the query initiated by the export, to add the required statements + * (`GROUP BY`, `SELECT`, `WHERE`) + * + * @param QueryBuilder $qb the QueryBuilder initiated by the Export (and eventually modified by other Modifiers) + * @param mixed[] $data the data from the Form (builded by buildForm) + */ + public function alterQuery(QueryBuilder $qb, $data); +} diff --git a/Form/Type/Export/ExportType.php b/Form/Type/Export/ExportType.php index 5e3848767..056dcd452 100644 --- a/Form/Type/Export/ExportType.php +++ b/Form/Type/Export/ExportType.php @@ -59,8 +59,7 @@ class ExportType extends AbstractType } */ //add filters - $filters = $this->exportManager->getFiltersApplyingOn($export->supportsModifiers(), - $options['picked_centers']); + $filters = $this->exportManager->getFiltersApplyingOn($export, $options['picked_centers']); $filterBuilder = $builder->create('filters', 'form', array('compound' => true)); foreach($filters as $alias => $filter) { @@ -74,8 +73,7 @@ class ExportType extends AbstractType //add aggregators $aggregators = $this->exportManager - ->getAggregatorsApplyingOn($export->supportsModifiers(), - $options['picked_centers']); + ->getAggregatorsApplyingOn($export, $options['picked_centers']); $aggregatorBuilder = $builder->create('aggregators', 'form', array('compound' => true)); diff --git a/Tests/Controller/ExportControllerTest.php b/Tests/Controller/ExportControllerTest.php new file mode 100644 index 000000000..d75f2cc71 --- /dev/null +++ b/Tests/Controller/ExportControllerTest.php @@ -0,0 +1,45 @@ + + * + * 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\Tests\Controller; + +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + +/** + * Test the export + * + * @author Julien Fastré + */ +class ExportControllerTest extends WebTestCase +{ + public function testIndex() + { + $client = static::createClient(array(), array( + 'PHP_AUTH_USER' => 'center a_social', + 'PHP_AUTH_PW' => 'password', + 'HTTP_ACCEPT_LANGUAGE' => 'fr_FR' + )); + + $client->request('GET', '/fr/exports/'); + + $this->assertTrue($client->getResponse()->isSuccessful(), + "assert the list is shown"); + } + +} diff --git a/Tests/Export/ExportManagerTest.php b/Tests/Export/ExportManagerTest.php new file mode 100644 index 000000000..c2d7110ae --- /dev/null +++ b/Tests/Export/ExportManagerTest.php @@ -0,0 +1,297 @@ + + * + * 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\Tests\Export; + +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Chill\MainBundle\Export\ExportManager; + +/** + * Test the export manager + * + * + * @author Julien Fastré + */ +class ExportManagerTest extends KernelTestCase +{ + /** + * + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + private $container; + + /** + * + * @var Prophecy\Prophet + */ + private $prophet; + + + + + + public function setUp() + { + self::bootKernel(); + + $this->container = self::$kernel->getContainer(); + + $this->prophet = new \Prophecy\Prophet; + } + + /** + * Create an ExportManager where every element may be replaced by a double. + * + * If null is provided for an element, this is replaced by the equivalent + * from the container; if the user provided is null, this is replaced by the + * user 'center a_social' from database. + * + * @param \Psr\Log\LoggerInterface $logger + * @param \Doctrine\ORM\EntityManagerInterface $em + * @param \Symfony\Component\Security\Core\Authorization\AuthorizationChecker $authorizationChecker + * @param \Chill\MainBundle\Security\Authorization\AuthorizationHelper $authorizationHelper + * @param \Symfony\Component\Security\Core\User\UserInterface $user + * @return ExportManager + */ + public function createExportManager( + \Psr\Log\LoggerInterface $logger = null, + \Doctrine\ORM\EntityManagerInterface $em = null, + \Symfony\Component\Security\Core\Authorization\AuthorizationChecker $authorizationChecker = null, + \Chill\MainBundle\Security\Authorization\AuthorizationHelper $authorizationHelper = null, + \Symfony\Component\Security\Core\User\UserInterface $user = null + ) + { + $localUser = $user === NULL ? $this->container->get('doctrine.orm.entity_manager') + ->getRepository('ChillMainBundle:User') + ->findOneBy(array('username' => 'center a_social')) : + $user; + $token = new \Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken($localUser, 'password', 'provider'); + $tokenStorage = new \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(); + $tokenStorage->setToken($token); + + return new ExportManager( + $logger === NULL ? $this->container->get('logger') : $logger, + $em === NULL ? $this->container->get('doctrine.orm.entity_manager') : $em, + $authorizationChecker === NULL ? $this->container->get('security.authorization_checker') : $authorizationChecker, + $authorizationHelper === NULL ? $this->container->get('chill.main.security.authorization.helper') : $authorizationHelper, + $tokenStorage) + ; + } + + + public function testGetExportsWithoutGranting() + { + $exportManager = $this->createExportManager(); + + //create an export and add it to ExportManager + $export = $this->prophet->prophesize(); + $export->willImplement('Chill\MainBundle\Export\ExportInterface'); + $exportManager->addExport($export->reveal(), 'dummy'); + + $exports = iterator_to_array($exportManager->getExports(false)); + + $this->assertGreaterThan(0, count($exports)); + $this->assertContains($export->reveal(), $exports); + $this->assertContains('dummy', array_keys($exports)); + } + + public function testGetExistingExportsTypes() + { + $exportManager = $this->createExportManager(); + + //create an export and add it to ExportManager + $export = $this->prophet->prophesize(); + $export->willImplement('Chill\MainBundle\Export\ExportInterface'); + $export->getType()->willReturn('my_type'); + $exportManager->addExport($export->reveal(), 'dummy'); + + $this->assertContains('my_type', $exportManager->getExistingExportsTypes()); + + } + + public function testGetExport() + { + $exportManager = $this->createExportManager(); + + //create an export and add it to ExportManager + $export = $this->prophet->prophesize(); + $export->willImplement('Chill\MainBundle\Export\ExportInterface'); + $exportManager->addExport($export->reveal(), 'dummy'); + + $obtained = $exportManager->getExport('dummy'); + + $this->assertInstanceof('Chill\MainBundle\Export\ExportInterface', $obtained); + } + + /** + * @expectedException \RuntimeException + */ + public function testGetExportNonExistant() + { + $exportManager = $this->createExportManager(); + + $exportManager->getExport('non existing'); + } + + public function testGetFilter() + { + $exportManager = $this->createExportManager(); + + //create a filter and add it to ExportManager + $filter = $this->prophet->prophesize(); + $filter->willImplement('Chill\MainBundle\Export\FilterInterface'); + $exportManager->addFilter($filter->reveal(), 'dummy'); + + $obtained = $exportManager->getFilter('dummy'); + + $this->assertInstanceof('Chill\MainBundle\Export\FilterInterface', $obtained); + } + + + /** + * @expectedException \RuntimeException + */ + public function testGetFilterNonExistant() + { + $exportManager = $this->createExportManager(); + + $exportManager->getFilter('non existing'); + } + + public function testGetFilters() + { + $exportManager = $this->createExportManager(); + + //create three filters and add them to ExportManager + $filterFoo = $this->prophet->prophesize(); + $filterFoo->willImplement('Chill\MainBundle\Export\FilterInterface'); + $filterBar = $this->prophet->prophesize(); + $filterBar->willImplement('Chill\MainBundle\Export\FilterInterface'); + $filterFooBar = $this->prophet->prophesize(); + $filterFooBar->willImplement('Chill\MainBundle\Export\FilterInterface'); + $exportManager->addFilter($filterFoo->reveal(), 'foo'); + $exportManager->addFilter($filterBar->reveal(), 'bar'); + $exportManager->addFilter($filterFooBar->reveal(), 'foobar'); + + $obtained = iterator_to_array($exportManager->getFilters(array('foo', 'bar'))); + + $this->assertContains($filterBar->reveal(), $obtained); + $this->assertContains($filterFoo->reveal(), $obtained); + $this->assertNotContains($filterFooBar->reveal(), $obtained); + } + + public function testGetAggregator() + { + $exportManager = $this->createExportManager(); + + //create a filter and add it to ExportManager + $agg = $this->prophet->prophesize(); + $agg->willImplement('Chill\MainBundle\Export\AggregatorInterface'); + $exportManager->addAggregator($agg->reveal(), 'dummy'); + + $obtained = $exportManager->getAggregator('dummy'); + + $this->assertInstanceof('Chill\MainBundle\Export\AggregatorInterface', $obtained); + } + + + /** + * @expectedException \RuntimeException + */ + public function testGetAggregatorNonExistant() + { + $exportManager = $this->createExportManager(); + + $exportManager->getAggregator('non existing'); + } + + public function testGetAggregators() + { + $exportManager = $this->createExportManager(); + + //create three filters and add them to ExportManager + $aggFoo = $this->prophet->prophesize(); + $aggFoo->willImplement('Chill\MainBundle\Export\AggregatorInterface'); + $aggBar = $this->prophet->prophesize(); + $aggBar->willImplement('Chill\MainBundle\Export\AggregatorInterface'); + $aggFooBar = $this->prophet->prophesize(); + $aggFooBar->willImplement('Chill\MainBundle\Export\AggregatorInterface'); + $exportManager->addAggregator($aggFoo->reveal(), 'foo'); + $exportManager->addAggregator($aggBar->reveal(), 'bar'); + $exportManager->addAggregator($aggFooBar->reveal(), 'foobar'); + + $obtained = iterator_to_array($exportManager->getAggregators(array('foo', 'bar'))); + + $this->assertContains($aggBar->reveal(), $obtained); + $this->assertContains($aggFoo->reveal(), $obtained); + $this->assertNotContains($aggFooBar->reveal(), $obtained); + } + + public function testGetFormatter() + { + $exportManager = $this->createExportManager(); + + //create a formatter + $formatter = $this->prophet->prophesize(); + $formatter->willImplement('Chill\MainBundle\Export\FormatterInterface'); + $exportManager->addFormatter($formatter->reveal(), 'dummy'); + + $obtained = $exportManager->getFormatter('dummy'); + + $this->assertInstanceOf('Chill\MainBundle\Export\FormatterInterface', $obtained); + } + + /** + * @expectedException \RuntimeException + */ + public function testNonExistingFormatter() + { + $exportManager = $this->createExportManager(); + + $exportManager->getFormatter('non existing'); + } + + public function testFormattersByTypes() + { + $exportManager = $this->createExportManager(); + + //create a formatter + $formatterFoo = $this->prophet->prophesize(); + $formatterFoo->willImplement('Chill\MainBundle\Export\FormatterInterface'); + $formatterFoo->getType()->willReturn('foo'); + $formatterBar = $this->prophet->prophesize(); + $formatterBar->willImplement('Chill\MainBundle\Export\FormatterInterface'); + $formatterBar->getType()->willReturn('bar'); + $exportManager->addFormatter($formatterFoo->reveal(), 'foo'); + $exportManager->addFormatter($formatterBar->reveal(), 'bar'); + + $obtained = $exportManager->getFormattersByTypes(array('foo')); + + $this->assertContains($formatterFoo->reveal(), $obtained); + $this->assertNotContains($formatterBar->reveal(), $obtained); + } + + public function testIsGrantedForElementUserIsGranted() + { + $this->markTestSkipped(); + } + + + +}