commit
6ff54c0791
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Schedule\SculpinScheduleBundle;
|
||||
use App\Speakers\SculpinSpeakersBundle;
|
||||
use Sculpin\Bundle\SculpinBundle\HttpKernel\AbstractKernel;
|
||||
|
||||
|
@ -8,6 +9,7 @@ class SculpinKernel extends AbstractKernel
|
|||
protected function getAdditionalSculpinBundles(): array
|
||||
{
|
||||
return [
|
||||
SculpinScheduleBundle::class,
|
||||
SculpinSpeakersBundle::class,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -12,6 +12,66 @@ eventbrite:
|
|||
papercall:
|
||||
url: https://www.papercall.io/drupalcamp-bristol-2019
|
||||
|
||||
schedule:
|
||||
slots:
|
||||
- id: 1
|
||||
time: 8:30 am
|
||||
label: Registration and refreshments
|
||||
|
||||
- id: 2
|
||||
time: 9:00 am
|
||||
label: Welcome
|
||||
|
||||
- id: 3
|
||||
time: 9:10 am
|
||||
|
||||
- id: 4
|
||||
time: 10:00 am
|
||||
|
||||
- id: 5
|
||||
time: 10:30 am
|
||||
label: Refreshments
|
||||
|
||||
- id: 6
|
||||
time: 10:50 am
|
||||
|
||||
- id: 7
|
||||
time: 11:40 am
|
||||
|
||||
- id: 8
|
||||
time: 12:10 pm
|
||||
label: Lunch
|
||||
|
||||
- id: 9
|
||||
time: 1:10 pm
|
||||
|
||||
- id: 10
|
||||
time: 2:00 pm
|
||||
|
||||
- id: 11
|
||||
time: 2:15 pm
|
||||
|
||||
- id: 12
|
||||
time: 2:30 pm
|
||||
label: Refreshments
|
||||
|
||||
- id: 13
|
||||
time: 2:50 pm
|
||||
|
||||
- id: 14
|
||||
time: 3:05 pm
|
||||
|
||||
- id: 15
|
||||
time: 3:20 pm
|
||||
|
||||
- id: 16
|
||||
time: 4:10 pm
|
||||
label: Closing remarks
|
||||
|
||||
- id: 17
|
||||
time: 4:40 pm
|
||||
label: Drinks reception
|
||||
|
||||
tickets:
|
||||
available: true
|
||||
url: '%eventbrite.url%'
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\Speakers\\": "src/Speakers/src"
|
||||
"App\\Speakers\\": "src/Speakers/src",
|
||||
"App\\Schedule\\": "src/Schedule/src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
{
|
||||
title: 'Speakers',
|
||||
href: '/#speakers',
|
||||
active: page.layout in ['session', 'speaker'],
|
||||
active: page.layout == 'speaker',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
title: 'Schedule',
|
||||
href: '/schedule',
|
||||
active: page.url == '/schedule' or page.layout in ['session', 'speaker'],
|
||||
enabled: false,
|
||||
href: '/#schedule',
|
||||
active: page.url == '/schedule' or page.layout == 'session',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
title: 'Sponsor us',
|
||||
|
|
22
source/_includes/schedule.html.twig
Normal file
22
source/_includes/schedule.html.twig
Normal file
|
@ -0,0 +1,22 @@
|
|||
<section id="schedule" class="tw-bg-purple-800 tw-text-white tw-py-16">
|
||||
<div class="tw-max-w-xl tw-mx-auto tw-px-4 tw-text-center">
|
||||
<h2 class="tw-text-3xl md:tw-text-4xl">The Schedule</h2>
|
||||
|
||||
<ul class="tw-list-reset tw-overflow-hidden">
|
||||
{% for slot in slots %}
|
||||
{% set session = sessionInSlot(slot.id, sessions) %}
|
||||
<li class="tw-pt-4 lg:tw-pt-6 {{ loop.last ?: 'tw-pb-4 lg:tw-pb-6 tw-border-solid tw-border-0 tw-border-b tw-border-purple-400' }}">
|
||||
<span class="tw-flex tw-items-center tw-justify-between tw--mx-6">
|
||||
<span class="tw-px-6 tw-text-gray-200 tw-flex-1 tw-text-left">
|
||||
<span class="tw-block">{{ session.title|default(slot.label)|default('TBA') }}</span>
|
||||
{% if session.speakers %}
|
||||
<span class="tw-block tw-mt-1">{{ session.speakers|join(', ') }}</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="tw-px-6 tw-font-semibold">{{ slot.time }}</span>
|
||||
</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Doing good with Drupal
|
||||
speakers: [Matt Haworth]
|
||||
slot: 15
|
||||
use: [speakers]
|
||||
---
|
||||
More and more charities and campaigners are choosing Drupal to create websites that raise funds, find supporters and deliver content and services to those who need it most.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
title: The Real State of Drupal
|
||||
slot: 3
|
||||
speakers: [Dan McNamara]
|
||||
use: [speakers]
|
||||
---
|
||||
|
|
|
@ -3,7 +3,7 @@ layout: default
|
|||
twitter:
|
||||
url: https://twitter.com/drupalcampbris
|
||||
update_text: Early bird tickets are now available!
|
||||
use: [speakers]
|
||||
use: [sessions, speakers]
|
||||
---
|
||||
{% block content %}
|
||||
<main class="tw-bg-balloon tw-bg-center tw-bg-cover tw-flex tw-flex-col tw-flex-1">
|
||||
|
@ -43,4 +43,9 @@ use: [speakers]
|
|||
{% include 'front-speakers' with {
|
||||
speakers: data.speakers,
|
||||
} %}
|
||||
|
||||
{% include 'schedule' with {
|
||||
sessions: data.sessions,
|
||||
slots: site.schedule.slots,
|
||||
} %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: page
|
||||
title: Schedule
|
||||
use:
|
||||
- sessions
|
||||
---
|
||||
<ul>
|
||||
{% for session in data.sessions %}
|
||||
<li>
|
||||
<a href="{{ session.url }}">{{ session.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
4
src/Schedule/services.yml
Normal file
4
src/Schedule/services.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
services:
|
||||
App\Schedule\TwigExtension\ScheduleExtension:
|
||||
tags:
|
||||
- { name: twig.extension }
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App\Schedule\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
|
||||
class SculpinScheduleExtension extends Extension
|
||||
{
|
||||
public function load(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../'));
|
||||
$loader->load('services.yml');
|
||||
}
|
||||
}
|
30
src/Schedule/src/Model/Session.php
Normal file
30
src/Schedule/src/Model/Session.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Schedule\Model;
|
||||
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
class Session
|
||||
{
|
||||
private $data;
|
||||
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function getSlot(): int
|
||||
{
|
||||
return (int) $this->data['slot'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return $this->data['title'];
|
||||
}
|
||||
|
||||
public function getSpeakers(): Collection
|
||||
{
|
||||
return collect($this->data['speakers']);
|
||||
}
|
||||
}
|
9
src/Schedule/src/SculpinScheduleBundle.php
Normal file
9
src/Schedule/src/SculpinScheduleBundle.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace App\Schedule;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class SculpinScheduleBundle extends Bundle
|
||||
{
|
||||
}
|
29
src/Schedule/src/TwigExtension/ScheduleExtension.php
Normal file
29
src/Schedule/src/TwigExtension/ScheduleExtension.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Schedule\TwigExtension;
|
||||
|
||||
use App\Schedule\Model\Session;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
class ScheduleExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('sessionInSlot', [$this, 'getSessionInSlot']),
|
||||
];
|
||||
}
|
||||
|
||||
public function getSessionInSlot(int $slotId, array $sessions): ?Session
|
||||
{
|
||||
return collect($sessions)->map(function ($session): ?Session {
|
||||
return new Session($session);
|
||||
})->first(function (?Session $session) use ($slotId): bool {
|
||||
return $session->getSlot() == $slotId;
|
||||
});
|
||||
}
|
||||
}
|
38
src/Schedule/tests/ScheduleTest.php
Normal file
38
src/Schedule/tests/ScheduleTest.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace App\Tests\Schedule;
|
||||
|
||||
use App\Schedule\Model\Session;
|
||||
use App\Schedule\TwigExtension\ScheduleExtension;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ScheduleTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var \App\Schedule\TwigExtension\ScheduleExtension
|
||||
*/
|
||||
private $extension;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->extension = new ScheduleExtension();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function get_a_session_for_a_slot()
|
||||
{
|
||||
$sessions = [
|
||||
['title' => 'The Real State of Drupal', 'slot' => 4],
|
||||
['title' => 'Using Ansible for automation', 'slot' => 1],
|
||||
['title' => 'Introduction to Views', 'slot' => 3],
|
||||
['title' => 'Doing Good with Drupal', 'slot' => 2],
|
||||
];
|
||||
|
||||
$session = $this->extension->getSessionInSlot(3, $sessions);
|
||||
|
||||
$this->assertInstanceOf(Session::class, $session);
|
||||
$this->assertSame('Introduction to Views', $session->getTitle());
|
||||
}
|
||||
}
|
|
@ -28,9 +28,12 @@ class SpeakersExtension extends AbstractExtension
|
|||
*/
|
||||
public function getSessionSpeakers($session, array $speakers): array
|
||||
{
|
||||
return collect($speakers)->filter(function ($speaker) use ($session): bool {
|
||||
return collect($speakers)
|
||||
->filter(function ($speaker) use ($session): bool {
|
||||
return collect($session['speakers'])->contains($speaker['title']);
|
||||
})->values()->toArray();
|
||||
})
|
||||
->values()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,8 +46,11 @@ class SpeakersExtension extends AbstractExtension
|
|||
*/
|
||||
public function getSpeakerSessions($speaker, array $sessions): array
|
||||
{
|
||||
return collect($sessions)->filter(function ($session) use ($speaker): bool {
|
||||
return collect($sessions)
|
||||
->filter(function ($session) use ($speaker): bool {
|
||||
return collect($session['speakers'])->contains($speaker['title']);
|
||||
})->values()->toArray();
|
||||
})
|
||||
->values()
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue