Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/config/packages/backoffice_menu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ parameters:
- admin_event_themes_list
- admin_event_themes_add
- admin_event_themes_edit
admin_event_editorialization:
nom: 'Éditorialisation'
niveau: 'ROLE_FORUM'
url: '/admin/event/editorialization'
extra_routes:
- admin_event_editorialization
forum_vote_github:
nom: 'Votes visiteurs'
niveau: 'ROLE_FORUM'
Expand Down
5 changes: 5 additions & 0 deletions app/config/routing/admin_event.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,5 +206,10 @@ admin_event_themes_list:
defaults:
_controller: AppBundle\Controller\Admin\Event\EventThemeAction

admin_event_editorialization:
path: /editorialization/
defaults:
_controller: AppBundle\Controller\Admin\Event\EventEditorializationAction

admin_event_ticket:
resource: "admin_event_ticket.yml"
17 changes: 17 additions & 0 deletions db/migrations/20260708090000_add_position_to_talks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class AddPositionToTalks extends AbstractMigration
{
public function change(): void
{
$this
->table('afup_sessions')
->addColumn('position', 'integer', ['null' => true])
->save()
;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php

declare(strict_types=1);

namespace AppBundle\Controller\Admin\Event;

use AppBundle\Event\AdminEventSelection;
use AppBundle\Event\Model\Event;
use AppBundle\Event\Model\Repository\EventThemeRepository;
use AppBundle\Event\Model\Repository\TalkRepository;
use AppBundle\Event\Model\Talk;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class EventEditorializationAction extends AbstractController
{
public function __construct(
private readonly EventThemeRepository $eventThemeRepository,
private readonly TalkRepository $talkRepository,
) {}

public function __invoke(Request $request, AdminEventSelection $eventSelection): Response
{
$event = $eventSelection->event;

if ($request->isXmlHttpRequest()) {
return $this->handleAjaxRequest($request, $event);
}

$eventId = $event->getId() ?? 0;
$hasThemes = $event->getHasThemes();
$themes = $hasThemes ? iterator_to_array($this->eventThemeRepository->getByThemesOrderedByPriority($eventId)) : [];
$scheduledTalks = iterator_to_array($this->talkRepository->getScheduledTalksByEvent($eventId));

$talkGroups = $this->groupTalks($scheduledTalks, $themes, $hasThemes);

return $this->render('admin/event/editorialization.html.twig', [
'event' => $event,
'event_select_form' => $eventSelection->selectForm(),
'has_themes' => $hasThemes,
'themes' => $themes,
'talk_groups' => $talkGroups,
]);
}

/**
* @param array<Talk> $scheduledTalks
* @param array<\AppBundle\Event\Model\EventTheme> $themes
* @return array<array{theme: ?\AppBundle\Event\Model\EventTheme, talks: array<Talk>}>
*/
private function groupTalks(array $scheduledTalks, array $themes, bool $hasThemes): array
{
if (!$hasThemes) {
$talks = $scheduledTalks;
usort($talks, $this->compareTalks(...));

return [['theme' => null, 'talks' => $talks]];
}

$talksByThemeId = [];
foreach ($themes as $theme) {
$talksByThemeId[(int) $theme->getId()] = [];
}

$noThemeTalks = [];
foreach ($scheduledTalks as $talk) {
$themeId = $talk->getTheme();
if ($themeId !== null && isset($talksByThemeId[$themeId])) {
$talksByThemeId[$themeId][] = $talk;
} else {
$noThemeTalks[] = $talk;
}
}

usort($noThemeTalks, $this->compareTalks(...));
$groups = [['theme' => null, 'talks' => $noThemeTalks]];

foreach ($themes as $theme) {
$talks = $talksByThemeId[(int) $theme->getId()];
usort($talks, $this->compareTalks(...));
$groups[] = ['theme' => $theme, 'talks' => $talks];
}

return $groups;
}

private function compareTalks(Talk $a, Talk $b): int
{
$positionA = $a->getPosition();
$positionB = $b->getPosition();

if ($positionA !== $positionB) {
if ($positionA === null) {
return 1;
}
if ($positionB === null) {
return -1;
}

return $positionA <=> $positionB;
}

return $a->getTitle() <=> $b->getTitle();
}

private function handleAjaxRequest(Request $request, Event $event): JsonResponse
{
$action = $request->request->get('action');

return match ($action) {
'update_talk_theme' => $this->updateTalkTheme($request),
'update_talk_position' => $this->updateTalkPosition($request),
default => new JsonResponse(['error' => 'Action non reconnue'], 400),
};
}

private function updateTalkTheme(Request $request): JsonResponse
{
$talkId = $request->request->getInt('talk_id');
$themeId = $request->request->get('theme_id');

$talk = $this->talkRepository->get($talkId);
if (!$talk) {
return new JsonResponse(['error' => 'Conférence non trouvée'], 404);
}

$talk->setTheme($themeId ? (int) $themeId : null);
$this->talkRepository->save($talk);

return new JsonResponse(['success' => true]);
}

private function updateTalkPosition(Request $request): JsonResponse
{
$talkId = $request->request->getInt('talk_id');
$position = $request->request->get('position');

$talk = $this->talkRepository->get($talkId);
if (!$talk) {
return new JsonResponse(['error' => 'Conférence non trouvée'], 404);
}

$talk->setPosition($position === null || $position === '' ? null : (int) $position);
$this->talkRepository->save($talk);

return new JsonResponse(['success' => true]);
}
}
25 changes: 1 addition & 24 deletions sources/AppBundle/Controller/Admin/Event/EventThemeAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,14 @@
use AppBundle\Event\AdminEventSelection;
use AppBundle\Event\Model\Event;
use AppBundle\Event\Model\Repository\EventThemeRepository;
use AppBundle\Event\Model\Repository\TalkRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class EventThemeAction extends AbstractController
{
public function __construct(
private readonly EventThemeRepository $eventThemeRepository,
private readonly TalkRepository $talkRepository,
) {}
public function __construct(private readonly EventThemeRepository $eventThemeRepository) {}

public function __invoke(Request $request, AdminEventSelection $eventSelection): Response
{
Expand All @@ -42,11 +38,9 @@ public function __invoke(Request $request, AdminEventSelection $eventSelection):

$eventId = $event->getId() ?? 0;
$themes = $this->eventThemeRepository->getByThemesOrderedByPriority($eventId);
$scheduledTalks = $this->talkRepository->getScheduledTalksByEvent($eventId);

return $this->render('admin/event/theme_list.html.twig', [
'themes' => $themes,
'scheduled_talks' => $scheduledTalks,
'event' => $event,
'event_select_form' => $eventSelection->selectForm(),
]);
Expand All @@ -58,7 +52,6 @@ private function handleAjaxRequest(Request $request, Event $event): JsonResponse

return match ($action) {
'update_theme_priority' => $this->updateThemePriority($request),
'update_talk_theme' => $this->updateTalkTheme($request),
default => new JsonResponse(['error' => 'Action non reconnue'], 400),
};
}
Expand All @@ -78,20 +71,4 @@ private function updateThemePriority(Request $request): JsonResponse

return new JsonResponse(['success' => true]);
}

private function updateTalkTheme(Request $request): JsonResponse
{
$talkId = $request->request->getInt('talk_id');
$themeId = $request->request->get('theme_id');

$talk = $this->talkRepository->get($talkId);
if (!$talk) {
return new JsonResponse(['error' => 'Conférence non trouvée'], 404);
}

$talk->setTheme($themeId ? (int) $themeId : null);
$this->talkRepository->save($talk);

return new JsonResponse(['success' => true]);
}
}
9 changes: 7 additions & 2 deletions sources/AppBundle/Event/Model/Repository/TalkRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public function getByEventsWithSpeakers(array $events, bool $applyPublicationdat

$query = $this->getPreparedQuery(
sprintf('SELECT talk.id_forum, talk.session_id, titre, skill, talk.genre, abstract, talk.plannifie, talk.language_code,
talk.joindin, talk.theme,
talk.joindin, talk.theme, talk.position,
speaker.conferencier_id, speaker.nom, speaker.prenom, speaker.id_forum, speaker.photo, speaker.societe,
planning.id, planning.debut, planning.fin, room.id, room.nom
FROM afup_sessions AS talk
Expand All @@ -293,7 +293,7 @@ public function getByEventsWithSpeakers(array $events, bool $applyPublicationdat
LEFT JOIN afup_forum_salle room ON planning.id_salle = room.id
LEFT JOIN afup_conference_theme ON afup_conference_theme.id = talk.theme
WHERE talk.id_forum IN(%s) AND plannifie = 1 %s %s
ORDER BY %s ', $inEvents, $publicationdateFilters, $themeFilters, $orderByTheme ? 'afup_conference_theme.priority ASC, afup_conference_theme.name ASC' : 'planning.debut ASC, room.id ASC, talk.date_publication DESC, talk.session_id ASC '),
ORDER BY %s ', $inEvents, $publicationdateFilters, $themeFilters, $orderByTheme ? 'afup_conference_theme.priority ASC, afup_conference_theme.name ASC, talk.position IS NULL, talk.position ASC, talk.date_publication DESC, talk.session_id ASC' : 'talk.position IS NULL, talk.position ASC, planning.debut ASC, room.id ASC, talk.date_publication DESC, talk.session_id ASC '),
)->setParams($params);

$result = $query->query($this->getCollection($hydrator));
Expand Down Expand Up @@ -625,6 +625,11 @@ public static function initMetadata(SerializerFactoryInterface $serializerFactor
'fieldName' => 'theme',
'type' => 'int',
])
->addField([
'columnName' => 'position',
'fieldName' => 'position',
'type' => 'int',
])
;

return $metadata;
Expand Down
13 changes: 13 additions & 0 deletions sources/AppBundle/Event/Model/Talk.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class Talk implements NotifyPropertyInterface

private ?int $theme = null;

private ?int $position = null;

public function __construct()
{
$this->submittedOn = new \DateTime();
Expand Down Expand Up @@ -687,4 +689,15 @@ public function setTheme(?int $theme): void
$this->propertyChanged('theme', $this->theme, $theme);
$this->theme = $theme;
}

public function getPosition(): ?int
{
return $this->position;
}

public function setPosition(?int $position): void
{
$this->propertyChanged('position', $this->position, $position);
$this->position = $position;
}
}
Loading
Loading