diff --git a/lib/Alchemy/Phrasea/Controller/Admin/Publications.php b/lib/Alchemy/Phrasea/Controller/Admin/Publications.php index 83a2a3072f..850183cb08 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/Publications.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/Publications.php @@ -48,9 +48,17 @@ class Publications implements ControllerProviderInterface $controllers->post('/create/', function(PhraseaApplication $app, Request $request) { - $publisher = new FeedPublisher($app['authentication']->getUser(), true); + $publisher = new FeedPublisher(); - $feed = new Feed($publisher, $request->request->get('title'), $request->request->get('subtitle')); + $feed = new Feed(); + + $publisher->setFeed($feed); + $publisher->setUsrId($app['authentication']->getUser()->get_id()); + $publisher->setOwner(true); + + $feed->addPublisher($publisher); + $feed->setTitle($request->request->get('title')); + $feed->setSubtitle($request->request->get('subtitle')); if ($request->request->get('public') == '1') { $feed->setPublic(true); @@ -69,7 +77,7 @@ class Publications implements ControllerProviderInterface })->bind('admin_feeds_create'); $controllers->get('/feed/{id}/', function(PhraseaApplication $app, Request $request, $id) { - $feed = $app["EM"]->getRepository("Entities\Feed")->find($id); + $feed = $app["EM"]->getRepository("Entities\Feed")->findOneBy(array("id" => $id)); return $app['twig'] ->render('admin/publications/fiche.html.twig', array('feed' => $feed, 'error' => $app['request']->query->get('error'))); @@ -79,24 +87,27 @@ class Publications implements ControllerProviderInterface $controllers->post('/feed/{id}/update/', function(PhraseaApplication $app, Request $request, $id) { - $feed = $app["EM"]->getRepository("Entities\Feed")->find($id); + $feed = $app["EM"]->getRepository("Entities\Feed")->findOneBy(array("id" => $id)); try { $collection = \collection::get_from_base_id($app, $request->request->get('base_id')); } catch (\Exception $e) { $collection = null; } - $feed->setTitle($request->request->get('title')); - $feed->setDescription($request->request->get('subtitle')); + if (null !== $request->request->get('title')) { + $feed->setTitle($request->request->get('title')); + } + if (null !== $request->request->get('subtitle')) { + $feed->setSubtitle($request->request->get('subtitle')); + } $feed->setCollection($collection); - $feed->setPublic($request->request->get('public')); - + $feed->setPublic($request->request->get('public') === '1' ? true : false); $app["EM"]->persist($feed); $app["EM"]->flush(); return $app->redirectPath('admin_feeds_list'); })->before(function(Request $request) use ($app) { - $feed = $app["EM"]->getRepository("Entities\Feed")->find($request->attributes->get('id')); + $feed = $app["EM"]->getRepository("Entities\Feed")->findOneBy(array("id" => $request->attributes->get('id'))); if (!$feed->getOwner($app['authentication']->getUser())) { return $app->redirectPath('admin_feeds_feed', array('id' => $request->attributes->get('id'), 'error' => _('You are not the owner of this feed, you can not edit it'))); @@ -110,7 +121,7 @@ class Publications implements ControllerProviderInterface 'success' => false, 'message' => '', ); - $feed = $app["EM"]->getRepository("Entities\Feed")->find($id); + $feed = $app["EM"]->getRepository("Entities\Feed")->findOneBy(array("id" => $id)); $request = $app["request"]; @@ -156,8 +167,6 @@ class Publications implements ControllerProviderInterface throw new \Exception_InternalServerError('Error while resizing'); } - //$feed->set_icon($tmpname); - unset($media); $app['filesystem']->remove($tmpname); @@ -177,9 +186,11 @@ class Publications implements ControllerProviderInterface try { $request = $app['request']; $user = \User_Adapter::getInstance($request->request->get('usr_id'), $app); - $feed = $app["EM"]->getRepository("Entities\Feed")->find($id); + $feed = $app["EM"]->getRepository("Entities\Feed")->findOneBy(array("id" => $id)); - $publisher = new FeedPublisher($user, false); + $publisher = new FeedPublisher(); + $publisher->setUsrId($user->get_id()); + $publisher->setOwner(false); $publisher->setFeed($feed); $feed->addPublisher($publisher); @@ -201,9 +212,13 @@ class Publications implements ControllerProviderInterface try { $request = $app['request']; - $feed = $app["EM"]->getRepository("Entities\Feed")->find($id); + $feed = $app["EM"]->getRepository("Entities\Feed")->findOneBy(array("id" => $id)); + + $publisher = $app["EM"]->getRepository("Entities\FeedPublisher")->findOneBy(array("id" => $request->request->get('publisher_id'))); + if (null === $publisher) { + throw new \Exception_Feed_PublisherNotFound(); + } - $publisher = $app["EM"]->getRepository("Entities\FeedPublisher")->find($request->request->get('publisher_id')); $user = $publisher->getUser($app); if ($feed->isPublisher($user) === true && $feed->isOwner($user) === false) { $feed->removePublisher($publisher); @@ -221,7 +236,7 @@ class Publications implements ControllerProviderInterface ->assert('id', '\d+'); $controllers->post('/feed/{id}/delete/', function(PhraseaApplication $app, $id) { - $feed = $app["EM"]->getRepository("Entities\Feed")->find($id); + $feed = $app["EM"]->getRepository("Entities\Feed")->findOneBy(array("id" => $id)); $publishers = $feed->getPublishers(); foreach ($publishers as $publisher) { $app["EM"]->remove($publisher); diff --git a/lib/Alchemy/Phrasea/Controller/Client/Root.php b/lib/Alchemy/Phrasea/Controller/Client/Root.php index 7bfd23ffcc..6e90f40b93 100644 --- a/lib/Alchemy/Phrasea/Controller/Client/Root.php +++ b/lib/Alchemy/Phrasea/Controller/Client/Root.php @@ -539,7 +539,6 @@ class Root implements ControllerProviderInterface private function getPublicationStartPage(Application $app) { return $app['twig']->render('client/home_inter_pub_basket.html.twig', array( -// 'feeds' => \Feed_Collection::load_all($app, $app['authentication']->getUser()), 'feeds' => $app['EM']->getRepository('Entities\Feed')->getAllforUser($app['authentication']->getUser()), 'image_size' => (int) $app['authentication']->getUser()->getPrefs('images_size') )); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Feed.php b/lib/Alchemy/Phrasea/Controller/Prod/Feed.php index dc477fb40b..8ede6dfdd6 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Feed.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Feed.php @@ -11,10 +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 Alchemy\Phrasea\Feed\Aggregate; +use Alchemy\Phrasea\Feed\Link\AggregateLinkGenerator; +use Alchemy\Phrasea\Feed\Link\FeedLinkGenerator; use Entities\FeedEntry; use Entities\FeedItem; use Silex\Application; @@ -60,7 +60,7 @@ class Feed implements ControllerProviderInterface $title = $request->request->get('title'); $subtitle = $request->request->get('subtitle'); $author_name = $request->request->get('author_name'); - $author_email = $request->request->get('author_email'); + $author_email = $request->request->get('author_mail'); $entry = new FeedEntry(); $entry->setFeed($feed); @@ -134,7 +134,7 @@ class Feed implements ControllerProviderInterface $title = $request->request->get('title'); $subtitle = $request->request->get('subtitle'); $author_name = $request->request->get('author_name'); - $author_mail = $request->request->get('author_email'); + $author_mail = $request->request->get('author_mail'); $entry->setAuthorEmail($author_mail) ->setAuthorName($author_name) @@ -237,7 +237,7 @@ class Feed implements ControllerProviderInterface $datas = $app['twig']->render('prod/feeds/feeds.html.twig' , array( 'feeds' => $feeds - , 'feed' => new Aggregate($app, $feeds) + , 'feed' => new Aggregate($app["EM"], $feeds) , 'page' => $page ) ); @@ -264,7 +264,7 @@ class Feed implements ControllerProviderInterface $feeds = $app["EM"]->getRepository("Entities\Feed")->findAll(); - $aggregate = new Aggregate($app, $feeds); + $aggregate = new Aggregate($app["EM"], $feeds); $link = $app['feed.aggregate-link-generator']->generate($aggregate, $app['authentication']->getUser(), AggregateLinkGenerator::FORMAT_RSS, null, $renew); @@ -283,7 +283,7 @@ class Feed implements ControllerProviderInterface $feed = $app["EM"]->getRepository("Entities\Feed")->loadWithUser($app, $app['authentication']->getUser(), $id); - $link = $app['feed.user-link-generator']->generate($feed, $app['authentication']->getUser(), LinkGenerator::FORMAT_RSS, null, $renew); + $link = $app['feed.user-link-generator']->generate($feed, $app['authentication']->getUser(), FeedLinkGenerator::FORMAT_RSS, null, $renew); $output = array( 'texte' => '
' . _('publication::Voici votre fil RSS personnel. Il vous permettra d\'etre tenu au courrant des publications.') diff --git a/lib/Alchemy/Phrasea/Controller/Root/RSSFeeds.php b/lib/Alchemy/Phrasea/Controller/Root/RSSFeeds.php index b448de9eef..02870affb5 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/RSSFeeds.php +++ b/lib/Alchemy/Phrasea/Controller/Root/RSSFeeds.php @@ -11,6 +11,8 @@ namespace Alchemy\Phrasea\Controller\Root; +use Entities\Feed; +use Alchemy\Phrasea\Feed\Aggregate; use Symfony\Component\HttpFoundation\Response; use Silex\Application; use Silex\ControllerProviderInterface; @@ -27,59 +29,14 @@ class RSSFeeds implements ControllerProviderInterface { $controllers = $app['controllers_factory']; - $display_feed = function(Application $app, $feed, $format, $page, $user = null) { - $total = $feed->getCountTotalEntries(); - $perPage = 5; - $entries = $feed->getEntries((($page - 1) * $perPage), $perPage); - - if ($format == 'rss') { - $content = new \Feed_XML_RSS(); - } - - if ($format == 'atom') { - $content = new \Feed_XML_Atom(); - } - - if ($format == 'cooliris') { - $content = new \Feed_XML_Cooliris(); - } - - if ($user instanceof \User_Adapter) - $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->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->getUserLink($app['phraseanet.registry'], $user, $format, ($page - 1))); - if ($total > ($page * $perPage)) - $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->getEntries() as $entry) - $content->set_item($entry); - - $render = $content->render(); - $response = new Response($render, 200, array('Content-Type' => $content->get_mimetype())); - $response->setCharset('UTF-8'); - - return $response; - }; - - $controllers->get('/feed/{id}/{format}/', function(Application $app, $id, $format) use ($display_feed) { + $controllers->get('/feed/{id}/{format}/', function(Application $app, $id, $format) { $feed = $app["EM"]->getRepository("Entities\Feed")->find($id); - if (!$feed->isPublic()) { + if (!$feed) { + return new Response('Not Found', 404); + } + + if (!$feed->getPublic()) { return new Response('Forbidden', 403); } @@ -88,65 +45,92 @@ class RSSFeeds implements ControllerProviderInterface $page = (int) $request->query->get('page'); $page = $page < 1 ? 1 : $page; - return $display_feed($app, $feed, $format, $page); + return $app[$this->getFormater($format)]->createResponse($feed, $page); }) ->bind('feed_public') ->assert('id', '\d+') ->assert('format', '(rss|atom)'); - $controllers->get('/userfeed/{token}/{id}/{format}/', function(Application $app, $token, $id, $format) use ($display_feed) { - $token = $app["EM"]->getRepository("Entities\FeedToken")->findBy(array("id" => $id)); + $controllers->get('/userfeed/{token}/{id}/{format}/', function(Application $app, $token, $id, $format) { + $token = $app["EM"]->getRepository("Entities\FeedToken")->findOneBy(array("id" => $id)); $feed = $token->getFeed(); + $usrId = $token->getUsrId(); + + $user = \User_Adapter::getInstance($usrId, $app); $request = $app['request']; $page = (int) $request->query->get('page'); $page = $page < 1 ? 1 : $page; - return $display_feed($app, $feed, $format, $page, $token->get_user()); + return $app[$this->getFormater($format)]->createResponse($feed, $page, $user); }) ->bind('feed_user') ->assert('id', '\d+') ->assert('format', '(rss|atom)'); - $controllers->get('/userfeed/aggregated/{token}/{format}/', function(Application $app, $token, $format) use ($display_feed) { - $token = $app["EM"]->getRepository("Entities\AggregateToken")->findBy(array("id" => $id)); + $controllers->get('/userfeed/aggregated/{token}/{format}/', function(Application $app, $token, $format) { + $token = $app["EM"]->getRepository("Entities\AggregateToken")->findOneBy(array("value" => $token)); + $usrId = $token->getUsrId(); + + $user = \User_Adapter::getInstance($usrId, $app); + + $feeds = $app["EM"]->getRepository('Entities\Feed')->getAllForUser($user); + + $aggregate = new Aggregate($app["EM"], $feeds, $token); $request = $app['request']; $page = (int) $request->query->get('page'); $page = $page < 1 ? 1 : $page; - return $display_feed($app, $feed, $format, $page, $token->get_user()); + return $app[$this->getFormater($format)]->createResponse($aggregate, $page, $user); }) ->bind('feed_user_aggregated') ->assert('format', '(rss|atom)'); - $controllers->get('/aggregated/{format}/', function(Application $app, $format) use ($display_feed) { + $controllers->get('/aggregated/{format}/', function(Application $app, $format) { $feeds = $app["EM"]->getRepository("Entities\Feed")->findAllPublic(); - $feed = new Aggregate($app, $feeds); + $feed = new Aggregate($app["EM"], $feeds); $request = $app['request']; $page = (int) $request->query->get('page'); $page = $page < 1 ? 1 : $page; - return $display_feed($app, $feed, $format, $page); + return $app[$this->getFormater($format)]->createResponse($feed, $page); }) ->bind('feed_public_aggregated') ->assert('format', '(rss|atom)'); - $controllers->get('/cooliris/', function(Application $app) use ($display_feed) { + $controllers->get('/cooliris/', function(Application $app) { $feeds = $app["EM"]->getRepository("Entities\Feed")->findAllPublic(); - $feed = new Aggregate($app, $feeds); + $feed = new Aggregate($app["EM"], $feeds); $request = $app['request']; $page = (int) $request->query->get('page'); $page = $page < 1 ? 1 : $page; - return $display_feed($app, $feed, 'cooliris', $page); + return $app[$this->getFormater('cooliris')]->createResponse($feed, $page); }) ->bind('feed_public_cooliris'); return $controllers; } + + private function getFormater($type) + { + switch ($type) { + case 'rss': + return 'feed.rss-formatter'; + break; + case 'atom': + return 'feed.atom-formatter'; + break; + case 'cooliris': + return 'feed.cooliris-formatter'; + break; + default: + throw new InvalidArgumentException(sprintf('Format %s is not recognized.', $format)); + } + } } diff --git a/lib/Alchemy/Phrasea/Core/Provider/FeedServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/FeedServiceProvider.php index f16badbc1c..4009fdb552 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/FeedServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/FeedServiceProvider.php @@ -11,8 +11,12 @@ namespace Alchemy\Phrasea\Core\Provider; -use Alchemy\Phrasea\Feed\LinkGenerator; -use Alchemy\Phrasea\Feed\AggregateLinkGenerator; +use Alchemy\Phrasea\Feed\Formatter\AtomFormatter; +use Alchemy\Phrasea\Feed\Formatter\CoolirisFormatter; +use Alchemy\Phrasea\Feed\Formatter\RssFormatter; +use Alchemy\Phrasea\Feed\Link\AggregateLinkGenerator; +use Alchemy\Phrasea\Feed\Link\FeedLinkGenerator; +use Alchemy\Phrasea\Feed\Link\LinkGeneratorCollection; use Silex\Application; use Silex\ServiceProviderInterface; @@ -21,11 +25,26 @@ class FeedServiceProvider implements ServiceProviderInterface public function register(Application $app) { $app['feed.user-link-generator'] = $app->share(function($app) { - return new LinkGenerator($app['url_generator'], $app['EM'], $app['tokens']); + return new FeedLinkGenerator($app['url_generator'], $app['EM'], $app['tokens']); }); $app['feed.aggregate-link-generator'] = $app->share(function($app) { return new AggregateLinkGenerator($app['url_generator'], $app['EM'], $app['tokens']); }); + $app['feed.link-generator-collection'] = $app->share(function($app) { + $collection = new LinkGeneratorCollection(); + $collection->pushGenerator($app['feed.user-link-generator']); + $collection->pushGenerator($app['feed.aggregate-link-generator']); + return $collection; + }); + $app['feed.rss-formatter'] = $app->share(function($app) { + return new RssFormatter($app['feed.link-generator-collection']); + }); + $app['feed.atom-formatter'] = $app->share(function($app) { + return new AtomFormatter($app['feed.link-generator-collection']); + }); + $app['feed.cooliris-formatter'] = $app->share(function($app) { + return new CoolirisFormatter($app['feed.link-generator-collection']); + }); } public function boot(Application $app) diff --git a/lib/Alchemy/Phrasea/Feed/Aggregate.php b/lib/Alchemy/Phrasea/Feed/Aggregate.php index 3bfbdd6177..03d90e979a 100644 --- a/lib/Alchemy/Phrasea/Feed/Aggregate.php +++ b/lib/Alchemy/Phrasea/Feed/Aggregate.php @@ -4,6 +4,7 @@ namespace Alchemy\Phrasea\Feed; use Alchemy\Phrasea\Application; use Doctrine\ORM\EntityManager; +use Entities\AggregateToken; class Aggregate implements FeedInterface { @@ -35,15 +36,15 @@ class Aggregate implements FeedInterface protected $token; - protected $app; + protected $em; - public function __construct(Application $app, array $feeds) + public function __construct(EntityManager $em, array $feeds, AggregateToken $token = null) { $this->title = 'AGGREGATE'; $this->subtitle = 'AGGREGATE SUBTITLE'; $this->created_on = new \DateTime(); $this->updated_on = new \DateTime(); - $this->app = $app; + $this->em = $em; $tmp_feeds = array(); @@ -52,20 +53,22 @@ class Aggregate implements FeedInterface } $this->feeds = $tmp_feeds; + $this->token = $token; return $this; } - public static function createFromUser(Application $app, \User_Adapter $user) + public static function createFromUser(EntityManager $em, \User_Adapter $user) { - $feeds = $app["EM"]->getRepository('Entities\Feed')->findByUser($user); + $feeds = $em->getRepository('Entities\Feed')->getAllForUser($user); + $token = $em->getRepository('Entities\AggregateToken')->findByUser($user); - return new static($app, $feeds); + return new static($em, $feeds, $token); } public static function create(Application $app, array $feed_ids) { - $feeds = $app["EM"]->getRepository('Entities\Feed')->findByIdArray($feed_ids); + $feeds = $this->em->getRepository('Entities\Feed')->findByIdArray($feed_ids); return new static($app, $feeds); } @@ -75,26 +78,26 @@ class Aggregate implements FeedInterface return true; } - public function getEntries($offset_start, $how_many) + public function getEntries($offset_start = 0, $how_many = null) { - $result = new \Feed_Entry_Collection(); + $count = 0; + $added = 0; - 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); + $collection = array(); + foreach ($this->feeds as $feed) { + foreach ($feed->getEntries() as $entry) { + if ($count >= $offset_start) { + $collection[] = $entry; + $added++; + } + $count++; + if (null !== $how_many && $added == $how_many) { + return $collection; + } } } - return $result; + return $collection; } public function getSubtitle() @@ -142,8 +145,16 @@ class Aggregate implements FeedInterface public function getCountTotalEntries() { if (count($this->feeds) > 0) { - return count($this->app["EM"]->getRepository("Entities\FeedEntry")->findByFeeds($this->feeds)); + return count($this->em->getRepository("Entities\FeedEntry")->findByFeeds($this->feeds)); } return 0; } + + public function hasPage($page, $pageSize) + { + $count = $this->getCountTotalEntries(); + if ($page >= $count / $pageSize) + return true; + return false; + } } diff --git a/lib/Alchemy/Phrasea/Feed/FeedInterface.php b/lib/Alchemy/Phrasea/Feed/FeedInterface.php index 504e9b6e37..976cc07d6b 100644 --- a/lib/Alchemy/Phrasea/Feed/FeedInterface.php +++ b/lib/Alchemy/Phrasea/Feed/FeedInterface.php @@ -1,15 +1,23 @@ linkGenerator = $generator; + } + + public function createResponse(FeedInterface $feed, $page, \User_Adapter $user = null, $generator = 'Phraseanet') + { + $content = $this->format($feed, $page, $user, $generator); + $response = new Response($content, 200, array('Content-Type' => 'application/atom+xml')); + $response->setCharset('UTF-8'); + return $response; + } + + public function format(FeedInterface $feed, $page, \User_Adapter $user = null, $generator = 'Phraseanet') + { + $title = $feed->getTitle(); + $subtitle = $feed->getSubtitle(); + $updated_on = $feed->getUpdatedOn(); + + $document = new \DOMDocument('1.0', 'UTF-8'); + $document->formatOutput = true; + $document->standalone = true; + + $root = $this->addTag($document, $document, 'feed'); + $root->setAttribute('xmlns', 'http://www.w3.org/2005/Atom'); + $root->setAttribute('xmlns:media', 'http://search.yahoo.com/mrss/'); + + $this->addTag($document, $root, 'title', $title); + if ($updated_on instanceof \DateTime) { + $updated_on = $updated_on->format(DATE_ATOM); + $this->addTag($document, $root, 'updated', $updated_on); + } + + if ($feed->hasPage($page + 1, static::PAGE_SIZE)) { + if (null === $user) { + $next = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page + 1); + } else { + $next = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page + 1); + } + } else { + $next = null; + } + if ($feed->hasPage($page - 1, static::PAGE_SIZE)) { + if (null === $user) { + $prev = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page - 1); + } else { + $prev = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page - 1); + } + } else { + $prev = null; + } + + if (null !== $user) { + $feedlink = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page); + } + else { + $feedlink = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page); + } + + if ($feedlink instanceof FeedLink) { + $link = $this->addTag($document, $root, 'link'); + $link->setAttribute('rel', 'self'); + $link->setAttribute('href', $feedlink->getURI()); + $this->addTag($document, $root, 'id', $feedlink->getURI()); + } + + if ($prev instanceof FeedLink) { + $prev_link = $this->addTag($document, $root, 'link'); + $prev_link->setAttribute('rel', 'previous'); + $prev_link->setAttribute('href', $prev->getURI()); + } + + if ($next instanceof FeedLink) { + $next_link = $this->addTag($document, $root, 'link'); + $next_link->setAttribute('rel', 'next'); + $next_link->setAttribute('href', $next->getURI()); + } + + if (isset($generator)) + $this->addTag($document, $root, 'generator', $generator); + if (isset($subtitle)) + $this->addTag($document, $root, 'subtitle', $subtitle); + if (isset($this->icon)) + $this->addTag($document, $root, 'icon', $this->icon); + if (isset($this->author)) { + $author = $this->addTag($document, $root, 'author'); + if (isset($this->author_email)) + $this->addTag($document, $author, 'email', $this->author_email); + if (isset($this->author_name)) + $this->addTag($document, $author, 'name', $this->author_name); + if (isset($this->author_url)) + $this->addTag($document, $author, 'uri', $this->author_url); + } + + foreach ($feed->getEntries() as $item) { + $this->addItem($document, $root, $item, $feedlink); + } + + return $document->saveXML(); + } + + protected function addItem(DOMDocument $document, DOMNode $feed, FeedEntry $entry, FeedLink $link) + { + $entry_node = $this->addTag($document, $feed, 'entry'); + + $link = sprintf('%sentry/%d/', $link->getURI(), $entry->getId()); + + $this->addTag($document, $entry_node, 'id', $link); + $link_tag = $this->addTag($document, $entry_node, 'link'); + $link_tag->setAttribute('rel', 'self'); + $link_tag->setAttribute('href', $link); + + $updated_on = $entry->getUpdatedOn()->format(DATE_ATOM); + $created_on = $entry->getCreatedOn()->format(DATE_ATOM); + + $this->addTag($document, $entry_node, 'updated', $updated_on); + $this->addTag($document, $entry_node, 'published', $created_on); + $this->addTag($document, $entry_node, 'title', $entry->getTitle()); + $author = $this->addTag($document, $entry_node, 'author'); + + if ($entry->getAuthorEmail()) + $this->addTag($document, $author, 'email', $entry->getAuthorEmail()); + if ($entry->getAuthorName()) + $this->addTag($document, $author, 'name', $entry->getAuthorName()); + + $this->addTag($document, $entry_node, 'content', $entry->getSubtitle()); + + foreach ($entry->getItems() as $content) { + $this->addContent($document, $entry_node, $entry, $content); + } + + return $entry_node; + } +} + diff --git a/lib/Alchemy/Phrasea/Feed/Formatter/CoolirisFormatter.php b/lib/Alchemy/Phrasea/Feed/Formatter/CoolirisFormatter.php new file mode 100644 index 0000000000..74fbc4c734 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Formatter/CoolirisFormatter.php @@ -0,0 +1,266 @@ +linkGenerator = $generator; + } + + public function createResponse(FeedInterface $feed, $page, \User_Adapter $user = null, $generator = 'Phraseanet') + { + $content = $this->format($feed, $page, $user, $generator); + $response = new Response($content, 200, array('Content-Type' => 'application/rss+xml')); + $response->setCharset('UTF-8'); + return $response; + } + + public function format(FeedInterface $feed, $page, \User_Adapter $user = null, $generator = 'Phraseanet') + { + $title = $feed->getTitle(); + $subtitle = $feed->getSubtitle(); + $updated_on = $feed->getUpdatedOn(); + + $doc = new \DOMDocument('1.0', 'UTF-8'); + $doc->formatOutput = true; + $doc->standalone = true; + + $root = $this->addTag($doc, $doc, 'rss'); + + $root->setAttribute('version', self::VERSION); + $root->setAttribute('xmlns:media', 'http://search.yahoo.com/mrss/'); + $root->setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom'); + $root->setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + + $channel = $this->addTag($doc, $root, 'channel'); + + $this->addTag($doc, $channel, 'title', $title); + $this->addTag($doc, $channel, 'dc:title', $title); + $this->addTag($doc, $channel, 'description', $subtitle); + + if (null !== $user) { + $link = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page); + } + else { + $link = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page); + } + + if ($link instanceof FeedLink) + $this->addTag($doc, $channel, 'link', $link->getURI()); + + if (isset($this->language)) + $this->addTag($doc, $channel, 'language', $this->language); + if (isset($this->copyright)) + $this->addTag($doc, $channel, 'copyright', $this->copyright); + if (isset($this->managingEditor)) + $this->addTag($doc, $channel, 'managingEditor', $this->managingEditor); + if (isset($this->webMaster)) + $this->addTag($doc, $channel, 'webMaster', $this->webMaster); + if ($updated_on instanceof DateTime) { + $updated_on = $updated_on->format(DATE_RFC2822); + $this->addTag($doc, $channel, 'pubDate', $updated_on); + } + if (isset($this->lastBuildDate) && $this->lastBuildDate instanceof DateTime) { + $last_build = $this->lastBuildDate->format(DATE_RFC2822); + $this->addTag($doc, $channel, 'lastBuildDate', $last_build); + } + if (isset($this->categories) && count($this->categories) > 0) { + foreach ($this->categories as $category) { + $this->addTag($doc, $channel, 'category', $category); + } + } + if (isset($this->linkgenerator)) + $this->addTag($doc, $channel, 'generator', $this->linkgenerator); + if (isset($this->docs)) + $this->addTag($doc, $channel, 'docs', $this->docs); + if (isset($this->ttl)) + $this->addTag($doc, $channel, 'ttl', $this->ttl); + if (isset($this->image) && $this->image instanceof Feed_XML_RSS_Image) { + $image = $this->addTag($doc, $channel, 'image'); + $this->addTag($doc, $image, 'url', $this->image->get_url()); + $this->addTag($doc, $image, 'title', $this->image->get_title()); + $this->addTag($doc, $image, 'link', $this->image->get_link()); + if ($this->image->get_width()) + $this->addTag($doc, $image, 'width', $this->image->get_width()); + if ($this->image->get_height()) + $this->addTag($doc, $image, 'height', $this->image->get_height()); + if ($this->image->get_description()) + $this->addTag($doc, $image, 'description', $this->image->get_description()); + } + if (isset($this->skipHours) && count($this->skipHours)) { + $skipHours = $this->addTag($doc, $channel, 'skipHours'); + foreach ($this->skipHours as $hour) { + $this->addTag($doc, $skipHours, 'hour', $hour); + } + } + if (isset($this->skipDays) && count($this->skipDays) > 0) { + $skipDays = $this->addTag($doc, $channel, 'skipDays'); + foreach ($this->skipDays as $day) { + $this->addTag($doc, $skipDays, 'day', $day); + } + } + if ($link instanceof FeedLink) { + $self_link = $this->addTag($doc, $channel, 'atom:link'); + $self_link->setAttribute('rel', 'self'); + $self_link->setAttribute('href', $link->getURI()); + } + + if ($feed->hasPage($page + 1, static::PAGE_SIZE)) { + if (null === $user) { + $next = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page + 1); + } else { + $next = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page + 1); + } + } else { + $next = null; + } + if ($feed->hasPage($page - 1, static::PAGE_SIZE)) { + if (null === $user) { + $prev = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page - 1); + } else { + $prev = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page - 1); + } + } else { + $prev = null; + } + + $prefix = 'atom'; + + if ($prev instanceof FeedLink) { + $prev_link = $this->addTag($doc, $channel, $prefix . 'link'); + $prev_link->setAttribute('rel', 'previous'); + $prev_link->setAttribute('href', $prev->getURI()); + } + + if ($next instanceof FeedLink) { + $next_link = $this->addTag($doc, $channel, $prefix . 'link'); + $next_link->setAttribute('rel', 'next'); + $next_link->setAttribute('href', $next->getURI()); + } + + foreach ($feed->getEntries() as $item) { + $this->addItem($doc, $channel, $item); + } + + return $doc->saveXML(); + } + + protected function addItem(\DOMDocument $document, \DOMNode $feed, FeedEntry $entry) + { + foreach ($entry->get_content() as $content) { + $this->addContent($document, $feed, $entry, $content); + } + } + + protected function addContent(\DOMDocument $document, \DOMNode $node, FeedItem $content) + { + + $preview_sd = $content->getRecord()->get_subdef('preview'); + $preview_permalink = $preview_sd->get_permalink(); + $thumbnail_sd = $content->getRecord()->get_thumbnail(); + $thumbnail_permalink = $thumbnail_sd->get_permalink(); + + $medium = strtolower($content->getRecord()->get_type()); + + if ( ! in_array($medium, array('image', 'audio', 'video'))) { + return $this; + } + + if (! $preview_permalink || ! $thumbnail_permalink) { + return $this; + } + + //add item node to channel node + $item = $this->addTag($document, $node, 'item'); + + $caption = $content->getRecord()->get_caption(); + + $title_field = $caption->get_dc_field(databox_Field_DCESAbstract::Title); + if ($title_field) { + $str_title = $title_field->get_serialized_values(' '); + } else { + $str_title = $content->getRecord()->get_title(); + } + + //attach tile node to item node + $title = $this->addTag($document, $item, 'title', $str_title); + + $desc_field = $caption->get_dc_field(databox_Field_DCESAbstract::Description); + if ($desc_field) { + $str_desc = $desc_field->get_serialized_values(' '); + } else { + $str_desc = ''; + } + + //attach desc node to item node + $desc = $this->addTag($document, $item, 'description', $str_desc); + + $duration = $content->getRecord()->get_duration(); + + if ($preview_permalink) { + $preview = $this->addTag($document, $item, 'media:content'); + + $preview->setAttribute('url', $preview_permalink->get_url()); + $preview->setAttribute('fileSize', $preview_sd->get_size()); + $preview->setAttribute('type', $preview_sd->get_mime()); + $preview->setAttribute('medium', $medium); + $preview->setAttribute('expression', 'full'); + $preview->setAttribute('isDefault', 'true'); + + if ($preview_sd->get_width()) + $preview->setAttribute('width', $preview_sd->get_width()); + if ($preview_sd->get_height()) + $preview->setAttribute('height', $preview_sd->get_height()); + if ($duration) + $preview->setAttribute('duration', $duration); + } + + if ($thumbnail_permalink) { + $thumbnail = $this->addTag($document, $item, 'media:thumbnail'); + + $thumbnail->setAttribute('url', $thumbnail_permalink->get_url()); + + if ($thumbnail_sd->get_width()) + $thumbnail->setAttribute('width', $thumbnail_sd->get_width()); + if ($thumbnail_sd->get_height()) + $thumbnail->setAttribute('height', $thumbnail_sd->get_height()); + + $thumbnail = $this->addTag($document, $item, 'media:content'); + + $thumbnail->setAttribute('url', $thumbnail_permalink->get_url()); + $thumbnail->setAttribute('fileSize', $thumbnail_sd->get_size()); + $thumbnail->setAttribute('type', $thumbnail_sd->get_mime()); + $thumbnail->setAttribute('medium', $medium); + $thumbnail->setAttribute('isDefault', 'false'); + + if ($thumbnail_sd->get_width()) + $thumbnail->setAttribute('width', $thumbnail_sd->get_width()); + if ($thumbnail_sd->get_height()) + $thumbnail->setAttribute('height', $thumbnail_sd->get_height()); + if ($duration) + $thumbnail->setAttribute('duration', $duration); + } + + return $this; + } +} + diff --git a/lib/Alchemy/Phrasea/Feed/Formatter/FeedFormatterAbstract.php b/lib/Alchemy/Phrasea/Feed/Formatter/FeedFormatterAbstract.php new file mode 100644 index 0000000000..97974f2729 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Formatter/FeedFormatterAbstract.php @@ -0,0 +1,164 @@ +createElement($tagname); + + if (trim($tagcontent) !== '') + $tag->appendChild($document->createTextNode($tagcontent)); + $node->appendChild($tag); + + return $tag; + } + + /** + * + * @param DOMDocument $document + * @param DOMNode $item + * @param FeedItem $content + * @return FeedFormaterInterface + */ + protected function addContent(\DOMDocument $document, \DOMNode $item, FeedItem $content) + { + $preview_sd = $content->getRecord()->get_subdef('preview'); + $preview_permalink = $preview_sd->get_permalink(); + $thumbnail_sd = $content->getRecord()->get_thumbnail(); + $thumbnail_permalink = $thumbnail_sd->get_permalink(); + + $medium = strtolower($content->getRecord()->get_type()); + + if ( ! in_array($medium, array('image', 'audio', 'video'))) { + return $this; + } + + if (! $preview_permalink || ! $thumbnail_permalink) { + return $this; + } + + $group = $this->addTag($document, $item, 'media:group'); + + $caption = $content->getRecord()->get_caption(); + + $title_field = $caption->get_dc_field(databox_Field_DCESAbstract::Title); + if ($title_field) { + $str_title = $title_field->get_serialized_values(' '); + $title = $this->addTag($document, $group, 'media:title', $str_title); + $title->setAttribute('type', 'plain'); + } + + $desc_field = $caption->get_dc_field(databox_Field_DCESAbstract::Description); + if ($desc_field) { + $str_desc = $desc_field->get_serialized_values(' '); + $desc = $this->addTag($document, $group, 'media:description', $str_desc); + $desc->setAttribute('type', 'plain'); + } + + $contrib_field = $caption->get_dc_field(databox_Field_DCESAbstract::Contributor); + if ($contrib_field) { + $str_contrib = $contrib_field->get_serialized_values(' '); + $contrib = $this->addTag($document, $group, 'media:credit', $str_contrib); + $contrib->setAttribute('role', 'contributor'); + $contrib->setAttribute('scheme', 'urn:ebu'); + } + + $director_field = $caption->get_dc_field(databox_Field_DCESAbstract::Creator); + if ($director_field) { + $str_director = $director_field->get_serialized_values(' '); + $director = $this->addTag($document, $group, 'media:credit', $str_director); + $director->setAttribute('role', 'director'); + $director->setAttribute('scheme', 'urn:ebu'); + } + + $publisher_field = $caption->get_dc_field(databox_Field_DCESAbstract::Publisher); + if ($publisher_field) { + $str_publisher = $publisher_field->get_serialized_values(' '); + $publisher = $this->addTag($document, $group, 'media:credit', $str_publisher); + $publisher->setAttribute('role', 'publisher'); + $publisher->setAttribute('scheme', 'urn:ebu'); + } + + $rights_field = $caption->get_dc_field(databox_Field_DCESAbstract::Rights); + if ($rights_field) { + $str_rights = $rights_field->get_serialized_values(' '); + $rights = $this->addTag($document, $group, 'media:copyright', $str_rights); + } + + $keyword_field = $caption->get_dc_field(databox_Field_DCESAbstract::Subject); + if ($keyword_field) { + $str_keywords = $keyword_field->get_serialized_values(', '); + $keywords = $this->addTag($document, $group, 'media:keywords', $str_keywords); + } + + $duration = $content->get_record()->get_duration(); + + if ($preview_permalink) { + $preview = $this->addTag($document, $group, 'media:content'); + + $preview->setAttribute('url', $preview_permalink->get_url()); + $preview->setAttribute('fileSize', $preview_sd->get_size()); + $preview->setAttribute('type', $preview_sd->get_mime()); + $preview->setAttribute('medium', $medium); + $preview->setAttribute('expression', 'full'); + $preview->setAttribute('isDefault', 'true'); + + if ($preview_sd->get_width()) + $preview->setAttribute('width', $preview_sd->get_width()); + if ($preview_sd->get_height()) + $preview->setAttribute('height', $preview_sd->get_height()); + if ($duration) + $preview->setAttribute('duration', $duration); + } + + if ($thumbnail_permalink) { + $thumbnail = $this->addTag($document, $group, 'media:thumbnail'); + + $thumbnail->setAttribute('url', $thumbnail_permalink->get_url()); + + if ($thumbnail_sd->get_width()) + $thumbnail->setAttribute('width', $thumbnail_sd->get_width()); + if ($thumbnail_sd->get_height()) + $thumbnail->setAttribute('height', $thumbnail_sd->get_height()); + + $thumbnail = $this->addTag($document, $group, 'media:content'); + + $thumbnail->setAttribute('url', $thumbnail_permalink->get_url()); + $thumbnail->setAttribute('fileSize', $thumbnail_sd->get_size()); + $thumbnail->setAttribute('type', $thumbnail_sd->get_mime()); + $thumbnail->setAttribute('medium', $medium); + $thumbnail->setAttribute('isDefault', 'false'); + + if ($thumbnail_sd->get_width()) + $thumbnail->setAttribute('width', $thumbnail_sd->get_width()); + if ($thumbnail_sd->get_height()) + $thumbnail->setAttribute('height', $thumbnail_sd->get_height()); + if ($duration) + $thumbnail->setAttribute('duration', $duration); + } + + return $this; + } + +} diff --git a/lib/Alchemy/Phrasea/Feed/Formatter/FeedFormatterInterface.php b/lib/Alchemy/Phrasea/Feed/Formatter/FeedFormatterInterface.php new file mode 100644 index 0000000000..7ac7185652 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Formatter/FeedFormatterInterface.php @@ -0,0 +1,20 @@ +linkGenerator = $generator; + } + + public function createResponse(FeedInterface $feed, $page, \User_Adapter $user = null, $generator = 'Phraseanet') + { + $content = $this->format($feed, $page, $user, $generator); + $response = new Response($content, 200, array('Content-Type' => 'application/rss+xml')); + $response->setCharset('UTF-8'); + return $response; + } + + public function format(FeedInterface $feed, $page, \User_Adapter $user = null, $generator = 'Phraseanet') + { + $title = $feed->getTitle(); + $subtitle = $feed->getSubtitle(); + $updated_on = $feed->getUpdatedOn(); + + if ($feed->hasPage($page + 1, static::PAGE_SIZE)) { + if (null === $user) { + $next = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page + 1); + } else { + $next = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page + 1); + } + } else { + $next = null; + } + if ($feed->hasPage($page - 1, static::PAGE_SIZE)) { + if (null === $user) { + $prev = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page - 1); + } else { + $prev = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page - 1); + } + } else { + $prev = null; + } + + if (null !== $user) { + $link = $this->linkGenerator->generate($feed, $user, static::FORMAT, $page); + } + else { + $link = $this->linkGenerator->generatePublic($feed, static::FORMAT, $page); + } + + $doc = new \DOMDocument('1.0', 'UTF-8'); + $doc->formatOutput = true; + $doc->standalone = true; + + $root = $this->addTag($doc, $doc, 'rss'); + + $root->setAttribute('version', static::VERSION); + $root->setAttribute('xmlns:media', 'http://search.yahoo.com/mrss/'); + $root->setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom'); + $root->setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + + $channel = $this->addTag($doc, $root, 'channel'); + + $this->addTag($doc, $channel, 'title', $title); + $this->addTag($doc, $channel, 'dc:title', $title); + $this->addTag($doc, $channel, 'description', $subtitle); + if ($link instanceof FeedLink) + $this->addTag($doc, $channel, 'link', $link->getURI()); + + if (isset($this->language)) + $this->addTag($doc, $channel, 'language', $this->language); + if (isset($this->copyright)) + $this->addTag($doc, $channel, 'copyright', $this->copyright); + if (isset($this->managingEditor)) + $this->addTag($doc, $channel, 'managingEditor', $this->managingEditor); + if (isset($this->webMaster)) + $this->addTag($doc, $channel, 'webMaster', $this->webMaster); + if ($updated_on instanceof \DateTime) { + $updated_on = $updated_on->format(DATE_RFC2822); + $this->addTag($doc, $channel, 'pubDate', $updated_on); + } + if (isset($this->lastBuildDate) && $this->lastBuildDate instanceof DateTime) { + $last_build = $this->lastBuildDate->format(DATE_RFC2822); + $this->addTag($doc, $channel, 'lastBuildDate', $last_build); + } + if (isset($this->categories) && count($this->categories) > 0) { + foreach ($this->categories as $category) { + $this->addTag($doc, $channel, 'category', $category); + } + } + if (isset($generator)) + $this->addTag($doc, $channel, 'generator', $generator); + if (isset($this->docs)) + $this->addTag($doc, $channel, 'docs', $this->docs); + if (isset($this->ttl)) + $this->addTag($doc, $channel, 'ttl', $this->ttl); + if (isset($this->image) && $this->image instanceof Feed_XML_RSS_Image) { + $image = $this->addTag($doc, $channel, 'image'); + $this->addTag($doc, $image, 'url', $this->image->get_url()); + $this->addTag($doc, $image, 'title', $this->image->get_title()); + $this->addTag($doc, $image, 'link', $this->image->get_link()); + if ($this->image->get_width()) + $this->addTag($doc, $image, 'width', $this->image->get_width()); + if ($this->image->get_height()) + $this->addTag($doc, $image, 'height', $this->image->get_height()); + if ($this->image->get_description()) + $this->addTag($doc, $image, 'description', $this->image->get_description()); + } + if (isset($this->skipHours) && count($this->skipHours)) { + $skipHours = $this->addTag($doc, $channel, 'skipHours'); + foreach ($this->skipHours as $hour) { + $this->addTag($doc, $skipHours, 'hour', $hour); + } + } + if (isset($this->skipDays) && count($this->skipDays) > 0) { + $skipDays = $this->addTag($doc, $channel, 'skipDays'); + foreach ($this->skipDays as $day) { + $this->addTag($doc, $skipDays, 'day', $day); + } + } + if ($link instanceof FeedLink) { + $self_link = $this->addTag($doc, $channel, 'atom:link'); + $self_link->setAttribute('rel', 'self'); + $self_link->setAttribute('href', $link->getURI()); + } + + $prefix = 'atom:'; + + if ($prev instanceof FeedLink) { + $prev_link = $this->addTag($doc, $channel, $prefix . 'link'); + $prev_link->setAttribute('rel', 'previous'); + $prev_link->setAttribute('href', $prev->getURI()); + } + + if ($next instanceof FeedLink) { + $next_link = $this->addTag($doc, $channel, $prefix . 'link'); + $next_link->setAttribute('rel', 'next'); + $next_link->setAttribute('href', $next->getURI()); + } + + foreach ($feed->getEntries() as $item) { + $this->addItem($doc, $channel, $item); + } + + return $doc->saveXML(); + } + + protected function addItem(\DOMDocument $document, \DOMNode $node, FeedEntry $entry) + { + $item = $this->addTag($document, $node, 'item'); + + $link = $entry->getLink(); + + $this->addTag($document, $item, 'title', $entry->getTitle()); + $this->addTag($document, $item, 'description', $entry->getSubtitle()); + + $author = sprintf( + '%s (%s)' + , $entry->getAuthorEmail() + , $entry->getAuthorName() + ); + $created_on = $entry->getCreatedOn()->format(DATE_RFC2822); + + $this->addTag($document, $item, 'author', $author); + $this->addTag($document, $item, 'pubDate', $created_on); + $this->addTag($document, $item, 'guid', $link->getURI()); + $this->addTag($document, $item, 'link', $link->getURI()); + + /** + * Missing : + * + * category Includes the item in one or more categories. More. + * comments URL of a page for comments relating to the item. More. + * enclosure Describes a media object that is attached to the item. More. + * source The RSS channel that the item came from. More. + * + */ + foreach ($entry->getItems() as $content) { + $this->addContent($document, $item, $entry, $content); + } + + return $item; + } +} + diff --git a/lib/Alchemy/Phrasea/Feed/Link/AggregateLinkGenerator.php b/lib/Alchemy/Phrasea/Feed/Link/AggregateLinkGenerator.php new file mode 100644 index 0000000000..22afd10a2e --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Link/AggregateLinkGenerator.php @@ -0,0 +1,122 @@ +generator = $generator; + $this->em = $em; + $this->random = $random; + } + + public function generate(FeedInterface $aggregate, \User_Adapter $user, $format, $page = null, $renew = false) + { + if (!$this->supports($aggregate)) { + throw new InvalidArgumentException('AggregateLinkGenerator only support aggregate feeds.'); + } + + switch ($format) { + case self::FORMAT_ATOM: + $params = array('token' => $this->getAggregateToken($user, $renew)->getValue(), + 'format' => 'atom'); + if (null !== $page) { + $params['page'] = $page; + } + return new FeedLink( + $this->generator->generate('feed_user_aggregated', $params, UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $aggregate->getTitle(), 'Atom'), + 'application/atom+xml' + ); + break; + case self::FORMAT_RSS: + $params = array('token' => $this->getAggregateToken($user, $renew)->getValue(), + 'format' => 'rss'); + if (null !== $page) { + $params['page'] = $page; + } + return new FeedLink( + $this->generator->generate('feed_user_aggregated', $params, UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $aggregate->getTitle(), 'RSS'), + 'application/rss+xml' + ); + break; + default: + throw new InvalidArgumentException(sprintf('Format %s is not recognized.', $format)); + } + } + + public function supports(FeedInterface $feed) + { + return $feed instanceof Aggregate; + } + + public function generatePublic(FeedInterface $aggregate, $format, $page = null) + { + if (!$this->supports($aggregate)) { + throw new InvalidArgumentException('AggregateLinkGenerator only support aggregate feeds.'); + } + + switch ($format) { + case self::FORMAT_ATOM: + $params = array('format' => 'atom'); + if (null !== $page) { + $params['page'] = $page; + } + return new FeedLink( + $this->generator->generate('feed_public_aggregated', $params, UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $aggregate->getTitle(), 'Atom'), + 'application/atom+xml' + ); + break; + case self::FORMAT_RSS: + $params = array('format' => 'rss'); + if (null !== $page) { + $params['page'] = $page; + } + return new FeedLink( + $this->generator->generate('feed_public_aggregated', $params, 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/Link/FeedLink.php b/lib/Alchemy/Phrasea/Feed/Link/FeedLink.php new file mode 100644 index 0000000000..3d55b2c562 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Link/FeedLink.php @@ -0,0 +1,68 @@ +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/Link/FeedLinkGenerator.php b/lib/Alchemy/Phrasea/Feed/Link/FeedLinkGenerator.php new file mode 100644 index 0000000000..aed7972f5d --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Link/FeedLinkGenerator.php @@ -0,0 +1,142 @@ +generator = $generator; + $this->em = $em; + $this->random = $random; + } + + public function generate(FeedInterface $feed, \User_Adapter $user, $format, $page = null, $renew = false) + { + if (!$this->supports($feed)) { + throw new InvalidArgumentException('FeedLinkGenerator only support aggregate feeds.'); + } + + switch ($format) { + case self::FORMAT_ATOM: + $params = array('token' => $this->getFeedToken($feed, $user, $renew)->getValue(), + 'id' => $feed->getId(), + 'format' => 'atom'); + if (null !== $page) { + $params['page'] = $page; + } + + return new FeedLink( + $this->generator->generate('feed_user', $params, UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $feed->getTitle(), 'Atom'), + 'application/atom+xml' + ); + break; + case self::FORMAT_RSS: + $params = array('token' => $this->getFeedToken($feed, $user, $renew)->getValue(), + 'id' => $feed->getId(), + 'format' => 'rss'); + if (null !== $page) { + $params['page'] = $page; + } + return new FeedLink( + $this->generator->generate('feed_user', $params, UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $feed->getTitle(), 'RSS'), + 'application/rss+xml' + ); + break; + default: + throw new InvalidArgumentException(sprintf('Format %s is not recognized.', $format)); + } + } + + public function supports(FeedInterface $feed) + { + return $feed instanceof Feed; + } + + public function generatePublic(FeedInterface $feed, $format, $page = null) + { + if (!$this->supports($feed)) { + throw new InvalidArgumentException('FeedLinkGenerator only support aggregate feeds.'); + } + + switch ($format) { + case self::FORMAT_ATOM: + $params = array('id' => $feed->getId(), + 'format' => 'atom'); + if (null !== $page) { + $params['page'] = $page; + } + + return new FeedLink( + $this->generator->generate('feed_public', $params, UrlGenerator::ABSOLUTE_URL), + sprintf('%s - %s', $feed->getTitle(), 'Atom'), + 'application/atom+xml' + ); + break; + case self::FORMAT_RSS: + $params = array('id' => $feed->getId(), + 'format' => 'rss'); + if (null !== $page) { + $params['page'] = $page; + } + + return new FeedLink( + $this->generator->generate('feed_public', $params, 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/Link/FeedLinkInterface.php b/lib/Alchemy/Phrasea/Feed/Link/FeedLinkInterface.php new file mode 100644 index 0000000000..6e158bdc23 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Link/FeedLinkInterface.php @@ -0,0 +1,30 @@ +generators[] = $generator; + } + + public function generate(FeedInterface $feed, \User_Adapter $user, $format, $page = null, $renew = false) + { + if (null === $generator = $this->findGenerator($feed)) { + throw new InvalidArgumentException(sprintf('Unable to find a valid generator for %s', get_class($feed))); + } + + return $generator->generate($feed, $user, $format, $page); + } + + public function generatePublic(FeedInterface $feed, $format, $page = null) + { + if (null === $generator = $this->findGenerator($feed)) { + throw new InvalidArgumentException(sprintf('Unable to find a valid generator for %s', get_class($feed))); + } + + return $generator->generatePublic($feed, $format, $page); + } + + public function supports(FeedInterface $feed) + { + return null !== $this->findGenerator($feed); + } + + private function findGenerator(FeedInterface $feed) + { + foreach ($this->generators as $generator) { + if ($generator->supports($feed)) { + return $generator; + } + } + + return null; + } +} diff --git a/lib/Alchemy/Phrasea/Feed/Link/LinkGeneratorInterface.php b/lib/Alchemy/Phrasea/Feed/Link/LinkGeneratorInterface.php new file mode 100644 index 0000000000..017b49d035 --- /dev/null +++ b/lib/Alchemy/Phrasea/Feed/Link/LinkGeneratorInterface.php @@ -0,0 +1,32 @@ +entries; + } return $this->entries->slice($offset_start, $how_many); } @@ -434,7 +437,7 @@ class Feed implements FeedInterface public function addEntrie(\Entities\FeedEntry $entries) { $this->entries[] = $entries; - + return $this; } @@ -447,4 +450,12 @@ class Feed implements FeedInterface { $this->entries->removeElement($entries); } + + public function hasPage($page, $pageSize) + { + $count = $this->getCountTotalEntries(); + if ($page >= $count / $pageSize + $pageSize) + return true; + return false; + } } \ No newline at end of file diff --git a/templates/web/admin/publications/fiche.html.twig b/templates/web/admin/publications/fiche.html.twig index e83e21c902..ce47d325a9 100644 --- a/templates/web/admin/publications/fiche.html.twig +++ b/templates/web/admin/publications/fiche.html.twig @@ -89,7 +89,7 @@