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 @@
- {% if feed.is_aggregated() %}
-
|
- {% 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()) %}
+
![]() ![]() |
{{ entry.get_subtitle()|nl2br|raw }}
+{{ entry.getSubtitle()|nl2br|raw }}