From 175448f56225b5bb40a872c54c0b0e9c6d7d19db Mon Sep 17 00:00:00 2001 From: Nicolas Le Goff Date: Mon, 22 Oct 2012 14:15:48 +0200 Subject: [PATCH] Add '/prod/download/' controller to download a set of documents --- lib/Alchemy/Phrasea/Application/Root.php | 2 + .../Phrasea/Controller/Prod/Download.php | 111 ++++++++++++++++++ .../Phrasea/Controller/Prod/DownloadTest.php | 48 ++++++++ 3 files changed, 161 insertions(+) create mode 100644 lib/Alchemy/Phrasea/Controller/Prod/Download.php create mode 100644 tests/Alchemy/Phrasea/Controller/Prod/DownloadTest.php diff --git a/lib/Alchemy/Phrasea/Application/Root.php b/lib/Alchemy/Phrasea/Application/Root.php index a6fc3cc788..097250a898 100644 --- a/lib/Alchemy/Phrasea/Application/Root.php +++ b/lib/Alchemy/Phrasea/Application/Root.php @@ -34,6 +34,7 @@ use Alchemy\Phrasea\Controller\Admin\TaskManager; use Alchemy\Phrasea\Controller\Admin\Users; use Alchemy\Phrasea\Controller\Prod\Basket; use Alchemy\Phrasea\Controller\Prod\Bridge; +use Alchemy\Phrasea\Controller\Prod\Download; use Alchemy\Phrasea\Controller\Prod\Edit; use Alchemy\Phrasea\Controller\Prod\Export; use Alchemy\Phrasea\Controller\Prod\Feed; @@ -134,6 +135,7 @@ return call_user_func(function($environment = null) { $app->mount('/prod/query/', new Query()); $app->mount('/prod/order/', new Order()); $app->mount('/prod/baskets', new Basket()); + $app->mount('/prod/download', new Download()); $app->mount('/prod/story', new Story()); $app->mount('/prod/WorkZone', new WorkZone()); $app->mount('/prod/lists', new UsrLists()); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Download.php b/lib/Alchemy/Phrasea/Controller/Prod/Download.php new file mode 100644 index 0000000000..18dac3f5e6 --- /dev/null +++ b/lib/Alchemy/Phrasea/Controller/Prod/Download.php @@ -0,0 +1,111 @@ +before(function(Request $request) use ($app) { + $app['firewall']->requireAuthentication(); + }); + + /** + * Download a set of documents + * + * name : download + * + * description : Download a set of documents + * + * method : POST + * + * parameters : none + * + * return : Redirect Response + */ + $controllers->post('/', $this->call('download')) + ->bind('download'); + + + return $controllers; + } + + /** + * Download a set of documents + * + * @param Application $app + * @param Request $request + * @return RedirectResponse + */ + public function download(Application $app, Request $request) + { + $lst = $request->request->get('lst'); + $ssttid = $request->request->get('ssttid', ''); + $subdefs = $request->request->get('obj', array()); + + $download = new \set_export($app, $lst, $ssttid); + + $list = $download->prepare_export( + $app['phraseanet.user'], + $app['filesystem'], + $subdefs, + $request->request->get('title') === 'title' ? true : false, + $request->request->get('businessfields') + ); + + $list['export_name'] = sprintf('%s.zip', $download->getExportName()); + + $token = \random::getUrlToken( + $app, + \random::TYPE_DOWNLOAD, + $app['phraseanet.user']->get_id(), + new \DateTime('+3 hours'), // Token lifetime + serialize($list) + ); + + if (!$token) { + throw new \RuntimeException('Download token could not be generated'); + } + + $app['events-manager']->trigger('__DOWNLOAD__', array( + 'lst' => $lst, + 'downloader' => $app['phraseanet.user']->get_id(), + 'subdefs' => $subdefs, + 'from_basket' => $ssttid, + 'export_file' => $download->getExportName() + )); + + return $app->redirect('/download/' . $token .'/'); + } + + /** + * Prefix the method to call with the controller class name + * + * @param string $method The method to call + * @return string + */ + private function call($method) + { + return sprintf('%s::%s', __CLASS__, $method); + } +} diff --git a/tests/Alchemy/Phrasea/Controller/Prod/DownloadTest.php b/tests/Alchemy/Phrasea/Controller/Prod/DownloadTest.php new file mode 100644 index 0000000000..48f15e23a1 --- /dev/null +++ b/tests/Alchemy/Phrasea/Controller/Prod/DownloadTest.php @@ -0,0 +1,48 @@ +getMockBuilder('\eventsmanager_broker') + ->disableOriginalConstructor() + ->getMock(); + + $eventManagerStub->expects($this->once()) + ->method('trigger') + ->with($this->equalTo('__DOWNLOAD__'), $this->isType('array')) + ->will($this->returnValue(null)); + + self::$DI['app']['events-manager'] = $eventManagerStub; + + self::$DI['client']->request('POST', '/prod/download/', array( + 'lst' => self::$DI['record_1']->get_serialize_key(), + 'ssttid' => '', + 'obj' => array('preview', 'document'), + 'title' => 'export_title_test', + 'businessfields' => '1' + )); + + $response = self::$DI['client']->getResponse(); + $this->assertTrue($response->isRedirect()); + $this->assertRegExp('#download/[a-zA-Z0-9]*/$#', $response->headers->get('location')); + } + + /** + * @covers Alchemy\Phrasea\Controller\Prod\Download::connect + * @covers Alchemy\Phrasea\Controller\Prod\Download::call + */ + public function testRequireAuthentication() + { + $this->logout(self::$DI['app']); + self::$DI['client']->request('POST', '/prod/download/'); + $this->assertTrue(self::$DI['client']->getResponse()->isRedirect()); + } +}