diff --git a/bower.json b/bower.json index af8d62cb85..160b1c6703 100644 --- a/bower.json +++ b/bower.json @@ -22,7 +22,8 @@ "zxcvbn": "https://github.com/lowe/zxcvbn.git", "geonames-server-jquery-plugin": "~0.2", "swfobject": "latest", - "tinymce": "~4.0" + "tinymce": "~4.0", + "jquery-galleria": "1.2.9" }, "devDependencies": { "mocha": "latest", diff --git a/lib/Alchemy/Phrasea/Controller/Permalink.php b/lib/Alchemy/Phrasea/Controller/Permalink.php index 5c57aafde9..5464d7a154 100644 --- a/lib/Alchemy/Phrasea/Controller/Permalink.php +++ b/lib/Alchemy/Phrasea/Controller/Permalink.php @@ -31,14 +31,24 @@ class Permalink extends AbstractDelivery $that = $this; - $deliverPermaview = function($sbas_id, $record_id, $token, $subdef, PhraseaApplication $app) { + $retrieveRecord = function ($app, $databox, $token, $record_id, $subdef) { + if (in_array($subdef, array(\databox_subdef::CLASS_PREVIEW, \databox_subdef::CLASS_THUMBNAIL)) && $app['EM']->getRepository('Entities\FeedItem')->isRecordInPublicFeed($app, $databox->get_sbas_id(), $record_id)) { + $record = $databox->get_record($record_id); + } else { + $record = \media_Permalink_Adapter::challenge_token($app, $databox, $token, $record_id, $subdef); + + if (!($record instanceof \record_adapter)) { + throw new NotFoundHttpException('Wrong token.'); + } + } + + return $record; + }; + + $deliverPermaview = function($sbas_id, $record_id, $token, $subdef, PhraseaApplication $app) use ($retrieveRecord) { $databox = $app['phraseanet.appbox']->get_databox((int) $sbas_id); - $record = \media_Permalink_Adapter::challenge_token($app, $databox, $token, $record_id, $subdef); - - if (!$record instanceof \record_adapter) { - throw new NotFoundHttpException('bad luck'); - } + $record = $retrieveRecord($app, $databox, $token, $record_id, $subdef); $params = array( 'subdef_name' => $subdef @@ -51,13 +61,10 @@ class Permalink extends AbstractDelivery return $app['twig']->render('overview.html.twig', $params); }; - $deliverPermalink = function(PhraseaApplication $app, $sbas_id, $record_id, $token, $subdef) use ($that) { + $deliverPermalink = function(PhraseaApplication $app, $sbas_id, $record_id, $token, $subdef) use ($that, $retrieveRecord) { $databox = $app['phraseanet.appbox']->get_databox((int) $sbas_id); - $record = \media_Permalink_Adapter::challenge_token($app, $databox, $token, $record_id, $subdef); - if (!($record instanceof \record_adapter)) { - throw new NotFoundHttpException('bad luck'); - } + $record = $retrieveRecord($app, $databox, $token, $record_id, $subdef); $watermark = $stamp = false; @@ -106,15 +113,11 @@ class Permalink extends AbstractDelivery return $response; }; - $controllers->get('/v1/{sbas_id}/{record_id}/caption/', function(PhraseaApplication $app, Request $request, $sbas_id, $record_id) { + $controllers->get('/v1/{sbas_id}/{record_id}/caption/', function(PhraseaApplication $app, Request $request, $sbas_id, $record_id) use ($retrieveRecord) { $token = $request->query->get('token'); $databox = $app['phraseanet.appbox']->get_databox((int) $sbas_id); - - $record = \media_Permalink_Adapter::challenge_token($app, $databox, $token, $record_id, 'thumbnail'); - if (null === $record) { - throw new NotFoundHttpException("Caption not found"); - } + $record = $retrieveRecord($app, $databox, $token, $record_id, \databox_subdef::CLASS_THUMBNAIL); $caption = $record->get_caption(); return new Response($caption->serialize(\caption_record::SERIALIZE_JSON), 200, array("Content-Type" => 'application/json')); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Feed.php b/lib/Alchemy/Phrasea/Controller/Prod/Feed.php index 730f42a697..84f68e14e9 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Feed.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Feed.php @@ -93,7 +93,7 @@ class Feed implements ControllerProviderInterface $app['EM']->persist($feed); $app['EM']->flush(); - $app['events-manager']->trigger('__FEED_ENTRY_CREATE__', array('entry_id' => $entry->getId()), $entry); + $app['events-manager']->trigger('__FEED_ENTRY_CREATE__', array('entry_id' => $entry->getId(), 'notify_email' => (Boolean) $request->request->get('notify')), $entry); $datas = array('error' => false, 'message' => false); diff --git a/lib/Alchemy/Phrasea/Controller/Root/Login.php b/lib/Alchemy/Phrasea/Controller/Root/Login.php index e70af6d6e9..2266c4ef76 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/Login.php +++ b/lib/Alchemy/Phrasea/Controller/Root/Login.php @@ -49,7 +49,22 @@ class Login implements ControllerProviderInterface { public static function getDefaultTemplateVariables(Application $app) { + $items = array(); + + foreach($app['EM']->getRepository('Entities\FeedItem')->loadLatest($app, 20) as $item) { + $record = $item->getRecord($app); + $preview = $record->get_subdef('preview'); + $permalink = $preview->get_permalink(); + + $items[] = array( + 'record' => $record, + 'preview' => $preview, + 'permalink' => $permalink + ); + } + return array( + 'last_publication_items' => $items, 'instance_title' => $app['phraseanet.registry']->get('GV_homeTitle'), 'has_terms_of_use' => $app->hasTermsOfUse(), 'meta_description' => $app['phraseanet.registry']->get('GV_metaDescription'), diff --git a/lib/Doctrine/Repositories/FeedItemRepository.php b/lib/Doctrine/Repositories/FeedItemRepository.php index 3bcb8e9d9a..7203bd3582 100644 --- a/lib/Doctrine/Repositories/FeedItemRepository.php +++ b/lib/Doctrine/Repositories/FeedItemRepository.php @@ -2,6 +2,7 @@ namespace Repositories; +use Alchemy\Phrasea\Application; use Doctrine\ORM\EntityRepository; /** @@ -12,4 +13,73 @@ use Doctrine\ORM\EntityRepository; */ class FeedItemRepository extends EntityRepository { + /** + * Checks if a record is published in a public feed. + * + * @param Application $app + * @param integer $sbas_id + * @param integer $record_id + * + * @return Boolean + */ + public function isRecordInPublicFeed(Application $app, $sbas_id, $record_id) + { + $dql = 'SELECT i + FROM Entities\FeedItem i + JOIN i.entry e + JOIN e.feed f + WHERE i.sbasId = :sbas_id + AND i.recordId = :record_id + AND f.public = true'; + + $query = $this->_em->createQuery($dql); + $query->setParameters(array('sbas_id' => $sbas_id, 'record_id' => $record_id)); + + return count($query->getResult()) > 0; + } + + /** + * Gets latest items from public feeds. + * + * @param Application $app + * @param integer $nbItems + * + * @return FeedItem[] An array of FeedItem + */ + public function loadLatest(Application $app, $nbItems = 20) + { + $execution = 0; + $items = array(); + + do { + $dql = 'SELECT i + FROM Entities\FeedItem i + JOIN i.entry e + JOIN e.feed f + WHERE f.public = true ORDER BY i.createdOn DESC'; + + $query = $this->_em->createQuery($dql); + $query + ->setFirstResult((integer) $nbItems * $execution) + ->setMaxResults((integer) $nbItems); + + $result = $query->getResult(); + + foreach($result as $item) { + if (null !== $preview = $item->getRecord($app)->get_subdef('preview')) { + if (null !== $permalink = $preview->get_permalink()) { + $items[] = $item; + + if (count($items) >= $nbItems) { + break; + } + } + } + } + + $execution++; + } while (count($items) < $nbItems && count($result) !== 0); + + return $items; + } } diff --git a/lib/classes/ACL.php b/lib/classes/ACL.php index a88d474787..ab3bffcae6 100644 --- a/lib/classes/ACL.php +++ b/lib/classes/ACL.php @@ -119,6 +119,11 @@ class ACL implements cache_cacheableInterface return $this; } + public function set_app(Application $app) + { + $this->app = $app; + } + /** * Check if a hd grant has been received for a record * @@ -253,6 +258,10 @@ class ACL implements cache_cacheableInterface $granted = true; } + if (false === $granted && $this->app['EM']->getRepository('Entities\FeedItem')->isRecordInPublicFeed($this->app, $record->get_sbas_id(), $record->get_record_id())) { + $granted = true; + } + return $granted; } diff --git a/lib/classes/User/Adapter.php b/lib/classes/User/Adapter.php index a874a0bfff..ad8c760978 100644 --- a/lib/classes/User/Adapter.php +++ b/lib/classes/User/Adapter.php @@ -327,6 +327,8 @@ class User_Adapter implements User_Interface, cache_cacheableInterface self::$_instance[$id] = new self($id, $app); $app['phraseanet.appbox']->set_data_to_cache(self::$_instance[$id], '_user_' . $id); } + } else { + self::$_instance[$id]->set_app($app); } return array_key_exists($id, self::$_instance) ? self::$_instance[$id] : false; @@ -349,6 +351,9 @@ class User_Adapter implements User_Interface, cache_cacheableInterface protected function set_app(Application $app) { $this->app = $app; + if (null !== $this->ACL) { + $this->ACL->set_app($app); + } } /** @@ -1074,6 +1079,8 @@ class User_Adapter implements User_Interface, cache_cacheableInterface } } + $this->load_notifications_preferences($this->app); + return $this; } @@ -1090,22 +1097,18 @@ class User_Adapter implements User_Interface, cache_cacheableInterface } } } - $this->notification_preferences_loaded = true; } - protected $notifications_preferences_loaded = false; public function get_notifications_preference(Application $app, $notification_id) { - if (!$this->notifications_preferences_loaded) - $this->load_notifications_preferences($app); + $this->load_preferences($app); - return $this->_prefs['notification_' . $notification_id]; + return isset($this->_prefs['notification_' . $notification_id]) ? $this->_prefs['notification_' . $notification_id] : null; } public function set_notification_preference(Application $app, $notification_id, $value) { - if (!$this->notifications_preferences_loaded) - $this->load_notifications_preferences($app); + $this->load_preferences($app); return $this->_prefs['notification_' . $notification_id] = $value ? '1' : '0'; } diff --git a/lib/classes/databox/field.php b/lib/classes/databox/field.php index 4790ba138d..6774be8752 100644 --- a/lib/classes/databox/field.php +++ b/lib/classes/databox/field.php @@ -285,6 +285,7 @@ class databox_field implements cache_cacheableInterface $databox->set_data_to_cache(self::$_instance[$instance_id], $cache_key); } } + self::$_instance[$instance_id]->app = $app; return self::$_instance[$instance_id]; } diff --git a/lib/classes/eventsmanager/notify/feed.php b/lib/classes/eventsmanager/notify/feed.php index 6caf6ce81b..50140861bf 100644 --- a/lib/classes/eventsmanager/notify/feed.php +++ b/lib/classes/eventsmanager/notify/feed.php @@ -45,7 +45,8 @@ class eventsmanager_notify_feed extends eventsmanager_notifyAbstract public function fire($event, $params, &$entry) { $params = array( - 'entry_id' => $entry->getId() + 'entry_id' => $entry->getId(), + 'notify_email' => $params['notify_email'], ); $dom_xml = new DOMDocument('1.0', 'UTF-8'); @@ -91,7 +92,7 @@ class eventsmanager_notify_feed extends eventsmanager_notifyAbstract /* @var $user_to_notif \User_Adapter */ $mailed = false; - if ($this->shouldSendNotificationFor($user_to_notif->get_id())) { + if ($params['notify_email'] && $this->shouldSendNotificationFor($user_to_notif->get_id())) { $readyToSend = false; try { $token = $this->app['tokens']->getUrlToken( diff --git a/lib/classes/eventsmanager/notifyAbstract.php b/lib/classes/eventsmanager/notifyAbstract.php index df9a1ef5d9..272a7f82a3 100644 --- a/lib/classes/eventsmanager/notifyAbstract.php +++ b/lib/classes/eventsmanager/notifyAbstract.php @@ -26,7 +26,7 @@ abstract class eventsmanager_notifyAbstract extends eventsmanager_eventAbstract protected function get_prefs($class, $usr_id) { $user = User_Adapter::getInstance($usr_id, $this->app); - $pref = $user->getPrefs('notification_' . $class); + $pref = $user->get_notifications_preference($this->app, $class); return null !== $pref ? $pref : 1; } diff --git a/lib/conf.d/PhraseaFixture/Feed/LoadOneFeed.php b/lib/conf.d/PhraseaFixture/Feed/LoadOneFeed.php index c45fd6615e..61e9e8aec9 100644 --- a/lib/conf.d/PhraseaFixture/Feed/LoadOneFeed.php +++ b/lib/conf.d/PhraseaFixture/Feed/LoadOneFeed.php @@ -47,9 +47,7 @@ class LoadOneFeed extends AbstractFixture implements FixtureInterface $feed->setTitle("test"); } - if (isset($this->public) && $this->public !== null) { - $feed->setIsPublic($this->public); - } + $feed->setIsPublic((Boolean) $this->public); $feed->setSubtitle("description"); diff --git a/lib/conf.d/_GV_template.inc b/lib/conf.d/_GV_template.inc index 2bf9d89cc9..62c401375a 100644 --- a/lib/conf.d/_GV_template.inc +++ b/lib/conf.d/_GV_template.inc @@ -348,7 +348,9 @@ return call_user_func_array(function(Application $app) { 'available' => array( 'DISPLAYx1' => _('Single image'), 'SCROLL' => _('Slide show'), - 'COOLIRIS' => 'Cooliris' + 'COOLIRIS' => 'Cooliris', + 'CAROUSEL' => _('Carousel'), + 'GALLERIA' => _('Gallery') ), 'required' => true ) diff --git a/templates/web/login/include/carousel.html.twig b/templates/web/login/include/carousel.html.twig new file mode 100644 index 0000000000..1fdb8aa05d --- /dev/null +++ b/templates/web/login/include/carousel.html.twig @@ -0,0 +1,16 @@ + + + diff --git a/templates/web/login/include/galleria.html.twig b/templates/web/login/include/galleria.html.twig new file mode 100644 index 0000000000..b4752d36fb --- /dev/null +++ b/templates/web/login/include/galleria.html.twig @@ -0,0 +1,25 @@ + + + diff --git a/templates/web/login/index.html.twig b/templates/web/login/index.html.twig index 3dda0bec61..a492178bcc 100644 --- a/templates/web/login/index.html.twig +++ b/templates/web/login/index.html.twig @@ -123,9 +123,35 @@ {% include 'login/include/cooliris-content.html.twig' %} {% elseif display_layout == "SCROLL" %} {% include 'login/include/scroll-content.html.twig' %} + {% elseif display_layout == "CAROUSEL" %} + {% include 'login/include/carousel.html.twig' %} + {% elseif display_layout == "GALLERIA" %} + {% include 'login/include/galleria.html.twig' %} {% endif %} {% endblock %} +{% block header_stylesheet %} + {{ parent() }} + + {% if display_layout == "CAROUSEL" %} + + {% elseif display_layout == "GALLERIA" %} + + {% endif %} +{% endblock %} + {% block scripts %} {{ parent() }} diff --git a/templates/web/prod/actions/publish/publish.html.twig b/templates/web/prod/actions/publish/publish.html.twig index 9fe747c77a..e90668f5f6 100644 --- a/templates/web/prod/actions/publish/publish.html.twig +++ b/templates/web/prod/actions/publish/publish.html.twig @@ -39,6 +39,8 @@ {% set title = publishing.basket().getName() %} {% set desc = publishing.basket().getDescription() %} {% endif %} + +
@@ -60,7 +62,7 @@ {% if feed.isPublic() %} {% endif %} - + {% endif %} {% endfor %} diff --git a/tests/Alchemy/Tests/Phrasea/Application/LightboxTest.php b/tests/Alchemy/Tests/Phrasea/Application/LightboxTest.php index b8a087e5ad..32984f4479 100644 --- a/tests/Alchemy/Tests/Phrasea/Application/LightboxTest.php +++ b/tests/Alchemy/Tests/Phrasea/Application/LightboxTest.php @@ -2,7 +2,7 @@ namespace Alchemy\Tests\Phrasea\Application; -class ApplicationLightboxTest extends \PhraseanetWebTestCaseAuthenticatedAbstract +class LightboxTest extends \PhraseanetWebTestCaseAuthenticatedAbstract { protected $client; @@ -311,21 +311,24 @@ class ApplicationLightboxTest extends \PhraseanetWebTestCaseAuthenticatedAbstrac $this->assertObjectHasAttribute('error', $datas); } - public function testAjaxSetRelease() + public function testAjaxSetReleaseWithRegularBasket() { $basket = $this->insertOneBasket(); - $this->mockNotificationDeliverer('Alchemy\Phrasea\Notification\Mail\MailInfoValidationDone'); - $crawler = self::$DI['client']->request('POST', '/lightbox/ajax/SET_RELEASE/' . $basket->getId() . '/'); $this->assertEquals(200, self::$DI['client']->getResponse()->getStatusCode()); $this->assertEquals('application/json', self::$DI['client']->getResponse()->headers->get('Content-type')); $datas = json_decode(self::$DI['client']->getResponse()->getContent()); $this->assertTrue(is_object($datas), 'asserting good json datas'); $this->assertTrue($datas->error); + } + public function testAjaxSetReleaseWithRegularBasketWithValidation() + { $validationBasket = $this->insertOneValidationBasket(); + $this->mockNotificationDeliverer('Alchemy\Phrasea\Notification\Mail\MailInfoValidationDone'); + foreach ($validationBasket->getElements() as $element) { $element->getUserValidationDatas(self::$DI['app']['authentication']->getUser(), self::$DI['app'])->setAgreement(true); break; diff --git a/tests/Alchemy/Tests/Phrasea/Application/OverviewTest.php b/tests/Alchemy/Tests/Phrasea/Application/OverviewTest.php index 501b04c31a..8cd448adc2 100644 --- a/tests/Alchemy/Tests/Phrasea/Application/OverviewTest.php +++ b/tests/Alchemy/Tests/Phrasea/Application/OverviewTest.php @@ -5,7 +5,7 @@ namespace Alchemy\Tests\Phrasea\Application; use Alchemy\Phrasea\Border\File; use Symfony\Component\HttpFoundation\File\UploadedFile; -class ApplicationOverviewTest extends \PhraseanetWebTestCaseAuthenticatedAbstract +class OverviewTest extends \PhraseanetWebTestCaseAuthenticatedAbstract { public function testDatafilesRouteAuthenticated() { @@ -61,6 +61,25 @@ class ApplicationOverviewTest extends \PhraseanetWebTestCaseAuthenticatedAbstrac $this->assertForbiddenResponse(self::$DI['client']->getResponse()); } + public function testDatafilesRouteOnUnaccessibleRecordIsOkInPublicFeed() + { + $tmp = tempnam(sys_get_temp_dir(), 'testEtag'); + copy(__DIR__ . '/../../../../files/cestlafete.jpg', $tmp); + + $media = self::$DI['app']['mediavorus']->guess($tmp); + + $file = new File(self::$DI['app'], $media, self::$DI['collection_no_access']); + $record = \record_adapter::createFromFile($file, self::$DI['app']); + $record->generate_subdefs($record->get_databox(), self::$DI['app']); + + $item = $this->insertOneFeedItem(self::$DI['user'], true, 1, $record); + + self::$DI['client']->request('GET', '/datafiles/' . $record->get_sbas_id() . '/' . $record->get_record_id() . '/preview/'); + $this->assertEquals(200, self::$DI['client']->getResponse()->getStatusCode()); + + unlink($tmp); + } + public function testDatafilesRouteNotAuthenticatedUnknownSubdef() { self::$DI['app']['authentication']->closeAccount(); @@ -189,6 +208,16 @@ class ApplicationOverviewTest extends \PhraseanetWebTestCaseAuthenticatedAbstrac $this->assertEquals(200, $response->getStatusCode()); } + public function testPermalinkRouteNotAuthenticatedIsOkInPublicFeed() + { + $record = $this->insertOneFeedItem(self::$DI['user'], true)->getRecord(self::$DI['app']); + + self::$DI['app']['authentication']->closeAccount(); + self::$DI['client']->request('GET', '/permalink/v1/' . $record->get_sbas_id() . '/' . $record->get_record_id() . '/preview/'); + + $this->assertEquals(200, self::$DI['client']->getResponse()->getStatusCode()); + } + protected function get_a_permaviewBCcompatibility(array $headers = array()) { $token = self::$DI['record_1']->get_preview()->get_permalink()->get_token(); diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Prod/FeedTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Prod/FeedTest.php index 9011f44890..2dba86f37f 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Prod/FeedTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Prod/FeedTest.php @@ -28,7 +28,7 @@ class FeedTest extends \PhraseanetWebTestCaseAuthenticatedAbstract $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()); + $this->assertEquals(1, $crawler->filterXPath("//input[@value='" . $one_feed->getId() . "' and @name='feed_proposal[]']")->count()); } } } @@ -46,6 +46,7 @@ class FeedTest extends \PhraseanetWebTestCaseAuthenticatedAbstract $feed = $this->insertOneFeed(self::$DI['user']); $params = array( "feed_id" => $feed->getId() + , "notify" => 1 , "title" => "salut" , "subtitle" => "coucou" , "author_name" => "robert" diff --git a/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration-setup.yml b/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration-setup.yml index 21dc8d7c58..8ebfa9f96a 100644 --- a/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration-setup.yml +++ b/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration-setup.yml @@ -14,7 +14,7 @@ main: driver: pdo_sqlite path: '/tmp/db.sqlite' charset: UTF8 - api-timers: true + api-timers: false cache: type: MemcacheCache options: diff --git a/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration.yml b/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration.yml index 21dc8d7c58..8ebfa9f96a 100644 --- a/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration.yml +++ b/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration.yml @@ -14,7 +14,7 @@ main: driver: pdo_sqlite path: '/tmp/db.sqlite' charset: UTF8 - api-timers: true + api-timers: false cache: type: MemcacheCache options: diff --git a/tests/classes/PhraseanetPHPUnitAbstract.php b/tests/classes/PhraseanetPHPUnitAbstract.php index aa22af778c..8593a103c0 100644 --- a/tests/classes/PhraseanetPHPUnitAbstract.php +++ b/tests/classes/PhraseanetPHPUnitAbstract.php @@ -6,6 +6,9 @@ use Alchemy\Phrasea\Border\File; use Doctrine\Common\DataFixtures\Loader; use Entities\AggregateToken; use Entities\Feed; +use Entities\FeedEntry; +use Entities\FeedItem; +use Entities\FeedPublisher; use Entities\FeedToken; use Entities\User; use Silex\WebTestCase; @@ -360,10 +363,10 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase * * @return \Entities\FeedEntry */ - protected function insertOneFeedEntry(\User_Adapter $user) + protected function insertOneFeedEntry(\User_Adapter $user, $public = false) { try { - $feed = $this->insertOneFeed($user); + $feed = $this->insertOneFeed($user, '', $public); $em = self::$DI['app']['EM']; @@ -433,22 +436,31 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase * * @return \Entities\FeedItem */ - protected function insertOneFeedItem(\User_Adapter $user) + protected function insertOneFeedItem(\User_Adapter $user, $public = false, $qty = 1, \record_adapter $record = null) { try { - $entry = $this->insertOneFeedEntry($user); - - $item = new \Entities\FeedItem(); - $item->setEntry($entry); - $item->setRecordId(self::$DI['record_1']->get_record_id()); - $item->setSbasId(self::$DI['record_1']->get_sbas_id()); - - $entry->addItem($item); - $em = self::$DI['app']['EM']; + $entry = $this->insertOneFeedEntry($user, $public); + + for ($i = 0; $i < $qty; $i++) { + $item = new \Entities\FeedItem(); + $item->setEntry($entry); + + if (null === $record) { + $actual = self::$DI['record_'.($i+1)]; + } else { + $actual = $record; + } + + $item->setRecordId($actual->get_record_id()); + $item->setSbasId($actual->get_sbas_id()); + $item->setEntry($entry); + + $entry->addItem($item); + $em->persist($item); + } $em->persist($entry); - $em->persist($item); $em->flush(); } catch (\Exception $e) { diff --git a/www/skins/prod/000000/prodcolor.css b/www/skins/prod/000000/prodcolor.css index 990ab13a14..7dd36cc001 100644 --- a/www/skins/prod/000000/prodcolor.css +++ b/www/skins/prod/000000/prodcolor.css @@ -3203,6 +3203,14 @@ dans l'onglet thesaurus : arbres, menus contextuels margin: 3px 0 10px 0; } +#modal_feed form label { + display:inline; +} + +#modal_feed form input.checkbox { + width: 20px; +} + #modal_feed form textarea { height: 60px; resize: none; diff --git a/www/skins/prod/959595/prodcolor.css b/www/skins/prod/959595/prodcolor.css index 991c6a9d15..9042ab4d5e 100644 --- a/www/skins/prod/959595/prodcolor.css +++ b/www/skins/prod/959595/prodcolor.css @@ -3283,6 +3283,14 @@ dans l'onglet thesaurus : arbres, menus contextuels margin: 3px 0 10px 0; } +#modal_feed form label { + display:inline; +} + +#modal_feed form input.checkbox { + width: 20px; +} + #modal_feed form textarea { height: 60px; resize: none;