From fd5efdcd4e979d1ffa9e012e4207ddaa795cbfc6 Mon Sep 17 00:00:00 2001 From: Laurent Laffont <llaffont@afi-sa.fr> Date: Thu, 9 Sep 2021 12:01:48 +0200 Subject: [PATCH] dev #138425 Agenda / Multiple timings : - display event period on agenda widget (Templating & Historic) - fix fetch of next timing in current month --- VERSIONS_WIP/138425 | 1 + library/Class/Article/EventTimingPeriod.php | 49 ++++++ library/Class/Article/SelectWithTimings.php | 2 +- .../View/Helper/Article/RenderAbstract.php | 20 ++- .../Library/View/Wrapper/Article.php | 10 ++ .../ArticlesMultipleTimingsCalendarTest.php | 150 +++++++++++++++--- .../ArticlesMultipleTimingsLoaderTest.php | 2 +- 7 files changed, 205 insertions(+), 29 deletions(-) create mode 100644 VERSIONS_WIP/138425 create mode 100644 library/Class/Article/EventTimingPeriod.php diff --git a/VERSIONS_WIP/138425 b/VERSIONS_WIP/138425 new file mode 100644 index 00000000000..c007496e6e5 --- /dev/null +++ b/VERSIONS_WIP/138425 @@ -0,0 +1 @@ + - ticket #138425 : Agenda avec horaires multiples : correction des dates de début / fin affichées. Affichage de la période de l'ensemble des horaires. \ No newline at end of file diff --git a/library/Class/Article/EventTimingPeriod.php b/library/Class/Article/EventTimingPeriod.php new file mode 100644 index 00000000000..47f328c7eaf --- /dev/null +++ b/library/Class/Article/EventTimingPeriod.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_Article_EventTimingPeriod { + protected + $_article; + + public function __construct($article) { + $this->_article = $article; + } + + + public function startEndDo($callback) { + if (!Class_AdminVar::get('ENABLE_ARTICLES_TIMINGS', 1)) + return $this; + + $timings = $this->_article->getEventTimings(); + if (count($timings) < 2) + return $this; + + $start = strtotime($timings[0]->getStart()); + $end = strtotime(end($timings)->getEnd()); + + if (date('Ymd', $start) == date('Ymd', $end)) + return $this; + + $callback($start, $end); + return $this; + } +} diff --git a/library/Class/Article/SelectWithTimings.php b/library/Class/Article/SelectWithTimings.php index 2ca761cab01..4c7f2b42649 100644 --- a/library/Class/Article/SelectWithTimings.php +++ b/library/Class/Article/SelectWithTimings.php @@ -28,7 +28,7 @@ class Class_Article_SelectWithTimings extends Class_Article_Select { $this->_select ->joinLeft('cms_article_timings', 'cms_article.id_article=cms_article_timings.article_id', - ['start', 'end']) + ['min(cms_article_timings.start) as start', 'min(cms_article_timings.end) as end']) ->group('id_article'); return $this; } diff --git a/library/ZendAfi/View/Helper/Article/RenderAbstract.php b/library/ZendAfi/View/Helper/Article/RenderAbstract.php index b99f325c0f6..afae61839bd 100644 --- a/library/ZendAfi/View/Helper/Article/RenderAbstract.php +++ b/library/ZendAfi/View/Helper/Article/RenderAbstract.php @@ -29,7 +29,8 @@ abstract class ZendAfi_View_Helper_Article_RenderAbstract . $this->renderTitreHeader($article) . $this->renderDraftStatus($article) . $this->renderArticleInfo($article) - . $this->tagArticleEvent($article)) + . $this->tagArticleEvent($article) + . $this->renderEventPeriod($article)) . $this->_tag('div', $this->renderContent($article), ['class' => 'article_content']) . $this->_tag('footer', @@ -150,4 +151,21 @@ abstract class ZendAfi_View_Helper_Article_RenderAbstract public function renderTimings($article) { return ''; } + + + public function renderEventPeriod($article) { + $content = ''; + + (new Class_Article_EventTimingPeriod($article)) + ->startEndDo( + function($start, $end) use (&$content) { + $content = $this->view->tag('span', + implode(' - ', + [strftime('%d %B', $start), + strftime('%d %B', $end)]), + ['class' => 'calendar_event_period']); + }); + + return $content; + } } diff --git a/library/templates/Intonation/Library/View/Wrapper/Article.php b/library/templates/Intonation/Library/View/Wrapper/Article.php index 250ce04f6a0..d6ea3d4c3bc 100644 --- a/library/templates/Intonation/Library/View/Wrapper/Article.php +++ b/library/templates/Intonation/Library/View/Wrapper/Article.php @@ -290,6 +290,16 @@ class Intonation_Library_View_Wrapper_Article extends Intonation_Library_View_Wr ->setTag('span') ->setText($this->_eventsText($end)) ->setClass('badge_event_end'); + + + $period = new Class_Article_EventTimingPeriod($this->_model); + $period->startEndDo(function($start, $end) use (&$badges) { + $badges []= (new Intonation_Library_Badge) + ->setTag('span') + ->setText(strftime('%d %B', $start) . ' - ' . strftime('%d %B', $end)) + ->setClass('badge_event_period'); + }); + return $badges; } diff --git a/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsCalendarTest.php b/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsCalendarTest.php index 54f2d6ba7f3..52fc2e702b8 100644 --- a/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsCalendarTest.php +++ b/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsCalendarTest.php @@ -19,9 +19,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -class ArticlesMultipleTimingsCalendarTest extends ViewHelperTestCase { -protected $_storm_default_to_volatile = true; +abstract class ArticlesMultipleTimingsCalendarTestCase extends AbstractControllerTestCase { + protected $_storm_default_to_volatile = true; public function setUp() { @@ -70,6 +69,28 @@ protected $_storm_default_to_volatile = true; $apero_timing_two]]); + $dessert = Class_Article::newInstance(['id' => 2, + 'titre' => 'Dessert', + 'events_debut' => '2021-06-12 09:00']); + + $digeo = Class_Article::newInstance(['id' => 3, + 'titre' => 'Digeo', + 'description' => 'Calendar should not display calendar event period when timings on same day', + 'events_debut' => '2021-06-13 21:00', + 'events_fin' => '2021-06-13 22:00', + 'event_timings' => [ + $this->fixture(Class_Article_EventTiming::class, + ['id' => 4, + 'start' => '2021-06-13 21:00:00', + 'end' => '2021-06-13 22:00:00']), + + $this->fixture(Class_Article_EventTiming::class, + ['id' => 5, + 'start' => '2021-06-13 23:00:00', + 'end' => '2021-06-13 23:30:00']) + ]]); + + $this->onLoaderOfModel(Class_Article::class) ->whenCalled('getArticlesByPreferences') ->with([ @@ -98,9 +119,8 @@ protected $_storm_default_to_volatile = true; 'event_end_after' => '', 'limit' => 3]) ->answers([$apero_second_fetch, - Class_Article::newInstance(['id' => 2, - 'titre' => 'Dessert', - 'events_debut' => '2021-06-12 09:00']) + $dessert, + $digeo ]) ->whenCalled('getArticlesByPreferences') @@ -113,27 +133,41 @@ protected $_storm_default_to_volatile = true; 'id_lieu' => '', 'custom_fields' => [], 'published' => true]) - ->answers([]) + ->answers([]); + + ZendAfi_View_Helper_CalendarContent::setTimeSource(new TimeSourceForTest('2021-06-01 09:00:00')); - ->beStrict(); + Class_AdminVar::set('TEMPLATING', 1); + Class_AdminVar::set('ENABLE_ARTICLES_TIMINGS', 1); + } +} - ZendAfi_View_Helper_CalendarContent::setTimeSource(new TimeSourceForTest('2021-06-01 09:00:00')); - $params = ['division' => '2', - 'type_module' => 'CALENDAR', - 'preferences' => ['titre' => 'Agenda']]; - $helper = new ZendAfi_View_Helper_Accueil_Calendar(2, $params); - $helper->setView(new ZendAfi_Controller_Action_Helper_View()); - $this->html = $helper->getBoite(); + +class ArticlesMultipleTimingsCalendarInHistoricTest extends ArticlesMultipleTimingsCalendarTestCase { + public function setUp() { + parent::setUp(); + + $profile = $this->fixture(Class_Profil::class, + ['id' => 34, + 'template' => 'Historic']) + ->beCurrentProfil(); + $profile_patcher = (new Class_Template_ProfilePatcher(null))->setProfile($profile); + $profile_patcher + ->addWidget(Class_Systeme_ModulesAccueil_Calendrier::CODE, + 2, + ['titre' => 'Agenda', + 'mode-affichage' => 'wall']); + + $this->dispatch('/'); } /** @test */ public function calendarShouldContainsOnlyOneArticleApero() { $this - ->assertXPathCount($this->html, - '//a[@class="calendar_event_title"][contains(@href, "cms/articleview/id/1")]', + ->assertXPathCount('//span[@class="title"]/a[contains(@href, "cms/articleview/id/1")]', 1); } @@ -141,26 +175,90 @@ protected $_storm_default_to_volatile = true; /** @test */ public function calendarShouldContainsArticleWithFirstEventsDebut2021_06_01() { $this - ->assertXPathContentContains($this->html, - '//span[@class="calendar_event_date"]', + ->assertXPathContentContains('//span[@class="calendar_event_date"]', 'mardi 01 juin 2021'); } /** @test */ - public function calendarShouldContainsTwoArticles() { + public function calendarShouldContainsThreeArticles() { $this - ->assertXPathCount($this->html, - '//a[@class="calendar_event_title"]', - 2); + ->assertXPathCount('//article', + 3); } /** @test */ public function calendarSecondArticleShouldBeDessert() { - $this - ->assertXPath($this->html, - '//a[@class="calendar_event_title"][contains(@href, "cms/articleview/id/2")]'); + $this + ->assertXPath('//span[@class="title"]/a[contains(@href, "cms/articleview/id/2")]'); + } + + + /** @test */ + public function articleAperoEventDataShouldContainsSpanCalendarEventPeriod_01Juin_10Juin() { + $this + ->assertXPathContentContains('//article[1]//span[@class="calendar_event_period"]', + '01 juin - 10 juin'); + } + + + /** @test */ + public function articleDessertEventDataShouldNotContainsSpanCalendarEventPeriod() { + $this + ->assertNotXPath('//article[2]//span[@class="calendar_event_period"]'); + } +} + + + + +class ArticlesMultipleTimingsCalendarInMuscleTest extends ArticlesMultipleTimingsCalendarTestCase { + public function setUp() { + parent::setUp(); + + $profile = $this->fixture(Class_Profil::class, + ['id' => 34, + 'template' => 'MUSCLE']) + ->beCurrentProfil(); + + $profile_patcher = (new Class_Template_ProfilePatcher(null))->setProfile($profile); + $profile_patcher + ->addWidget(Intonation_Library_Widget_Carousel_Agenda_Definition::CODE, + Class_Profil::DIV_MAIN, + ['rendering' => 'card-description', + 'layout' => 'wall', + 'size' => 3]); + + $this->dispatch('/'); + } + + + /** @test */ + public function articleAperoEventDataShouldContainsBadgeEventPeriod_01Juin_10Juin() { + $this + ->assertXPathContentContains('//div[@class="masonry-brick"][1]//span[contains(@class,"badge_event_period")]', + '01 juin - 10 juin'); + } + + + /** @test */ + public function articleAperoEventDataShouldNotContainsSpanCalendarEventPeriod() { + $this + ->assertNotXPath('//span[@class="calendar_event_period"]'); + } + + + /** @test */ + public function divCardTitleShouldContainsArticleDigeo() { + $this->assertXPathContentContains('//div[contains(@class, "card-title")]/a', 'Digeo'); + } + + + /** @test */ + public function onlyOneArticleShouldContainsSpanCalendarEventPeriod() { + $this + ->assertXPathCount('//span[contains(@class,"badge_event_period")]', 1); } } diff --git a/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsLoaderTest.php b/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsLoaderTest.php index 884846da7f9..91db60b3963 100644 --- a/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsLoaderTest.php +++ b/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsLoaderTest.php @@ -53,7 +53,7 @@ class ArticlesMultipleTimingsLoaderTest extends ArticleLoaderGetArticlesByPrefer public function assertSelect($expected) { - $this->assertEquals("SELECT `cms_article`.*, `cms_article_timings`.`start`, `cms_article_timings`.`end` FROM `cms_article` ".$expected, + $this->assertEquals("SELECT `cms_article`.*, min(cms_article_timings.start) AS `start`, min(cms_article_timings.end) AS `end` FROM `cms_article` ".$expected, str_replace("\n", "", $this->select->assemble())); } -- GitLab