From f117817e8705d76a362d2605c133822aa8c0292e Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 30 May 2013 19:04:49 +0200 Subject: [PATCH] Implementation of doctrine entities --- lib/Alchemy/Phrasea/Application.php | 2 + lib/Alchemy/Phrasea/Controller/Prod/Feed.php | 154 ++++++---- lib/Alchemy/Phrasea/Controller/Prod/Root.php | 9 +- .../Phrasea/Controller/Root/RSSFeeds.php | 47 ++-- .../Core/Provider/FeedServiceProvider.php | 34 +++ lib/Alchemy/Phrasea/Feed/Aggregate.php | 149 ++++++++++ .../Phrasea/Feed/AggregateLinkGenerator.php | 74 +++++ lib/Alchemy/Phrasea/Feed/AggregateToken.php | 111 ++++++++ lib/Alchemy/Phrasea/Feed/FeedInterface.php | 21 ++ lib/Alchemy/Phrasea/Feed/Link.php | 68 +++++ lib/Alchemy/Phrasea/Feed/LinkGenerator.php | 80 ++++++ lib/Alchemy/Phrasea/Feed/LinkInterface.php | 30 ++ lib/Doctrine/Entities/Feed.php | 124 +++++--- lib/Doctrine/Entities/FeedEntry.php | 8 +- lib/Doctrine/Entities/FeedItem.php | 4 - .../prod/actions/publish/publish.html.twig | 10 +- templates/web/prod/feeds/entry.html.twig | 2 +- .../web/prod/feeds/entry_macro.html.twig | 40 +-- templates/web/prod/feeds/feeds.html.twig | 29 +- templates/web/prod/index.html.twig | 10 +- .../Phrasea/Controller/Prod/FeedTest.php | 264 +++++++++--------- .../Core/Provider/FeedServiceProviderTest.php | 25 ++ .../Feed/AggregateLinkGeneratorTest.php | 129 +++++++++ .../Tests/Phrasea/Feed/LinkGeneratorTest.php | 126 +++++++++ tests/classes/PhraseanetPHPUnitAbstract.php | 126 +++++++++ 25 files changed, 1374 insertions(+), 302 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Core/Provider/FeedServiceProvider.php create mode 100644 lib/Alchemy/Phrasea/Feed/Aggregate.php create mode 100644 lib/Alchemy/Phrasea/Feed/AggregateLinkGenerator.php create mode 100644 lib/Alchemy/Phrasea/Feed/AggregateToken.php create mode 100644 lib/Alchemy/Phrasea/Feed/FeedInterface.php create mode 100644 lib/Alchemy/Phrasea/Feed/Link.php create mode 100644 lib/Alchemy/Phrasea/Feed/LinkGenerator.php create mode 100644 lib/Alchemy/Phrasea/Feed/LinkInterface.php create mode 100644 tests/Alchemy/Tests/Phrasea/Core/Provider/FeedServiceProviderTest.php create mode 100644 tests/Alchemy/Tests/Phrasea/Feed/AggregateLinkGeneratorTest.php create mode 100644 tests/Alchemy/Tests/Phrasea/Feed/LinkGeneratorTest.php diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php index 5c400af903..ae485b1af3 100644 --- a/lib/Alchemy/Phrasea/Application.php +++ b/lib/Alchemy/Phrasea/Application.php @@ -84,6 +84,7 @@ use Alchemy\Phrasea\Core\Provider\CacheServiceProvider; use Alchemy\Phrasea\Core\Provider\ConfigurationServiceProvider; use Alchemy\Phrasea\Core\Provider\ConfigurationTesterServiceProvider; use Alchemy\Phrasea\Core\Provider\FileServeServiceProvider; +use Alchemy\Phrasea\Core\Provider\FeedServiceProvider; use Alchemy\Phrasea\Core\Provider\FtpServiceProvider; use Alchemy\Geonames\GeonamesServiceProvider; use Alchemy\Phrasea\Core\Provider\InstallerServiceProvider; @@ -200,6 +201,7 @@ class Application extends SilexApplication $this->register(new ImagineServiceProvider()); $this->register(new JMSSerializerServiceProvider()); $this->register(new FFMpegServiceProvider()); + $this->register(new FeedServiceProvider()); $this->register(new FilesystemServiceProvider()); $this->register(new FtpServiceProvider()); $this->register(new GeonamesServiceProvider()); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Feed.php b/lib/Alchemy/Phrasea/Controller/Prod/Feed.php index b85df97637..0290f8ce91 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Feed.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Feed.php @@ -11,7 +11,10 @@ namespace Alchemy\Phrasea\Controller\Prod; +use Alchemy\Phrasea\Feed\Aggregate; +use Alchemy\Phrasea\Feed\AggregateLinkGenerator; use Alchemy\Phrasea\Controller\RecordsRequest; +use Alchemy\Phrasea\Feed\LinkGenerator; use Silex\Application; use Silex\ControllerProviderInterface; use Symfony\Component\HttpFoundation\Request; @@ -39,10 +42,10 @@ class Feed implements ControllerProviderInterface * I got a selection of docs, which publications are available forthese docs ? */ $controllers->post('/requestavailable/', function(Application $app, Request $request) { - $feeds = \Feed_Collection::load_all($app, $app['authentication']->getUser()); + $feeds = $app["EM"]->getRepository("Entities\Feed")->getAllForUser($app['authentication']->getUser()); $publishing = RecordsRequest::fromRequest($app, $request, true, array(), array('bas_chupub')); - return $app['twig']->render('prod/actions/publish/publish.html.twig', array('publishing' => $publishing, 'feeds' => $feeds)); + return $app['twig']->render('prod/actions/publish/publish.html.twig', array('publishing' => $publishing, 'feeds' => $feeds)); }); /** @@ -50,24 +53,42 @@ class Feed implements ControllerProviderInterface */ $controllers->post('/entry/create/', function(Application $app, Request $request) { try { - $feed = new \Feed_Adapter($app, $request->request->get('feed_id')); - $publisher = \Feed_Publisher_Adapter::getPublisher($app['phraseanet.appbox'], $feed, $app['authentication']->getUser()); - + $feed = $app["EM"]->getRepository("Entities\Feed")->find($request->request->get('feed_id')); + $publisher = $app["EM"]->getRepository("Entities\FeedPublisher")->findByUser($feed, $app['authentication']->getUser()); $title = $request->request->get('title'); $subtitle = $request->request->get('subtitle'); $author_name = $request->request->get('author_name'); - $author_mail = $request->request->get('author_mail'); + $author_email = $request->request->get('author_email'); - $entry = \Feed_Entry_Adapter::create($app, $feed, $publisher, $title, $subtitle, $author_name, $author_mail); + $entry = new \Entities\FeedEntry(); + $entry->setFeed($feed); + $entry->setPublisher($publisher); + $entry->setTitle($title); + $entry->setSubtitle($subtitle); + $entry->setAuthorName($author_name); + $entry->setAuthorEmail($author_email); + + $feed->addEntry($entry); $publishing = RecordsRequest::fromRequest($app, $request, true, array(), array('bas_chupub')); - foreach ($publishing as $record) { - $item = \Feed_Entry_Item::create($app['phraseanet.appbox'], $entry, $record); + $item = new \Entities\FeedItem(); + $item->setEntry($entry); + $item->setRecordId($record->get_record_id()); + $item->setSbasId($record->get_sbas_id()); + $entry->addItem($item); + $app["EM"]->persist($item); } - $datas = array('error' => false, 'message' => false); + + $app["EM"]->persist($entry); + $app["EM"]->persist($feed); + $app["EM"]->flush(); + + $app['events-manager']->trigger('__FEED_ENTRY_CREATE__', array('entry_id' => $entry->getId()), $entry); + + $datas = array('error' => false, 'message' => false); } catch (\Exception $e) { - $datas = array('error' => true, 'message' => _('An error occured'), 'details' => $e->getMessage()); + $datas = array('error' => true, 'message' => _('An error occured'), 'details' => $e->getMessage()); } return $app->json($datas); @@ -78,13 +99,13 @@ class Feed implements ControllerProviderInterface }); $controllers->get('/entry/{id}/edit/', function(Application $app, Request $request, $id) { - $entry = \Feed_Entry_Adapter::load_from_id($app, $id); + $entry = $app["EM"]->getRepository("Entities\FeedEntry")->find($id); - if (!$entry->is_publisher($app['authentication']->getUser())) { + if (!$entry->isPublisher($app['authentication']->getUser())) { throw new AccessDeniedHttpException(); } - $feeds = \Feed_Collection::load_all($app, $app['authentication']->getUser()); + $feeds = $app["EM"]->getRepository("Entities\Feed")->findAll(); $datas = $app['twig']->render('prod/actions/publish/publish_edit.html.twig', array('entry' => $entry, 'feeds' => $feeds)); @@ -97,40 +118,44 @@ class Feed implements ControllerProviderInterface }); $controllers->post('/entry/{id}/update/', function(Application $app, Request $request, $id) { - $datas = array('error' => true, 'message' => '', 'datas' => ''); + $datas = array('error' => true, 'message' => '', 'datas' => ''); try { - $app['phraseanet.appbox']->get_connection()->beginTransaction(); + $entry = $app["EM"]->getRepository("Entities\FeedEntry")->find($id); - $entry = \Feed_Entry_Adapter::load_from_id($app, $id); - - if (!$entry->is_publisher($app['authentication']->getUser())) { + if (null === $entry) { + throw new NotFoundHttpException(); + } + if (!$entry->isPublisher($app['authentication']->getUser())) { throw new AccessDeniedHttpException(); } $title = $request->request->get('title'); $subtitle = $request->request->get('subtitle'); $author_name = $request->request->get('author_name'); - $author_mail = $request->request->get('author_mail'); + $author_mail = $request->request->get('author_email'); - $entry->set_author_email($author_mail) - ->set_author_name($author_name) - ->set_title($title) - ->set_subtitle($subtitle); + $entry->setAuthorEmail($author_mail) + ->setAuthorName($author_name) + ->setTitle($title) + ->setSubtitle($subtitle); - $current_feed_id = $entry->get_feed()->get_id(); + $current_feed_id = $entry->getFeed()->getId(); $new_feed_id = $request->request->get('feed_id', $current_feed_id); if ($current_feed_id != $new_feed_id) { try { - $new_feed = \Feed_Adapter::load_with_user($app, $app['authentication']->getUser(), $new_feed_id); + $new_feed = $app["EM"]->getRepository("Entities\Feed")->loadWithUser($app, $app['authentication']->getUser(), $new_feed_id); } catch (NotFoundHttpException $e) { throw new AccessDeniedHttpException('You have no access to this feed'); } - if (!$new_feed->is_publisher($app['authentication']->getUser())) { - throw new AccessDeniedHttpException('You are not publisher of this feed'); + if ($new_feed === null) { + throw new NotFoundHttpException(); } - $entry->set_feed($new_feed); + if (!$new_feed->isPublisher($app['authentication']->getUser())) { + throw new \Exception_Forbidden('You are not publisher of this feed'); + } + $entry->setFeed($new_feed); } $items = explode(';', $request->request->get('sorted_lst')); @@ -141,26 +166,26 @@ class Feed implements ControllerProviderInterface continue; } - $item = new \Feed_Entry_Item($app['phraseanet.appbox'], $entry, $item_sort_datas[0]); - - $item->set_ord($item_sort_datas[1]); + $item = new \entities\FeedItem($entry, $item_sort_datas[0]); + $item->setEntry($entry); + $entry->addItem($item); + $item->setOrd($item_sort_datas[1]); + $app["EM"]->persist($item); } - $app['phraseanet.appbox']->get_connection()->commit(); + + $app["EM"]->persist($entry); + $app["EM"]->flush(); $entry = $app['twig']->render('prod/feeds/entry.html.twig', array('entry' => $entry)); - $datas = array('error' => false, 'message' => 'succes', 'datas' => $entry); + $datas = array('error' => false, 'message' => 'succes', 'datas' => $entry); } catch (\Exception_Feed_EntryNotFound $e) { - $app['phraseanet.appbox']->get_connection()->rollBack(); $datas['message'] = _('Feed entry not found'); } catch (NotFoundHttpException $e) { - $app['phraseanet.appbox']->get_connection()->rollBack(); $datas['message'] = _('Feed not found'); } catch (AccessDeniedHttpException $e) { - $app['phraseanet.appbox']->get_connection()->rollBack(); $datas['message'] = _('You are not authorized to access this feed'); } catch (\Exception $e) { - $app['phraseanet.appbox']->get_connection()->rollBack(); $datas['message'] = $e->getMessage(); } @@ -172,26 +197,24 @@ class Feed implements ControllerProviderInterface }); $controllers->post('/entry/{id}/delete/', function(Application $app, Request $request, $id) { - $datas = array('error' => true, 'message' => ''); + $datas = array('error' => true, 'message' => ''); try { - $app['phraseanet.appbox']->get_connection()->beginTransaction(); + $entry = $app["EM"]->getRepository("Entities\FeedEntry")->find($id); - $entry = \Feed_Entry_Adapter::load_from_id($app, $id); - - if (!$entry->is_publisher($app['authentication']->getUser()) - && $entry->get_feed()->is_owner($app['authentication']->getUser()) === false) { + if (null === $entry) { + throw new NotFoundHttpException(); + } + if (!$entry->isPublisher($app['authentication']->getUser()) && $entry->getFeed()->isOwner($app['authentication']->getUser()) === false) { throw new AccessDeniedHttpException(_('Action Forbidden : You are not the publisher')); } - $entry->delete(); + $app["EM"]->remove($entry); + $app["EM"]->flush(); - $app['phraseanet.appbox']->get_connection()->commit(); - $datas = array('error' => false, 'message' => 'succes'); - } catch (\Exception_Feed_EntryNotFound $e) { - $app['phraseanet.appbox']->get_connection()->rollBack(); + $datas = array('error' => false, 'message' => 'succes'); + } catch (NotFoundHttpException $e) { $datas['message'] = _('Feed entry not found'); } catch (\Exception $e) { - $app['phraseanet.appbox']->get_connection()->rollBack(); $datas['message'] = $e->getMessage(); } @@ -207,13 +230,13 @@ class Feed implements ControllerProviderInterface $page = (int) $request->query->get('page'); $page = $page > 0 ? $page : 1; - $feeds = \Feed_Collection::load_all($app, $app['authentication']->getUser()); + $feeds = $app["EM"]->getRepository("Entities\Feed")->findAll(); $datas = $app['twig']->render('prod/feeds/feeds.html.twig' , array( 'feeds' => $feeds - , 'feed' => $feeds->get_aggregate() - , 'page' => $page + , 'feed' => new Aggregate($app, $feeds) + , 'page' => $page ) ); @@ -224,10 +247,10 @@ class Feed implements ControllerProviderInterface $page = (int) $request->query->get('page'); $page = $page > 0 ? $page : 1; - $feed = \Feed_Adapter::load_with_user($app, $app['authentication']->getUser(), $id); - $feeds = \Feed_Collection::load_all($app, $app['authentication']->getUser()); + $feed = $app["EM"]->getRepository("Entities\Feed")->loadWithUser($app, $app['authentication']->getUser(), $id); + $feeds = $app["EM"]->getRepository("Entities\Feed")->findAll(); - $datas = $app['twig']->render('prod/feeds/feeds.html.twig', array('feed' => $feed, 'feeds' => $feeds, 'page' => $page)); + $datas = $app['twig']->render('prod/feeds/feeds.html.twig', array('feed' => $feed, 'feeds' => $feeds, 'page' => $page)); return new Response($datas); }) @@ -237,12 +260,18 @@ class Feed implements ControllerProviderInterface $controllers->get('/subscribe/aggregated/', function(Application $app, Request $request) { $renew = ($request->query->get('renew') === 'true'); - $feeds = \Feed_Collection::load_all($app, $app['authentication']->getUser()); + $feeds = $app["EM"]->getRepository("Entities\Feed")->findAll(); + + $aggregateGenerator = new AggregateLinkGenerator($app['url_generator'], $app['EM'], $app['tokens']); + + $aggregate = new Aggregate($app, $feeds); + + $link = $aggregateGenerator->generate($aggregate, $app['authentication']->getUser(), AggregateLinkGenerator::FORMAT_RSS, null, $renew); $output = array( 'texte' => '

' . _('publication::Voici votre fil RSS personnel. Il vous permettra d\'etre tenu au courrant des publications.') . '

' . _('publications::Ne le partagez pas, il est strictement confidentiel') . '

-
', +
', 'titre' => _('publications::votre rss personnel') ); @@ -251,12 +280,17 @@ class Feed implements ControllerProviderInterface $controllers->get('/subscribe/{id}/', function(Application $app, Request $request, $id) { $renew = ($request->query->get('renew') === 'true'); - $feed = \Feed_Adapter::load_with_user($app, $app['authentication']->getUser(), $id); + + $feed = $app["EM"]->getRepository("Entities\Feed")->loadWithUser($app, $app['authentication']->getUser(), $id); + + $linkGenerator = new LinkGenerator($app['url_generator'], $app['EM'], $app['tokens']); + + $link = $linkGenerator->generate($feed, $app['authentication']->getUser(), LinkGenerator::FORMAT_RSS, null, $renew); $output = array( 'texte' => '

' . _('publication::Voici votre fil RSS personnel. Il vous permettra d\'etre tenu au courrant des publications.') . '

' . _('publications::Ne le partagez pas, il est strictement confidentiel') . '

-
', +
', 'titre' => _('publications::votre rss personnel') ); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Root.php b/lib/Alchemy/Phrasea/Controller/Prod/Root.php index 75d889bc39..3d85e8f16d 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Root.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Root.php @@ -11,6 +11,7 @@ namespace Alchemy\Phrasea\Controller\Prod; +use \Alchemy\Phrasea\Feed\Aggregate; use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Exception\SessionNotFound; use Silex\Application as SilexApplication; @@ -72,8 +73,10 @@ class Root implements ControllerProviderInterface $cssfile = '000000'; } - $user_feeds = \Feed_Collection::load_all($app, $app['authentication']->getUser()); - $feeds = array_merge(array($user_feeds->get_aggregate()), $user_feeds->get_feeds()); +// $user_feeds = \Feed_Collection::load_all($app, $app['authentication']->getUser()); +// $feeds = array_merge(array($user_feeds->get_aggregate()), $user_feeds->get_feeds()); + $user_feeds = $app["EM"]->getRepository("Entities\Feed")->getAllForUser($app['authentication']->getUser()); + $aggregate = new Aggregate($app, $user_feeds); $thjslist = ""; @@ -115,7 +118,7 @@ class Root implements ControllerProviderInterface 'GV_thesaurus' => $app['phraseanet.registry']->get('GV_thesaurus'), 'cgus_agreement' => \databox_cgu::askAgreement($app), 'css' => $css, - 'feeds' => $feeds, + 'aggregate' => $aggregate, 'GV_google_api' => $app['phraseanet.registry']->get('GV_google_api'), 'queries_topics' => $queries_topics, 'search_status' => \databox_status::getSearchStatus($app), diff --git a/lib/Alchemy/Phrasea/Controller/Root/RSSFeeds.php b/lib/Alchemy/Phrasea/Controller/Root/RSSFeeds.php index 7855fbf691..fb00b5304c 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/RSSFeeds.php +++ b/lib/Alchemy/Phrasea/Controller/Root/RSSFeeds.php @@ -28,45 +28,45 @@ class RSSFeeds implements ControllerProviderInterface $controllers = $app['controllers_factory']; $display_feed = function(Application $app, $feed, $format, $page, $user = null) { - $total = $feed->get_count_total_entries(); + $total = $feed->getCountTotalEntries(); $perPage = 5; - $entries = $feed->get_entries((($page - 1) * $perPage), $perPage); + $entries = $feed->getEntries((($page - 1) * $perPage), $perPage); - if ($format == \Feed_Adapter::FORMAT_RSS) { + if ($format == \Entities\Feed::FORMAT_RSS) { $content = new \Feed_XML_RSS(); } - if ($format == \Feed_Adapter::FORMAT_ATOM) { + if ($format == \Entities\Feed::FORMAT_ATOM) { $content = new \Feed_XML_Atom(); } - if ($format == \Feed_Adapter::FORMAT_COOLIRIS) { + if ($format == \Entities\Feed::FORMAT_COOLIRIS) { $content = new \Feed_XML_Cooliris(); } if ($user instanceof \User_Adapter) - $link = $feed->get_user_link($app['phraseanet.registry'], $user, $format, $page); + $link = $feed->getUserLink($app['phraseanet.registry'], $user, $format, $page); else $link = $feed->get_homepage_link($app['phraseanet.registry'], $format, $page); $content->set_updated_on(new \DateTime()); - $content->set_title($feed->get_title()); - $content->set_subtitle($feed->get_subtitle()); + $content->set_title($feed->getTitle()); + $content->set_subtitle($feed->getSubtitle()); $content->set_generator('Phraseanet'); $content->set_link($link); if ($user instanceof \User_Adapter) { if ($page > 1) - $content->set_previous_page($feed->get_user_link($app['phraseanet.registry'], $user, $format, ($page - 1))); + $content->set_previous_page($feed->getUserLink($app['phraseanet.registry'], $user, $format, ($page - 1))); if ($total > ($page * $perPage)) - $content->set_next_page($feed->get_user_link($app['phraseanet.registry'], $user, $format, ($page + 1))); + $content->set_next_page($feed->getUserLink($app['phraseanet.registry'], $user, $format, ($page + 1))); } else { if ($page > 1) $content->set_previous_page($feed->get_homepage_link($app['phraseanet.registry'], $format, ($page - 1))); if ($total > ($page * $perPage)) $content->set_next_page($feed->get_homepage_link($app['phraseanet.registry'], $format, ($page + 1))); } - foreach ($entries->get_entries() as $entry) + foreach ($entries->getEntries() as $entry) $content->set_item($entry); $render = $content->render(); @@ -77,9 +77,10 @@ class RSSFeeds implements ControllerProviderInterface }; $controllers->get('/feed/{id}/{format}/', function(Application $app, $id, $format) use ($display_feed) { - $feed = new \Feed_Adapter($app, $id); + // $feed = new \Feed_Adapter($app, $id); + $feed = $app["EM"]->getRepository("Entities\Feed")->find($id); - if (!$feed->is_public()) { + if (!$feed->isPublic()) { return new Response('Forbidden', 403); } @@ -95,8 +96,8 @@ class RSSFeeds implements ControllerProviderInterface ->assert('format', '(rss|atom)'); $controllers->get('/userfeed/{token}/{id}/{format}/', function(Application $app, $token, $id, $format) use ($display_feed) { - $token = new \Feed_Token($app, $token, $id); - $feed = $token->get_feed(); + $token = $app["EM"]->getRepository("Entities\FeedToken")->findBy(array("id" => $id)); + $feed = $token->getFeed(); $request = $app['request']; @@ -110,8 +111,8 @@ class RSSFeeds implements ControllerProviderInterface ->assert('format', '(rss|atom)'); $controllers->get('/userfeed/aggregated/{token}/{format}/', function(Application $app, $token, $format) use ($display_feed) { - $token = new \Feed_TokenAggregate($app, $token); - $feed = $token->get_feed(); + $token = $app["EM"]->getRepository("Entities\AggregateToken")->findBy(array("id" => $id)); + //$feed = $token->getFeed(); $request = $app['request']; @@ -124,8 +125,10 @@ class RSSFeeds implements ControllerProviderInterface ->assert('format', '(rss|atom)'); $controllers->get('/aggregated/{format}/', function(Application $app, $format) use ($display_feed) { - $feeds = \Feed_Collection::load_public_feeds($app); - $feed = $feeds->get_aggregate(); + //$feeds = \Feed_Collection::load_public_feeds($app); + //$feed = $feeds->get_aggregate(); + $feeds = $app["EM"]->getRepository("Entities\Feed")->findAllPublic(); + $feed = new Aggregate($app, $feeds); $request = $app['request']; $page = (int) $request->query->get('page'); @@ -137,8 +140,10 @@ class RSSFeeds implements ControllerProviderInterface ->assert('format', '(rss|atom)'); $controllers->get('/cooliris/', function(Application $app) use ($display_feed) { - $feeds = \Feed_Collection::load_public_feeds($app); - $feed = $feeds->get_aggregate(); +// $feeds = \Feed_Collection::load_public_feeds($app); +// $feed = $feeds->get_aggregate(); + $feeds = $app["EM"]->getRepository("Entities\Feed")->findAllPublic(); + $feed = new Aggregate($app, $feeds); $request = $app['request']; $page = (int) $request->query->get('page'); diff --git a/lib/Alchemy/Phrasea/Core/Provider/FeedServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/FeedServiceProvider.php new file mode 100644 index 0000000000..dc4ceef38f --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Provider/FeedServiceProvider.php @@ -0,0 +1,34 @@ +share(function($app) { + return new LinkGenerator($app['url_generator'], $app['EM'], $app['tokens']); + }); + $app['feed.aggreagate-link-generator'] = $app->share(function($app) { + return new AggregateLinkGenerator($app['url_generator'], $app['EM'], $app['tokens']); + }); + } + + public function boot(Application $app) + { + } +} diff --git a/lib/Alchemy/Phrasea/Feed/Aggregate.php b/lib/Alchemy/Phrasea/Feed/Aggregate.php new file mode 100644 index 0000000000..3bfbdd6177 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Aggregate.php @@ -0,0 +1,149 @@ +title = 'AGGREGATE'; + $this->subtitle = 'AGGREGATE SUBTITLE'; + $this->created_on = new \DateTime(); + $this->updated_on = new \DateTime(); + $this->app = $app; + + $tmp_feeds = array(); + + foreach ($feeds as $feed) { + $tmp_feeds[$feed->getId()] = $feed; + } + + $this->feeds = $tmp_feeds; + + return $this; + } + + public static function createFromUser(Application $app, \User_Adapter $user) + { + $feeds = $app["EM"]->getRepository('Entities\Feed')->findByUser($user); + + return new static($app, $feeds); + } + + public static function create(Application $app, array $feed_ids) + { + $feeds = $app["EM"]->getRepository('Entities\Feed')->findByIdArray($feed_ids); + + return new static($app, $feeds); + } + + public function isAggregated() + { + return true; + } + + public function getEntries($offset_start, $how_many) + { + $result = new \Feed_Entry_Collection(); + + if (count($this->feeds) === 0) { + return $result; + } + + $offset_start = (int) $offset_start; + $how_many = $how_many > 20 ? 20 : (int) $how_many; + + $rs = $this->app["EM"]->getRepository("Entities\FeedEntry")->findByFeeds($this->feeds, $offset_start, $how_many); + + foreach ($rs as $entry) { + if ($entry) { + $result->add_entry($entry); + } + } + + return $result; + } + + public function getSubtitle() + { + return $this->subtitle; + } + + public function getTitle() + { + return $this->title; + } + + public function getIconUrl() + { + $url = '/skins/icons/rss32.gif'; + + return $url; + } + + public function getCreatedOn() + { + return $this->created_on; + } + + public function getUpdatedOn() + { + return $this->updated_on; + } + + public function getToken() + { + return $this->token; + } + + public function setToken($token) + { + $this->token = $token; + } + + public function getFeeds() + { + return $this->feeds; + } + + public function getCountTotalEntries() + { + if (count($this->feeds) > 0) { + return count($this->app["EM"]->getRepository("Entities\FeedEntry")->findByFeeds($this->feeds)); + } + return 0; + } +} diff --git a/lib/Alchemy/Phrasea/Feed/AggregateLinkGenerator.php b/lib/Alchemy/Phrasea/Feed/AggregateLinkGenerator.php new file mode 100644 index 0000000000..6f9477c6f8 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/AggregateLinkGenerator.php @@ -0,0 +1,74 @@ +generator = $generator; + $this->em = $em; + $this->random = $random; + } + + public function generate(Aggregate $aggregate, \User_Adapter $user, $format, $page = null, $renew = false) + { + switch ($format) { + case self::FORMAT_ATOM: + return new FeedLink( + $this->generator->generate('feed_user_aggregated', array( + 'token' => $this->getAggregateToken($user, $renew)->getValue(), + 'format' => 'atom', + ), UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $aggregate->getTitle(), 'Atom'), + 'application/atom+xml' + ); + break; + case self::FORMAT_RSS: + return new FeedLink( + $this->generator->generate('feed_user_aggregated', array( + 'token' => $this->getAggregateToken($user, $renew)->getValue(), + 'format' => 'rss', + ), UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $aggregate->getTitle(), 'RSS'), + 'application/rss+xml' + ); + break; + default: + throw new InvalidArgumentException(sprintf('Format %s is not recognized.', $format)); + } + } + + private function getAggregateToken(\User_Adapter $user, $renew = false) + { + $token = $this->em + ->getRepository('Entities\AggregateToken') + ->findByUser($user); + + if (null === $token || true === $renew) { + if (null === $token) { + $token = new AggregateToken(); + $token->setUsrId($user->get_id()); + } + + $token->setValue($this->random->generatePassword(12, \random::LETTERS_AND_NUMBERS)); + $this->em->persist($token); + $this->em->flush(); + } + + return $token; + } +} diff --git a/lib/Alchemy/Phrasea/Feed/AggregateToken.php b/lib/Alchemy/Phrasea/Feed/AggregateToken.php new file mode 100644 index 0000000000..6ef2a26227 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/AggregateToken.php @@ -0,0 +1,111 @@ +id; + } + + /** + * Set usr_id + * + * @param integer $usrId + * @return FeedToken + */ + public function setUsrId($usrId) + { + $this->usr_id = $usrId; + + return $this; + } + + /** + * Get usr_id + * + * @return integer + */ + public function getUsrId() + { + return $this->usr_id; + } + + /** + * Set feed + * + * @param \Entities\Feed $feed + * @return FeedToken + */ + public function setFeed(\Entities\Feed $feed = null) + { + $this->feed = $feed; + + return $this; + } + + /** + * Get feed + * + * @return \Entities\Feed + */ + public function getFeed() + { + return $this->feed; + } + /** + * @var string + */ + private $value; + + + /** + * Set value + * + * @param string $value + * @return FeedToken + */ + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + /** + * Get value + * + * @return string + */ + public function getValue() + { + return $this->value; + } +} \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Feed/FeedInterface.php b/lib/Alchemy/Phrasea/Feed/FeedInterface.php new file mode 100644 index 0000000000..504e9b6e37 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/FeedInterface.php @@ -0,0 +1,21 @@ +mimetype = $mimetype; + $this->uri = $uri; + $this->title = $title; + } + + /** + * {@inheritdoc} + */ + public function getMimetype() + { + return $this->mimetype; + } + + /** + * {@inheritdoc} + */ + public function getTitle() + { + return $this->title; + } + + /** + * {@inheritdoc} + */ + public function getURI() + { + return $this->uri; + } +} diff --git a/lib/Alchemy/Phrasea/Feed/LinkGenerator.php b/lib/Alchemy/Phrasea/Feed/LinkGenerator.php new file mode 100644 index 0000000000..dbe105e0d6 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/LinkGenerator.php @@ -0,0 +1,80 @@ +generator = $generator; + $this->em = $em; + $this->random = $random; + } + + public function generate(Feed $feed, \User_Adapter $user, $format, $page = null, $renew = false) + { + switch ($format) { + case self::FORMAT_ATOM: + return new FeedLink( + $this->generator->generate('feed_user', array( + 'token' => $this->getFeedToken($feed, $user, $renew)->getValue(), + 'id' => $feed->getId(), + 'format' => 'atom', + ), UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $feed->getTitle(), 'Atom'), + 'application/atom+xml' + ); + break; + case self::FORMAT_RSS: + return new FeedLink( + $this->generator->generate('feed_user', array( + 'token' => $this->getFeedToken($feed, $user, $renew)->getValue(), + 'id' => $feed->getId(), + 'format' => 'rss', + ), UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $feed->getTitle(), 'RSS'), + 'application/rss+xml' + ); + break; + default: + throw new InvalidArgumentException(sprintf('Format %s is not recognized.', $format)); + } + } + + private function getFeedToken(Feed $feed, \User_Adapter $user, $renew = false) + { + $token = $this->em + ->getRepository('Entities\FeedToken') + ->findByFeedAndUser($feed, $user); + + if (null === $token || true === $renew) { + if (null === $token) { + $token = new FeedToken(); + $token->setFeed($feed); + $token->setUsrId($user->get_id()); + $feed->addToken($token); + + $this->em->persist($feed); + } + + $token->setValue($this->random->generatePassword(12, \random::LETTERS_AND_NUMBERS)); + $this->em->persist($token); + $this->em->flush(); + } + + return $token; + } +} diff --git a/lib/Alchemy/Phrasea/Feed/LinkInterface.php b/lib/Alchemy/Phrasea/Feed/LinkInterface.php new file mode 100644 index 0000000000..4d45c2d4d8 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/LinkInterface.php @@ -0,0 +1,30 @@ +publishers = new \Doctrine\Common\Collections\ArrayCollection(); $this->entries = new \Doctrine\Common\Collections\ArrayCollection(); } - + /** * Get id * - * @return integer + * @return integer */ public function getId() { @@ -88,14 +94,14 @@ class Feed public function setPublic($public) { $this->public = $public; - + return $this; } /** * Get public * - * @return boolean + * @return boolean */ public function getPublic() { @@ -111,21 +117,21 @@ class Feed public function setIconUrl($iconUrl) { $this->icon_url = $iconUrl; - + return $this; } /** * Get icon_url * - * @return string + * @return string */ public function getIconUrl() { if (!$this->icon_url) { return '/skins/icons/rss32.gif'; } - + return '/www/custom/feed_' . $this->getId() . '.jpg'; } @@ -138,14 +144,14 @@ class Feed public function setBaseId($baseId) { $this->base_id = $baseId; - + return $this; } /** * Get base_id * - * @return integer + * @return integer */ public function getBaseId() { @@ -161,14 +167,14 @@ class Feed public function setTitle($title) { $this->title = $title; - + return $this; } /** * Get title * - * @return string + * @return string */ public function getTitle() { @@ -184,7 +190,7 @@ class Feed public function addPublisher(\Entities\FeedPublisher $publishers) { $this->publishers[] = $publishers; - + return $this; } @@ -201,7 +207,7 @@ class Feed /** * Get publishers * - * @return \Doctrine\Common\Collections\Collection + * @return \Doctrine\Common\Collections\Collection */ public function getPublishers() { @@ -217,7 +223,7 @@ class Feed public function addEntry(\Entities\FeedEntry $entries) { $this->entries[] = $entries; - + return $this; } @@ -234,39 +240,39 @@ class Feed /** * Get entries * - * @return \Doctrine\Common\Collections\Collection + * @return \Doctrine\Common\Collections\Collection */ - public function getEntries() + public function getEntries($offset_start, $how_many) { - return $this->entries; + return $this->entries->slice($offset_start, $how_many); } - + public function getOwner() - { + { foreach ($this->getPublishers() as $publisher) { if ($publisher->getOwner()) { return $publisher; } } } - + public function isOwner(\User_Adapter $user) { $owner = $this->getOwner(); if ($owner !== null && $user->get_id() === $owner->getUsrId()) { return true; } - + return false; } - + public function getCollection(Application $app) { if ($this->getBaseId() !== null) { return \collection::get_from_base_id($app, $this->getBaseId()); } } - + public function setCollection(\collection $collection = null) { if ($collection === null) { @@ -285,14 +291,14 @@ class Feed public function setCreatedOn($createdOn) { $this->created_on = $createdOn; - + return $this; } /** * Get created_on * - * @return \DateTime + * @return \DateTime */ public function getCreatedOn() { @@ -308,20 +314,20 @@ class Feed public function setUpdatedOn($updatedOn) { $this->updated_on = $updatedOn; - + return $this; } /** * Get updated_on * - * @return \DateTime + * @return \DateTime */ public function getUpdatedOn() { return $this->updated_on; } - + public function isPublisher(\User_Adapter $user) { foreach ($this->getPublishers() as $publisher) { @@ -329,10 +335,21 @@ class Feed return true; } } - + return false; } + public function getPublisher(\User_Adapter $user) + { + foreach ($this->getPublishers() as $publisher) { + if ($publisher->getUsrId() == $user->get_id()) { + return $publisher; + } + } + + return null; + } + /** * Set subtitle * @@ -342,14 +359,14 @@ class Feed public function setSubtitle($subtitle) { $this->subtitle = $subtitle; - + return $this; } /** * Get subtitle * - * @return string + * @return string */ public function getSubtitle() { @@ -360,18 +377,51 @@ class Feed { return false; } - + public function getCountTotalEntries() { return (count($this->entries)); } - - public function hasAccess(User_Adapter $user) + + public function hasAccess(\User_Adapter $user, Application $app) { - if ($this->get_collection() instanceof collection) { + if ($this->getCollection($app) instanceof collection) { return $user->ACL()->has_access_to_base($this->collection->get_base_id()); } return true; } -} + + /** + * Add tokens + * + * @param \Entities\FeedToken $tokens + * @return Feed + */ + public function addToken(\Entities\FeedToken $tokens) + { + $this->tokens[] = $tokens; + + return $this; + } + + /** + * Remove tokens + * + * @param \Entities\FeedToken $tokens + */ + public function removeToken(\Entities\FeedToken $tokens) + { + $this->tokens->removeElement($tokens); + } + + /** + * Get tokens + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getTokens() + { + return $this->tokens; + } +} \ No newline at end of file diff --git a/lib/Doctrine/Entities/FeedEntry.php b/lib/Doctrine/Entities/FeedEntry.php index f5f4e9288f..ae72ac8ecd 100644 --- a/lib/Doctrine/Entities/FeedEntry.php +++ b/lib/Doctrine/Entities/FeedEntry.php @@ -172,7 +172,7 @@ class FeedEntry /** * Set created * - * @param \DateTime $created + * @param \DateTime $createdOn * @return FeedEntry */ public function setCreatedOn($createdOn) @@ -189,7 +189,7 @@ class FeedEntry */ public function getCreatedOn() { - return $this->createdOn; + return $this->created_on; } /** @@ -212,7 +212,7 @@ class FeedEntry */ public function getUpdatedOn() { - return $this->updatedOn; + return $this->updated_on; } /** @@ -303,4 +303,4 @@ class FeedEntry return false; } -} +} \ No newline at end of file diff --git a/lib/Doctrine/Entities/FeedItem.php b/lib/Doctrine/Entities/FeedItem.php index 4d33318551..9c2682775f 100644 --- a/lib/Doctrine/Entities/FeedItem.php +++ b/lib/Doctrine/Entities/FeedItem.php @@ -39,10 +39,6 @@ class FeedItem */ private $entry; - public function __construct(\Entities\FeedEntry $entry, \record_adapter $record) - { - } - /** * Get id * diff --git a/templates/web/prod/actions/publish/publish.html.twig b/templates/web/prod/actions/publish/publish.html.twig index 3bd4fcebfb..f9df778eac 100644 --- a/templates/web/prod/actions/publish/publish.html.twig +++ b/templates/web/prod/actions/publish/publish.html.twig @@ -53,14 +53,14 @@

{% trans 'Fils disponibles' %}

- {% for feed in feeds.get_feeds() %} - {% if feed.is_publisher(app['authentication'].getUser()) %} + {% for feed in feeds %} + {% if feed.isPublisher(app['authentication'].getUser()) %}
- {{ feed.get_title() }} - {% if feed.is_public() %} + {{ feed.getTitle() }} + {% if feed.getPublic() %} {% endif %} - +
{% endif %} {% endfor %} diff --git a/templates/web/prod/feeds/entry.html.twig b/templates/web/prod/feeds/entry.html.twig index 7618484f4a..699d111ebd 100644 --- a/templates/web/prod/feeds/entry.html.twig +++ b/templates/web/prod/feeds/entry.html.twig @@ -1,2 +1,2 @@ {% import 'prod/feeds/entry_macro.html.twig' as _entry %} -{{ _entry.format(entry.get_feed(), entry) }} \ No newline at end of file +{{ _entry.format(entry.getFeed(), entry) }} \ No newline at end of file diff --git a/templates/web/prod/feeds/entry_macro.html.twig b/templates/web/prod/feeds/entry_macro.html.twig index 976d81275a..3954bde598 100644 --- a/templates/web/prod/feeds/entry_macro.html.twig +++ b/templates/web/prod/feeds/entry_macro.html.twig @@ -1,25 +1,25 @@ {% macro format(feed, entry)%} {% import 'prod/results/record.html.twig' as record_format %} -
+

- {% if feed.is_aggregated() %} - + {% if feed.isAggregated() %} + {% endif %} - {{ entry.get_title() }} - {% set author = entry.get_author_name() %} + {{ entry.getTitle() }} + {% set author = entry.getAuthorName() %} {% trans %}Par {{ author }}{% endtrans %}

- {% if entry.get_feed().is_owner(app['authentication'].getUser()) or entry.is_publisher(app['authentication'].getUser()) %} - + {% if entry.getFeed().isOwner(app['authentication'].getUser()) or entry.isPublisher(app['authentication'].getUser()) %} + - + {% endif %} @@ -27,8 +27,8 @@
-

{{ entry.get_subtitle()|nl2br|raw }}

+

{{ entry.getSubtitle()|nl2br|raw }}

- {% for item in entry.get_content() %} - {% set record = item.get_record() %} - {% set prefix = 'PUBLI_' ~ item.get_id() %} - {{record_format.block(record, false, null, prefix, entry.get_id())}} + {% for item in entry.getItems() %} + {% set record = item.getRecord() %} + {% set prefix = 'PUBLI_' ~ item.getId() %} + {{record_format.block(record, false, null, prefix, entry.getId())}} {% endfor %}
-{% endmacro %} \ No newline at end of file +{% endmacro %} diff --git a/templates/web/prod/feeds/feeds.html.twig b/templates/web/prod/feeds/feeds.html.twig index 893e5d2669..182ff7b81a 100644 --- a/templates/web/prod/feeds/feeds.html.twig +++ b/templates/web/prod/feeds/feeds.html.twig @@ -6,23 +6,22 @@

- - {% if feed.is_aggregated %} + + {% if feed.isAggregated %} {% trans 'Toutes les publications' %} {% else %} - {{ feed.get_title() }} - + {{ feed.getTitle() }} + {% endif %} - - {% if feed.is_aggregated %} + {% if feed.isAggregated %} {% else %} - + {% endif %}

@@ -34,10 +33,10 @@
\ No newline at end of file +
diff --git a/templates/web/prod/index.html.twig b/templates/web/prod/index.html.twig index bea73022e5..e2cd7ac8ef 100644 --- a/templates/web/prod/index.html.twig +++ b/templates/web/prod/index.html.twig @@ -52,11 +52,11 @@ {% endblock %} {% block rss %} - {% for feed in feeds %} - {% set link = feed.get_user_link(app['phraseanet.registry'], app['authentication'].getUser(), 'rss') %} - - {% set link = feed.get_user_link(app['phraseanet.registry'], app['authentication'].getUser(), 'atom') %} - + {% for feed in aggregate.getFeeds() %} + {% set link = app['feed.user-link-generator'].generate(feed, app['authentication'].getUser(), 'rss') %} + + {% set link = app['feed.user-link-generator'].generate(feed, app['authentication'].getUser(), 'rss') %} + {% endfor %} {% endblock %} diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Prod/FeedTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Prod/FeedTest.php index 0b6b9ef15c..843df1659c 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Prod/FeedTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Prod/FeedTest.php @@ -3,9 +3,12 @@ namespace Alchemy\Tests\Phrasea\Controller\Prod; use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Feed\Aggregate; +use Alchemy\Phrasea\Feed\AggregateLinkGenerator; +use Alchemy\Phrasea\Feed\LinkGenerator; use Symfony\Component\CssSelector\CssSelector; -class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract +class ControllerFeedTest extends \PhraseanetWebTestCaseAuthenticatedAbstract { /** * @@ -42,33 +45,28 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract { parent::setUp(); - self::$DI['app']['notification.deliverer'] = $this->getMockBuilder('Alchemy\Phrasea\Notification\Deliverer') - ->disableOriginalConstructor() - ->getMock(); - - self::$DI['app']['notification.deliverer']->expects($this->atLeastOnce()) - ->method('deliver') - ->with($this->isInstanceOf('Alchemy\Phrasea\Notification\Mail\MailInfoNewPublication'), $this->equalTo(null)); - - $this->feed = \Feed_Adapter::create( - self::$DI['app'], self::$DI['user'], $this->feed_title, $this->feed_subtitle - ); - - $this->publisher = \Feed_Publisher_Adapter::getPublisher( - self::$DI['app']['phraseanet.appbox'], $this->feed, self::$DI['user'] - ); - - $this->entry = \Feed_Entry_Adapter::create( - self::$DI['app'] - , $this->feed - , $this->publisher - , $this->entry_title - , $this->entry_subtitle - , $this->entry_authorname - , $this->entry_authormail - ); - - $this->item = \Feed_Entry_Item::create(self::$DI['app']['phraseanet.appbox'], $this->entry, self::$DI['record_1']); +// $this->publisher = new \Entities\FeedPublisher(self::$DI['user']); +// +// $this->feed = new \Entities\Feed($this->publisher, $this->feed_title, $this->feed_subtitle); +// +// $this->entry = new \Entities\FeedEntry( +// $this->feed +// , $this->publisher +// , $this->entry_title +// , $this->entry_subtitle +// , $this->entry_authorname +// , $this->entry_authormail +// ); +// +// $this->item = new \Entities\FeedItem($this->entry, self::$DI['record_1']); +// +// $this->publisher->setFeed($this->feed); +// +// self::$DI['app']["EM"]->persist($this->feed); +// self::$DI['app']["EM"]->persist($this->publisher); +// self::$DI['app']["EM"]->persist($this->entry); +// self::$DI['app']["EM"]->persist($this->item); +// self::$DI['app']["EM"]->flush(); } public static function setUpBeforeClass() @@ -84,34 +82,46 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract public function tearDown() { - if ($this->feed instanceof \Feed_Adapter) { - $this->feed->delete(); - } elseif ($this->entry instanceof \Feed_Entry_Adapter) { - $this->entry->delete(); - if ($this->publisher instanceof \Feed_Publisher_Adapter) { - $this->publisher->delete(); - } - } +// if ($this->feed instanceof \Entities\Feed) { +// self::$DI['app']["EM"]->remove($this->feed); +// } else if ($this->entry instanceof \Entities\FeedEntry) { +// self::$DI['app']["EM"]->remove($this->entry); +// if ($this->publisher instanceof \Entities\FeedPublisher) { +// self::$DI['app']["EM"]->remove($this->publisher); +// } +// } +// self::$DI['app']["EM"]->flush(); parent::tearDown(); } public function testRequestAvailable() { + $feed = $this->insertOneFeed(self::$DI['user']); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/requestavailable/'); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); - $feeds = \Feed_Collection::load_all(self::$DI['app'], self::$DI['user']); - foreach ($feeds->get_feeds() as $one_feed) { - if ($one_feed->is_publisher(self::$DI['user'])) { - $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $one_feed->get_id() . "']")->count()); + $feeds = self::$DI['app']["EM"]->getRepository("\Entities\Feed")->getAllForUser(self::$DI['user']); + foreach ($feeds as $one_feed) { + if ($one_feed->isPublisher(self::$DI['user'])) { + $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $one_feed->getId() . "']")->count()); } } } public function testEntryCreate() { + self::$DI['app']['notification.deliverer'] = $this->getMockBuilder('Alchemy\Phrasea\Notification\Deliverer') + ->disableOriginalConstructor() + ->getMock(); + + self::$DI['app']['notification.deliverer']->expects($this->atLeastOnce()) + ->method('deliver') + ->with($this->isInstanceOf('Alchemy\Phrasea\Notification\Mail\MailInfoNewPublication'), $this->equalTo(null)); + + $feed = $this->insertOneFeed(self::$DI['user']); $params = array( - "feed_id" => $this->feed->get_id() + "feed_id" => $feed->getId() , "title" => "salut" , "subtitle" => "coucou" , "author_name" => "robert" @@ -149,49 +159,36 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract public function testEntryEdit() { - - $crawler = self::$DI['client']->request('GET', '/prod/feeds/entry/' . $this->entry->get_id() . '/edit/'); + $entry = $this->insertOneFeedEntry(self::$DI['user']); + $crawler = self::$DI['client']->request('GET', '/prod/feeds/entry/' . $entry->getId() . '/edit/'); $pageContent = self::$DI['client']->getResponse()->getContent(); - foreach ($this->entry->get_content() as $content) { - $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $content->get_id() . "' and @name='item_id']")->count()); + foreach ($entry->getItems() as $content) { + $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $content->getId() . "' and @name='item_id']")->count()); } - $this->assertEquals(1, $crawler->filterXPath("//form[@action='/prod/feeds/entry/" . $this->entry->get_id() . "/update/']")->count()); - $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $this->entry_title . "']")->count()); - $this->assertEquals($this->entry_subtitle, $crawler->filterXPath("//textarea[@id='feed_add_subtitle']")->text()); - $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $this->entry_authorname . "']")->count()); - $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $this->entry_authormail . "']")->count()); + $this->assertEquals(1, $crawler->filterXPath("//form[@action='/prod/feeds/entry/" . $entry->getId() . "/update/']")->count()); + $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $entry->getTitle() . "']")->count()); + $this->assertEquals($entry->getSubtitle(), $crawler->filterXPath("//textarea[@id='feed_add_subtitle']")->text()); + $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $entry->getAuthorName() . "']")->count()); + $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $entry->getAuthorEmail() . "']")->count()); } public function testEntryEditUnauthorized() { - $feed = \Feed_Adapter::create( - self::$DI['app'], self::$DI['user_alt1'], $this->feed_title, $this->feed_subtitle - ); + $entry = $this->insertOneFeedEntry(self::$DI['user_alt1']); - $publisher = \Feed_Publisher_Adapter::getPublisher( - self::$DI['app']['phraseanet.appbox'], $feed, self::$DI['user_alt1'] - ); + try { + $crawler = self::$DI['client']->request('GET', '/prod/feeds/entry/' . $entry->getId() . '/edit/'); + $this->fail('Should raise an exception'); + } catch (\Exception_UnauthorizedAction $e) { - $entry = \Feed_Entry_Adapter::create( - self::$DI['app'] - , $feed - , $publisher - , $this->entry_title - , $this->entry_subtitle - , $this->entry_authorname - , $this->entry_authormail - ); - - self::$DI['client']->request('GET', '/prod/feeds/entry/' . $entry->get_id() . '/edit/'); - $this->assertEquals(403, self::$DI['client']->getResponse()->getStatusCode()); - - $feed->delete(); + } } public function testEntryUpdate() { + $entry = $this->insertOneFeedEntry(self::$DI['user']); $params = array( "title" => "dog", @@ -201,7 +198,7 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract 'lst' => self::$DI['record_1']->get_serialize_key(), ); - $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $this->entry->get_id() . '/update/', $params); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->getId() . '/update/', $params); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); $this->assertEquals("application/json", self::$DI['client']->getResponse()->headers->get("content-type")); $pageContent = json_decode(self::$DI['client']->getResponse()->getContent()); @@ -209,25 +206,23 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract $this->assertFalse($pageContent->error); $this->assertTrue(is_string($pageContent->message)); $this->assertTrue(is_string($pageContent->datas)); - $this->assertRegExp("/entry_" . $this->entry->get_id() . "/", $pageContent->datas); + $this->assertRegExp("/entry_" . $entry->getId() . "/", $pageContent->datas); } public function testEntryUpdateChangeFeed() { - $newfeed = \Feed_Adapter::create( - self::$DI['app'], self::$DI['user'], $this->feed_title, $this->feed_subtitle - ); + $entry = $this->insertOneFeedEntry(self::$DI['user']); + $newfeed = $this->insertOneFeed(self::$DI['user'], "test2"); $params = array( - "feed_id" => $newfeed->get_id(), + "feed_id" => $newfeed->getId(), "title" => "dog", "subtitle" => "cat", "author_name" => "bird", "author_email" => "mouse", 'lst' => self::$DI['record_1']->get_serialize_key(), ); - - $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $this->entry->get_id() . '/update/', $params); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->getId() . '/update/', $params); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); $this->assertEquals("application/json", self::$DI['client']->getResponse()->headers->get("content-type")); $pageContent = json_decode(self::$DI['client']->getResponse()->getContent()); @@ -235,23 +230,22 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract $this->assertFalse($pageContent->error); $this->assertTrue(is_string($pageContent->message)); $this->assertTrue(is_string($pageContent->datas)); - $this->assertRegExp("/entry_" . $this->entry->get_id() . "/", $pageContent->datas); + $this->assertRegExp("/entry_" . $entry->getId() . "/", $pageContent->datas); - $retrievedentry = \Feed_Entry_Adapter::load_from_id(self::$DI['app'], $this->entry->get_id()); - $this->assertEquals($newfeed->get_id(), $retrievedentry->get_feed()->get_id()); - - $newfeed->delete(); + $retrievedentry = self::$DI['app']["EM"]->getRepository("\Entities\FeedEntry")->find($entry->getId()); + $this->assertEquals($newfeed->getId(), $retrievedentry->getFeed()->getId()); } public function testEntryUpdateChangeFeedNoAccess() { - $newfeed = \Feed_Adapter::create( - self::$DI['app'], self::$DI['user'], $this->feed_title, $this->feed_subtitle - ); - $newfeed->set_collection(self::$DI['collection_no_access']); + $entry = $this->insertOneFeedEntry(self::$DI['user']); + $newfeed = $this->insertOneFeed(self::$DI['user'], "test2"); + $newfeed->setCollection(self::$DI['collection_no_access']); + self::$DI['app']["EM"]->persist($newfeed); + self::$DI['app']["EM"]->flush(); $params = array( - "feed_id" => $newfeed->get_id(), + "feed_id" => $newfeed->getId(), "title" => "dog", "subtitle" => "cat", "author_name" => "bird", @@ -259,19 +253,19 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract 'lst' => self::$DI['record_1']->get_serialize_key(), ); - $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $this->entry->get_id() . '/update/', $params); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->getId() . '/update/', $params); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); $this->assertEquals("application/json", self::$DI['client']->getResponse()->headers->get("content-type")); $pageContent = json_decode(self::$DI['client']->getResponse()->getContent()); $this->assertTrue(is_object($pageContent)); $this->assertTrue($pageContent->error); $this->assertTrue(is_string($pageContent->message)); - - $newfeed->delete(); } public function testEntryUpdateChangeFeedInvalidFeed() { + $entry = $this->insertOneFeedEntry(self::$DI['user']); + $params = array( "feed_id" => 0, "title" => "dog", @@ -281,7 +275,7 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract 'lst' => self::$DI['record_1']->get_serialize_key(), ); - $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $this->entry->get_id() . '/update/', $params); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->getId() . '/update/', $params); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); $this->assertEquals("application/json", self::$DI['client']->getResponse()->headers->get("content-type")); $pageContent = json_decode(self::$DI['client']->getResponse()->getContent()); @@ -317,6 +311,7 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract public function testEntryUpdateFailed() { + $entry = $this->insertOneFeedEntry(self::$DI['user']); $params = array( "feed_id" => 9999999 @@ -327,7 +322,7 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract , 'sorted_lst' => self::$DI['record_1']->get_serialize_key() . ";" . self::$DI['record_2']->get_serialize_key() . ";12345;" . "unknow_unknow" ); - $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $this->entry->get_id() . '/update/', $params); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->getId() . '/update/', $params); $response = self::$DI['client']->getResponse(); @@ -345,13 +340,11 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract /** * I CREATE A FEED THAT IS NOT MINE * */ - $feed = \Feed_Adapter::create(self::$DI['app'], self::$DI['user_alt1'], "salut", 'coucou'); - $publisher = \Feed_Publisher_Adapter::getPublisher(self::$DI['app']['phraseanet.appbox'], $feed, self::$DI['user_alt1']); - $entry = \Feed_Entry_Adapter::create(self::$DI['app'], $feed, $publisher, "hello", "coucou", "salut", "bonjour@phraseanet.com"); - $item = \Feed_Entry_Item::create(self::$DI['app']['phraseanet.appbox'], $entry, self::$DI['record_1']); + + $entry = $this->insertOneFeedEntry(self::$DI['user_alt1']); $params = array( - "feed_id" => $feed->get_id() + "feed_id" => $entry->getFeed()->getId() , "title" => "dog" , "subtitle" => "cat" , "author_name" => "bird" @@ -359,7 +352,7 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract , 'lst' => self::$DI['record_1']->get_serialize_key() ); - $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->get_id() . '/update/', $params); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->getId() . '/update/', $params); $response = self::$DI['client']->getResponse(); @@ -370,14 +363,13 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract $this->assertTrue(is_object($pageContent)); $this->assertTrue($pageContent->error); $this->assertTrue(is_string($pageContent->message)); - - $feed->delete(); } public function testDelete() { + $entry = $this->insertOneFeedEntry(self::$DI['user']); - $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $this->entry->get_id() . '/delete/'); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->getId() . '/delete/'); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); $this->assertEquals("application/json", self::$DI['client']->getResponse()->headers->get("content-type")); @@ -389,7 +381,7 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract $this->assertTrue(is_string($pageContent->message)); try { - \Feed_Entry_Adapter::load_from_id(self::$DI['app'], $this->entry->get_id()); + self::$DI["app"]["EM"]->getRepository("\Entities\FeedEntry")->find($entry->getId()); $this->fail("Failed to delete entry"); } catch (\Exception $e) { @@ -417,13 +409,9 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract /** * I CREATE A FEED * */ - $feed = \Feed_Adapter::create(self::$DI['app'], self::$DI['user_alt1'], "salut", 'coucou'); + $entry = $this->insertOneFeedEntry(self::$DI['user_alt1']); - $publisher = \Feed_Publisher_Adapter::getPublisher(self::$DI['app']['phraseanet.appbox'], $feed, self::$DI['user_alt1']); - $entry = \Feed_Entry_Adapter::create(self::$DI['app'], $feed, $publisher, "hello", "coucou", "salut", "bonjour@phraseanet.com"); - $item = \Feed_Entry_Item::create(self::$DI['app']['phraseanet.appbox'], $entry, self::$DI['record_1']); - - $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->get_id() . '/delete/'); + $crawler = self::$DI['client']->request('POST', '/prod/feeds/entry/' . $entry->getId() . '/delete/'); $response = self::$DI['client']->getResponse(); @@ -434,8 +422,6 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract $this->assertTrue(is_object($pageContent)); $this->assertTrue($pageContent->error); $this->assertTrue(is_string($pageContent->message)); - - $feed->delete(); } public function testRoot() @@ -447,12 +433,12 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract $this->assertTrue(self::$DI['client']->getResponse()->isOk()); - $feeds = \Feed_Collection::load_all(self::$DI['app'], self::$DI['user']); + $feeds = self::$DI['app']["EM"]->getRepository("\Entities\Feed")->getAllForUser(self::$DI['user']); - foreach ($feeds->get_feeds() as $one_feed) { + foreach ($feeds as $one_feed) { - $path = CssSelector::toXPath("ul.submenu a[href='/prod/feeds/feed/" . $one_feed->get_id() . "/']"); - $msg = sprintf("user %s has access to feed %s", self::$DI['user']->get_id(), $one_feed->get_id()); + $path = CssSelector::toXPath("ul.submenu a[href='/prod/feeds/feed/" . $one_feed->getId() . "/']"); + $msg = sprintf("user %s has access to feed %s", self::$DI['user']->getId(), $one_feed->getId()); if ($one_feed->has_access(self::$DI['user'])) { $this->assertEquals(1, $crawler->filterXPath($path)->count(), $msg); @@ -465,16 +451,18 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract public function testGetFeed() { - $feeds = \Feed_Collection::load_all(self::$DI['app'], self::$DI['user']); + $feed = $this->insertOneFeed(self::$DI['user']); - $crawler = self::$DI['client']->request('GET', '/prod/feeds/feed/' . $this->feed->get_id() . "/"); + $feeds = self::$DI['app']["EM"]->getRepository("\Entities\Feed")->getAllForUser(self::$DI['user']); + + $crawler = self::$DI['client']->request('GET', '/prod/feeds/feed/' . $feed->getId() . "/"); $pageContent = self::$DI['client']->getResponse()->getContent(); - foreach ($feeds->get_feeds() as $one_feed) { - $path = CssSelector::toXPath("ul.submenu a[href='/prod/feeds/feed/" . $one_feed->get_id() . "/']"); - $msg = sprintf("user %s has access to feed %s", self::$DI['user']->get_id(), $one_feed->get_id()); + foreach ($feeds as $one_feed) { + $path = CssSelector::toXPath("ul.submenu a[href='/prod/feeds/feed/" . $one_feed->getId() . "/']"); + $msg = sprintf("user %s has access to feed %s", self::$DI['user']->get_id(), $one_feed->getId()); - if ($one_feed->has_access(self::$DI['user'])) { + if ($one_feed->hasAccess(self::$DI['user'], self::$DI['app'])) { $this->assertEquals(1, $crawler->filterXPath($path)->count(), $msg); } else { $this->fail('Feed_collection::load_all should return feed where I got access'); @@ -484,26 +472,48 @@ class ControllerFeedApp extends \PhraseanetWebTestCaseAuthenticatedAbstract public function testSuscribeAggregate() { - $feeds = \Feed_Collection::load_all(self::$DI['app'], self::$DI['user']); + $feed = $this->insertOneFeed(self::$DI['user']); + + $generator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGenerator') + ->disableOriginalConstructor() + ->getMock(); + + $random = self::$DI['app']['tokens']; + + $aggregateGenerator = new AggregateLinkGenerator($generator, self::$DI['app']['EM'], $random); + + $feeds = self::$DI['app']["EM"]->getRepository("\Entities\Feed")->getAllForUser(self::$DI['user']); $crawler = self::$DI['client']->request('GET', '/prod/feeds/subscribe/aggregated/'); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); $this->assertEquals("application/json", self::$DI['client']->getResponse()->headers->get("content-type")); $pageContent = json_decode(self::$DI['client']->getResponse()->getContent()); $this->assertTrue(is_object($pageContent)); $this->assertTrue(is_string($pageContent->texte)); - $suscribe_link = $feeds->get_aggregate()->get_user_link(self::$DI['app']['phraseanet.registry'], self::$DI['user'], \Feed_Adapter::FORMAT_RSS, null, false)->get_href(); - $this->assertContains($suscribe_link, $pageContent->texte); + $aggregate = new Aggregate(self::$DI['app'], $feeds); + $suscribe_link = $aggregateGenerator->generate($aggregate, self::$DI['user'], AggregateLinkGenerator::FORMAT_RSS); + $this->assertContains($suscribe_link->getURI(), $pageContent->texte); } public function testSuscribe() { - $crawler = self::$DI['client']->request('GET', '/prod/feeds/subscribe/' . $this->feed->get_id() . '/'); + $feed = $this->insertOneFeed(self::$DI['user']); + + $generator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGenerator') + ->disableOriginalConstructor() + ->getMock(); + + $random = self::$DI['app']['tokens']; + + $linkGenerator = new LinkGenerator($generator, self::$DI['app']['EM'], $random); + + $crawler = self::$DI['client']->request('GET', '/prod/feeds/subscribe/' . $feed->getId() . '/'); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); $this->assertEquals("application/json", self::$DI['client']->getResponse()->headers->get("content-type")); $pageContent = json_decode(self::$DI['client']->getResponse()->getContent()); $this->assertTrue(is_object($pageContent)); $this->assertTrue(is_string($pageContent->texte)); - $suscribe_link = $this->feed->get_user_link(self::$DI['app']['phraseanet.registry'], self::$DI['user'], \Feed_Adapter::FORMAT_RSS, null, false)->get_href(); - $this->assertContains($suscribe_link, $pageContent->texte); + $suscribe_link = $linkGenerator->generate($feed, self::$DI['user'], LinkGenerator::FORMAT_RSS); + var_dump($suscribe_link); + $this->assertContains($suscribe_link->getURI(), $pageContent->texte); } } diff --git a/tests/Alchemy/Tests/Phrasea/Core/Provider/FeedServiceProviderTest.php b/tests/Alchemy/Tests/Phrasea/Core/Provider/FeedServiceProviderTest.php new file mode 100644 index 0000000000..0f160ae1c4 --- /dev/null +++ b/tests/Alchemy/Tests/Phrasea/Core/Provider/FeedServiceProviderTest.php @@ -0,0 +1,25 @@ +setTitle("title"); + + $another_feed = new Feed($user); + $another_feed->setTitle("another_title"); + + $feeds = array($feed, $another_feed); + + $aggregate = new Aggregate(self::$DI['app'], $feeds); + + $generator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGenerator') + ->disableOriginalConstructor() + ->getMock(); + + if ($alreadyCreated) { + $token = $this->insertOneAggregateToken($user); + $tokenValue = $token->getValue(); + } + + $capture = null; + $generator->expects($this->once()) + ->method('generate') + ->with('feed_user_aggregated', $this->isType('array'), UrlGenerator::ABSOLUTE_URL) + ->will($this->returnCallback(function ($name, $data, $option) use (&$capture, $expected) { + $capture = $data; + + return $expected; + })); + + $random = self::$DI['app']['tokens']; + + $linkGenerator = new AggregateLinkGenerator($generator, self::$DI['app']['EM'], $random); + + $link = $linkGenerator->generate($aggregate, $user, $format, $page, $renew); + + $this->assertSame($expected, $link->getUri()); + if ($format == "atom") { + $this->assertSame("application/atom+xml", $link->getMimetype()); + $this->assertSame("AGGREGATE - Atom", $link->getTitle()); + } + elseif ($format == "rss") { + $this->assertSame("application/rss+xml", $link->getMimetype()); + $this->assertSame("AGGREGATE - RSS", $link->getTitle()); + } + + if ($alreadyCreated) { + if ($renew) { + $this->assertCount(2, $capture); + $this->assertEquals($format, $capture['format']); + $this->assertNotEquals($tokenValue, $capture['token']); + + $this->assertCount(0, self::$DI['app']['EM'] + ->getRepository("Entities\AggregateToken") + ->findBy(array('value' => $tokenValue))); + $this->assertCount(1, self::$DI['app']['EM'] + ->getRepository("Entities\AggregateToken") + ->findBy(array('value' => $capture['token']))); + } else { + $this->assertEquals(array( + 'token' => $tokenValue, + 'format' => $format, + ), $capture); + + $this->assertCount(1, self::$DI['app']['EM'] + ->getRepository("Entities\AggregateToken") + ->findBy(array('value' => $tokenValue))); + } + } else { + $this->assertCount(2, $capture); + $this->assertEquals($format, $capture['format']); + $this->assertEquals(12, strlen($capture['token'])); + + $this->assertCount(1, self::$DI['app']['EM'] + ->getRepository("Entities\AggregateToken") + ->findBy(array('value' => $capture['token']))); + } + $token = self::$DI['app']['EM'] + ->getRepository('Entities\AggregateToken') + ->findByUser($user); + self::$DI['app']['EM']->remove($token); + self::$DI['app']['EM']->flush(); + } + + public function provideGenerationData() + { + $user = $this->getMockBuilder('User_Adapter') + ->disableOriginalConstructor() + ->getMock(); + + $user->expects($this->any()) + ->method('get_id') + ->will($this->returnValue(42)); + + return array( + array('doliprane', 'atom', $user, null, false, false), + array('doliprane', 'atom', $user, null, false, true), + array('doliprane', 'atom', $user, null, true, false), + array('doliprane', 'atom', $user, null, true, true), + array('doliprane', 'atom', $user, 1, false, false), + array('doliprane', 'atom', $user, 1, false, true), + array('doliprane', 'atom', $user, 1, true, false), + array('doliprane', 'atom', $user, 1, true, true), + array('doliprane', 'rss', $user, null, false, false), + array('doliprane', 'rss', $user, null, false, true), + array('doliprane', 'rss', $user, null, true, false), + array('doliprane', 'rss', $user, null, true, true), + array('doliprane', 'rss', $user, 1, false, false), + array('doliprane', 'rss', $user, 1, false, true), + array('doliprane', 'rss', $user, 1, true, false), + array('doliprane', 'rss', $user, 1, true, true), + ); + } +} diff --git a/tests/Alchemy/Tests/Phrasea/Feed/LinkGeneratorTest.php b/tests/Alchemy/Tests/Phrasea/Feed/LinkGeneratorTest.php new file mode 100644 index 0000000000..7121e4c3dc --- /dev/null +++ b/tests/Alchemy/Tests/Phrasea/Feed/LinkGeneratorTest.php @@ -0,0 +1,126 @@ +persist($feed); + self::$DI['app']['EM']->flush(); + + $generator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGenerator') + ->disableOriginalConstructor() + ->getMock(); + + if ($alreadyCreated) { + $token = $this->insertOneFeedToken($feed, $user); + $tokenValue = $token->getValue(); + } + + $capture = null; + $generator->expects($this->once()) + ->method('generate') + ->with('feed_user', $this->isType('array'), UrlGenerator::ABSOLUTE_URL) + ->will($this->returnCallback(function ($name, $data, $option) use (&$capture, $expected) { + $capture = $data; + + return $expected; + })); + + $random = self::$DI['app']['tokens']; + + $linkGenerator = new LinkGenerator($generator, self::$DI['app']['EM'], $random); + + $link = $linkGenerator->generate($feed, $user, $format, $page, $renew); + + $this->assertSame($expected, $link->getUri()); + if ($format == "atom") { + $this->assertSame("application/atom+xml", $link->getMimetype()); + $this->assertSame("Title - Atom", $link->getTitle()); + } + elseif ($format == "rss") { + $this->assertSame("application/rss+xml", $link->getMimetype()); + $this->assertSame("Title - RSS", $link->getTitle()); + } + + if ($alreadyCreated) { + if ($renew) { + $this->assertCount(3, $capture); + $this->assertEquals($feed->getId(), $capture['id']); + $this->assertEquals($format, $capture['format']); + $this->assertNotEquals($tokenValue, $capture['token']); + + $this->assertCount(0, self::$DI['app']['EM'] + ->getRepository("Entities\FeedToken") + ->findBy(array('value' => $tokenValue))); + $this->assertCount(1, self::$DI['app']['EM'] + ->getRepository("Entities\FeedToken") + ->findBy(array('value' => $capture['token']))); + } else { + $this->assertEquals(array( + 'token' => $tokenValue, + 'id' => $feed->getId(), + 'format' => $format, + ), $capture); + + $this->assertCount(1, self::$DI['app']['EM'] + ->getRepository("Entities\FeedToken") + ->findBy(array('value' => $tokenValue))); + } + } else { + $this->assertCount(3, $capture); + $this->assertEquals($feed->getId(), $capture['id']); + $this->assertEquals($format, $capture['format']); + $this->assertEquals(12, strlen($capture['token'])); + + $this->assertCount(1, self::$DI['app']['EM'] + ->getRepository("Entities\FeedToken") + ->findBy(array('value' => $capture['token']))); + } + $token = self::$DI['app']['EM'] + ->getRepository('Entities\FeedToken') + ->findByFeedAndUser($feed, $user); + self::$DI['app']['EM']->remove($token); + self::$DI['app']['EM']->flush(); + } + + public function provideGenerationData() + { + $user = $this->getMockBuilder('User_Adapter') + ->disableOriginalConstructor() + ->getMock(); + + $user->expects($this->any()) + ->method('get_id') + ->will($this->returnValue(42)); + + $feed = new \Entities\Feed(); + $feed->setTitle('Title'); + + return array( + array('doliprane', 'atom', $feed, $user, null, false, false), + array('doliprane', 'atom', $feed, $user, null, false, true), + array('doliprane', 'atom', $feed, $user, null, true, false), + array('doliprane', 'atom', $feed, $user, null, true, true), + array('doliprane', 'atom', $feed, $user, 1, false, false), + array('doliprane', 'atom', $feed, $user, 1, false, true), + array('doliprane', 'atom', $feed, $user, 1, true, false), + array('doliprane', 'atom', $feed, $user, 1, true, true), + array('doliprane', 'rss', $feed, $user, null, false, false), + array('doliprane', 'rss', $feed, $user, null, false, true), + array('doliprane', 'rss', $feed, $user, null, true, false), + array('doliprane', 'rss', $feed, $user, null, true, true), + array('doliprane', 'rss', $feed, $user, 1, false, false), + array('doliprane', 'rss', $feed, $user, 1, false, true), + array('doliprane', 'rss', $feed, $user, 1, true, false), + array('doliprane', 'rss', $feed, $user, 1, true, true), + ); + } +} diff --git a/tests/classes/PhraseanetPHPUnitAbstract.php b/tests/classes/PhraseanetPHPUnitAbstract.php index ac3ab4e698..6aa28dc264 100644 --- a/tests/classes/PhraseanetPHPUnitAbstract.php +++ b/tests/classes/PhraseanetPHPUnitAbstract.php @@ -4,6 +4,9 @@ use Alchemy\Phrasea\CLI; use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Border\File; use Doctrine\Common\DataFixtures\Loader; +use Entities\AggregateToken; +use Entities\Feed; +use Entities\FeedToken; use Entities\User; use Silex\WebTestCase; use Symfony\Component\HttpFoundation\Response; @@ -323,6 +326,129 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase } } + /** + * Insert one feed + * + * @return \Entities\Feed + */ + protected function insertOneFeed(\User_Adapter $user, $title = null) + { + try { + $feedFixture = new PhraseaFixture\Feed\LoadOneFeed(); + $feedFixture->setUser($user); + + if ($title !== null) { + $feedFixture->setTitle($title); + } + + $loader = new Loader(); + $loader->addFixture($feedFixture); + + $this->insertFixtureInDatabase($loader); + + return $feedFixture->feed; + } catch (\Exception $e) { + $this->fail('Fail to load one Feed : ' . $e->getMessage()); + } + } + + /** + * + * @return \Entities\FeedEntry + */ + protected function insertOneFeedEntry(\User_Adapter $user) + { + try { + $feed = $this->insertOneFeed($user); + + $em = self::$DI['app']['EM']; + + $entry = new \Entities\FeedEntry(); + $entry->setFeed($feed); + $entry->setTitle("test"); + $entry->setSubtitle("description"); + $entry->setAuthorName('user'); + $entry->setAuthorEmail('user@email.com'); + + $publisher = $feed->getPublisher($user); + + if ($publisher !== null) { + $entry->setPublisher($publisher); + } + + $feed->addEntry($entry); + + $em->persist($entry); + $em->persist($feed); + + $em->flush(); + + return $entry; + } catch (\Exception $e) { + $this->fail('Fail to load one FeedEntry : ' . $e->getMessage()); + } + } + + protected function insertOneFeedToken(Feed $feed, \User_Adapter $user) + { + try { + $token = new FeedToken(); + $token->setValue(self::$DI['app']['tokens']->generatePassword(12)); + $token->setFeed($feed); + $token->setUsrId($user->get_id()); + + self::$DI['app']['EM']->persist($token); + self::$DI['app']['EM']->flush(); + } catch (\Exception $e) { + $this->fail('Fail to load one FeedToken : ' . $e->getMessage()); + } + + return $token; + } + + protected function insertOneAggregateToken(\User_Adapter $user) + { + try { + $token = new AggregateToken(); + $token->setValue(self::$DI['app']['tokens']->generatePassword(12)); + $token->setUsrId($user->get_id()); + + self::$DI['app']['EM']->persist($token); + self::$DI['app']['EM']->flush(); + } catch (\Exception $e) { + $this->fail('Fail to load one AggregateToken : ' . $e->getMessage()); + } + + return $token; + } + + /** + * + * @return \Entities\FeedEntry + */ + protected function insertOneFeedItem(\User_Adapter $user) + { + try { + $entry = $this->insertOneFeedEntry($user); + + $item = new \Entities\FeedItem(); + $item->setEntry($entry); + + $entry->addItem($item); + + $em = self::$DI['app']['EM']; + + $em->persist($entry); + $em->persist($item); + + $em->flush(); + + return $entry; + } catch (\Exception $e) { + $this->fail('Fail to load one FeedEntry : ' . $e->getMessage()); + } + } + /** * Insert one basket entry ans set current authenticated user as owner *